diff --git a/app/controllers/crate/version.js b/app/controllers/crate/version.js
index a0e07e25284..61e25c289f4 100644
--- a/app/controllers/crate/version.js
+++ b/app/controllers/crate/version.js
@@ -33,6 +33,11 @@ export default Controller.extend({
isOwner: computed('crate.owner_user', 'session.currentUser.id', function() {
return this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id'));
}),
+ notYankedOrIsOwner: computed('model', 'crate.owner_user', 'session.currentUser.id', function() {
+ return (
+ !this.get('model').yanked || this.get('crate.owner_user').findBy('id', this.get('session.currentUser.id'))
+ );
+ }),
sortedVersions: readOnly('crate.versions'),
diff --git a/app/templates/crate/version.hbs b/app/templates/crate/version.hbs
index ec02774604c..468747ddc07 100644
--- a/app/templates/crate/version.hbs
+++ b/app/templates/crate/version.hbs
@@ -43,254 +43,254 @@
Repository
{{/if}}
- {{#link-to 'crate.reverse-dependencies' (query-params dependency=crate.crate_id) data-test-reverse-deps-link=true}}
- Dependent crates
- {{/link-to}}
+ {{#link-to 'crate.reverse-dependencies' (query-params dependency=crate.crate_id) data-test-reverse-deps-link=true}}
+ Dependent crates
+ {{/link-to}}
-{{#if currentVersion.yanked}}
-
-
-
This crate has been yanked, but it is still available for download for
- other crates that may be depending on it.
-
You may wish to
- {{#link-to 'crate.versions' crate}}view all versions{{/link-to}} to find one that
- has not been yanked.
-
-
-
-{{else}}
-
-
Cargo.toml
-
{{ crate.name }} = "{{ currentVersion.num }}"
-
- {{#if (is-clipboard-supported)}}
- {{#copy-button clipboardTarget="#crate-toml" success=(action 'copySuccess') error=(action 'copyError') title="Copy to clipboard"}}
- {{svg-jar "copy" alt="Copy to clipboard"}}
- {{/copy-button}}
- {{/if}}
-
-
-
-
- {{#if showNotification}}
- {{#if showSuccess}}
- Copied!
- {{else}}
- An error occured. Please use CTRL+C.
+ {{#if currentVersion.yanked}}
+
+ This crate has been yanked, but it is still available for download for other crates that
+ may be depending on it.
+
+
+ You may wish to {{#link-to 'crate.versions' crate}}view all versions{{/link-to}} to find
+ one that has not been yanked.
+
+ {{else}}
+
+
Cargo.toml
+
{{ crate.name }} = "{{ currentVersion.num }}"
+ {{#if (is-clipboard-supported)}}
+ {{#copy-button clipboardTarget="#crate-toml" success=(action 'copySuccess') error=(action 'copyError') title="Copy to clipboard"}}
+ {{svg-jar "copy" alt="Copy to clipboard"}}
+ {{/copy-button}}
+ {{/if}}
+
+
+
+ {{#if showNotification}}
+ {{#if showSuccess}}
+ Copied!
+ {{else}}
+ An error occured. Please use CTRL+C.
+ {{/if}}
{{/if}}
+
+
+ {{#if crate.readme}}
+
+ {{crate-readme rendered=crate.readme}}
+
+ {{else}}
+ {{#if crate.description}}
+
+
About This Package
+
{{ crate.description }}
+
{{/if}}
-
-
- {{#if crate.readme}}
-
- {{crate-readme rendered=crate.readme}}
-
- {{else}}
- {{#if crate.description}}
-
-
About This Package
-
{{ crate.description }}
-
{{/if}}
{{/if}}
-
-
-
-
Last Updated
-
{{moment-from-now crate.updated_at}}
- {{#each crate.annotated_badges as |badge|}}
-
- {{component badge.component_name badge=badge}}
-
- {{/each}}
-
-
- {{#if currentVersion.crate_size}}
+ {{#if notYankedOrIsOwner}}
+
+
-
Crate Size
-
{{format-crate-size currentVersion.crate_size}}
-
- {{/if}}
-
-
-
Authors
-
- {{#each displayedAuthors as |author|}}
- - {{ format-email author.name }}
+ Last Updated
+ {{moment-from-now crate.updated_at}}
+ {{#each crate.annotated_badges as |badge|}}
+
+ {{component badge.component_name badge=badge}}
+
{{/each}}
-
-
-
-
-
- {{#if currentVersion.license}}
-
-
License
-
{{ currentVersion.license }}
- {{/if}}
- {{#unless crate.keywords.isPending}}
- {{#if anyKeywords}}
+ {{#if currentVersion.crate_size}}
-
Keywords
-
- {{#each keywords as |keyword|}}
- - {{link-to keyword.id 'keyword' keyword}}
- {{/each}}
-
+
Crate Size
+
{{format-crate-size currentVersion.crate_size}}
{{/if}}
- {{/unless}}
- {{#unless crate.categories.isPending}}
- {{#if anyCategories}}
+
+
Authors
+
+ {{#each displayedAuthors as |author|}}
+ - {{ format-email author.name }}
+ {{/each}}
+
+
+
+
+
+ {{#if currentVersion.license}}
-
Categories
-
- {{#each categories as |category|}}
- - {{link-to category.category 'category' category.slug}}
- {{/each}}
-
+
License
+
{{ currentVersion.license }}
{{/if}}
- {{/unless}}
-
-
Owners
+ {{#unless crate.keywords.isPending}}
+ {{#if anyKeywords}}
+
+
Keywords
+
+ {{#each keywords as |keyword|}}
+ - {{link-to keyword.id 'keyword' keyword}}
+ {{/each}}
+
+
+ {{/if}}
+ {{/unless}}
- {{#if isOwner}}
-
- {{#link-to 'crate.owners' crate}}
- Manage owners
- {{/link-to}}
-
- {{/if}}
+ {{#unless crate.categories.isPending}}
+ {{#if anyCategories}}
+
+
Categories
+
+ {{#each categories as |category|}}
+ - {{link-to category.category 'category' category.slug}}
+ {{/each}}
+
+
+ {{/if}}
+ {{/unless}}
-
- {{#each crate.owner_team as |team|}}
- -
- {{#link-to team.kind team.login data-test-team-link=team.login}}
- {{user-avatar user=team size='medium-small'}}
- {{/link-to}}
-
- {{/each}}
+
+
Owners
- {{#each crate.owner_user as |user|}}
- -
- {{#link-to user.kind user.login data-test-user-link=user.login}}
- {{user-avatar user=user size='medium-small'}}
- {{/link-to}}
-
- {{/each}}
-
-
-
-
-
Versions
-
- {{#each smallSortedVersions as |version|}}
- -
- {{#link-to 'crate.version' version.num data-test-version-link=version.num}}
- {{ version.num }}
- {{/link-to}}
- {{moment-format version.created_at 'll'}}
- {{#if version.yanked}}
- yanked
- {{/if}}
-
- {{/each}}
-
-
- {{#if hasMoreVersions}}
- {{#link-to 'crate.versions' crate data-test-all-versions-link=true}}
- show all {{ crate.versions.length }} versions
+ {{#if isOwner}}
+
+ {{#link-to 'crate.owners' crate}}
+ Manage owners
{{/link-to}}
+
{{/if}}
-
-
-
-
Dependencies
-
- {{#each currentDependencies as |dep|}}
- {{link-to-dep tagName="li" dep=dep}}
- {{else}}
- - None
+
+ {{#each crate.owner_team as |team|}}
+ -
+ {{#link-to team.kind team.login data-test-team-link=team.login}}
+ {{user-avatar user=team size='medium-small'}}
+ {{/link-to}}
+
+ {{/each}}
+
+ {{#each crate.owner_user as |user|}}
+ -
+ {{#link-to user.kind user.login data-test-user-link=user.login}}
+ {{user-avatar user=user size='medium-small'}}
+ {{/link-to}}
+
{{/each}}
-
+
- {{#if currentDevDependencies}}
-
-
Dev-Dependencies
+
+
Versions
- {{#each currentDevDependencies as |dep|}}
- {{link-to-dep tagName="li" dep=dep}}
+ {{#each smallSortedVersions as |version|}}
+ -
+ {{#link-to 'crate.version' version.num data-test-version-link=version.num}}
+ {{ version.num }}
+ {{/link-to}}
+ {{moment-format version.created_at 'll'}}
+ {{#if version.yanked}}
+ yanked
+ {{/if}}
+
{{/each}}
+
+ {{#if hasMoreVersions}}
+ {{#link-to 'crate.versions' crate data-test-all-versions-link=true}}
+ show all {{ crate.versions.length }} versions
+ {{/link-to}}
+ {{/if}}
+
- {{/if}}
-
-
+
+
+
Dependencies
+
+ {{#each currentDependencies as |dep|}}
+ {{link-to-dep tagName="li" dep=dep}}
+ {{else}}
+ - None
+ {{/each}}
+
+
+
+ {{#if currentDevDependencies}}
+
+
Dev-Dependencies
+
+ {{#each currentDevDependencies as |dep|}}
+ {{link-to-dep tagName="li" dep=dep}}
+ {{/each}}
+
+
+ {{/if}}
+
+
+ {{/if}}
-
-
-
Stats Overview
-
-
- {{svg-jar "download"}}
- {{ format-num downloadsContext.downloads }}
-
- Downloads all time
-
-
-
- {{svg-jar "crate"}}
- {{ crate.versions.length }}
-
-
Versions published
+{{#unless currentVersion.yanked}}
+
+
+
Stats Overview
+
+
+ {{svg-jar "download"}}
+ {{ format-num downloadsContext.downloads }}
+
+ Downloads all time
+
+
+
+ {{svg-jar "crate"}}
+ {{ crate.versions.length }}
+
+ Versions published
+
-
-
-
Showing stats for
+
+ Showing stats for
- {{#rl-dropdown-container class="button-holder"}}
- {{#rl-dropdown-toggle class="tan-button dropdown"}}
- {{#if requestedVersion}}
- {{ requestedVersion }}
- {{else}}
- All Versions
- {{/if}}
-
- {{/rl-dropdown-toggle}}
+ {{#rl-dropdown-container class="button-holder"}}
+ {{#rl-dropdown-toggle class="tan-button dropdown"}}
+ {{#if requestedVersion}}
+ {{ requestedVersion }}
+ {{else}}
+ All Versions
+ {{/if}}
+
+ {{/rl-dropdown-toggle}}
- {{#rl-dropdown id="all-versions" tagName="ul" class="dropdown" closeOnChildClick="a:link"}}
-
- {{#link-to 'crate.version' 'all'}}All Versions{{/link-to}}
-
- {{#each smallSortedVersions as |version|}}
-
- {{#link-to 'crate.version' version.num}}
- {{ version.num }}
- {{/link-to}}
+ {{#rl-dropdown id="all-versions" tagName="ul" class="dropdown" closeOnChildClick="a:link"}}
+
+ {{#link-to 'crate.version' 'all'}}All Versions{{/link-to}}
- {{/each}}
- {{/rl-dropdown}}
- {{/rl-dropdown-container}}
-
-
-
Downloads over the last 90 days
- {{download-graph data=downloadData}}
+ {{#each smallSortedVersions as |version|}}
+
+ {{#link-to 'crate.version' version.num}}
+ {{ version.num }}
+ {{/link-to}}
+
+ {{/each}}
+ {{/rl-dropdown}}
+ {{/rl-dropdown-container}}
+
+
+
Downloads over the last 90 days
+ {{download-graph data=downloadData}}
+
-
-{{/if}}
+{{/unless}}
diff --git a/tests/unit/controllers/crate/version-test.js b/tests/unit/controllers/crate/version-test.js
new file mode 100644
index 00000000000..df75dcffa13
--- /dev/null
+++ b/tests/unit/controllers/crate/version-test.js
@@ -0,0 +1,35 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+import { A } from '@ember/array';
+import Service from '@ember/service';
+
+module('Unit | Controller | crate/version', function(hooks) {
+ setupTest(hooks);
+ const userId = 1;
+ // stub the session service
+ // https://guides.emberjs.com/release/testing/testing-components/#toc_stubbing-services
+ const sessionStub = Service.extend();
+
+ hooks.beforeEach(function() {
+ sessionStub.currentUser = { id: userId };
+ this.owner.register('service:session', sessionStub);
+ });
+
+ test('notYankedOrIsOwner is true when conditions fulfilled', function(assert) {
+ assert.expect(2);
+ let controller = this.owner.lookup('controller:crate/version');
+ controller.model = { yanked: false };
+ controller.crate = { owner_user: A([{ id: userId }]) };
+ assert.ok(controller);
+ assert.ok(controller.notYankedOrIsOwner);
+ });
+
+ test('notYankedOrIsOwner is false when conditions fulfilled', function(assert) {
+ assert.expect(2);
+ let controller = this.owner.lookup('controller:crate/version');
+ controller.model = { yanked: true };
+ controller.crate = { owner_user: A([{ id: userId }]) };
+ assert.ok(controller);
+ assert.notOk(controller.notYankedOrIsOwner);
+ });
+});