Skip to content

Commit 910ac64

Browse files
committed
Auto merge of #4357 - Turbo87:api-tokens, r=locks
Improve "API Tokens" settings page ## Before <img width="994" alt="Bildschirmfoto 2021-12-23 um 22 33 02" src="https://user-images.githubusercontent.com/141300/147293184-03d219c1-78d0-422c-a757-e2cd0f4a07b4.png"> ## After <img width="1009" alt="Bildschirmfoto 2021-12-23 um 22 29 46" src="https://user-images.githubusercontent.com/141300/147293188-496db36d-f1e7-455c-8de4-e7c8a42c3e4b.png"> <img width="994" alt="Bildschirmfoto 2021-12-23 um 22 30 14" src="https://user-images.githubusercontent.com/141300/147293185-66288d5d-239f-4666-b82c-5fa767844171.png"> Closes #3915
2 parents 3049692 + 370f23d commit 910ac64

File tree

5 files changed

+264
-115
lines changed

5 files changed

+264
-115
lines changed
Lines changed: 103 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div local-class="me-subheading">
2-
<h2>API Access</h2>
2+
<h2>API Tokens</h2>
33
<div local-class="right">
44
<button
55
type="button"
@@ -13,93 +13,120 @@
1313
</div>
1414
</div>
1515

16-
<p>
17-
If you want to use package commands from the command line, you will need to
18-
login with <code>cargo login (token)</code> using one of the tokens listed below.
16+
<p local-class="explainer">
17+
You can use the API tokens on this page to run <a href="https://doc.rust-lang.org/cargo/">cargo</a>
18+
commands that need write access to crates.io. If you want to publish your own
19+
crates then this is required.
1920
</p>
20-
<p>
21-
When working in shared environments, supplying the token on the command line could
22-
expose it to prying eyes. To avoid this, enter <code>cargo login</code> and supply your
23-
token when prompted.
21+
22+
<p local-class="explainer">
23+
Run <a href="https://doc.rust-lang.org/cargo/commands/cargo-login.html"><code>cargo login</code></a>
24+
on the command line to save the API token that you will use for local
25+
development. For CI systems you can use the
26+
<a href="https://doc.rust-lang.org/cargo/reference/config.html?highlight=CARGO_REGISTRY_TOKEN#credentials"><code>CARGO_REGISTRY_TOKEN</code></a>
27+
environment variable, but make sure that the token stays secret!
2428
</p>
2529

26-
<div local-class="token-list">
27-
{{#if this.newToken}}
28-
<form local-class="row create-token" {{on "submit" (prevent-default (perform this.saveTokenTask))}}>
29-
<div local-class="name">
30-
<Input
31-
@type="text"
32-
placeholder="New token name"
33-
aria-label="New token name"
34-
disabled={{this.newToken.isSaving}}
35-
@value={{this.newToken.name}}
36-
data-test-focused-input
37-
{{auto-focus}}
38-
/>
39-
</div>
30+
{{#if this.newToken}}
31+
<form local-class="new-token-form" {{on "submit" (prevent-default (perform this.saveTokenTask))}}>
32+
<Input
33+
@type="text"
34+
placeholder="New token name"
35+
aria-label="New token name"
36+
disabled={{this.newToken.isSaving}}
37+
@value={{this.newToken.name}}
38+
local-class="input"
39+
data-test-focused-input
40+
{{auto-focus}}
41+
/>
4042

41-
<div local-class="actions">
42-
<button
43-
type="submit"
44-
local-class="save-button"
45-
disabled={{or this.newToken.isSaving (not this.newToken.name)}}
46-
title={{unless this.newToken.name "You must specify a name"}}
47-
data-test-save-token-button
48-
>
49-
Create
50-
</button>
51-
{{#if this.newToken.isSaving}}
52-
<LoadingSpinner local-class="spinner" data-test-saving-spinner />
53-
{{/if}}
54-
</div>
55-
</form>
56-
{{/if}}
43+
<div local-class="actions">
44+
<button
45+
type="submit"
46+
local-class="save-button"
47+
disabled={{or this.newToken.isSaving (not this.newToken.name)}}
48+
title={{unless this.newToken.name "You must specify a name"}}
49+
data-test-save-token-button
50+
>
51+
Create
52+
</button>
53+
{{#if this.newToken.isSaving}}
54+
<LoadingSpinner local-class="spinner" data-test-saving-spinner />
55+
{{/if}}
56+
</div>
57+
</form>
58+
{{/if}}
5759

58-
{{#each this.sortedTokens as |token|}}
59-
<div local-class="row" data-test-api-token={{token.id}}>
60-
<div local-class="name" data-test-name>
61-
{{token.name}}
62-
</div>
60+
{{#if this.sortedTokens}}
61+
<ul role="list" local-class="token-list">
62+
{{#each this.sortedTokens as |token|}}
63+
<li local-class="row" data-test-api-token={{or token.id true}}>
64+
<h3 local-class="name" data-test-name>
65+
{{token.name}}
66+
</h3>
6367

64-
<div local-class="dates">
65-
<span title={{token.created_at}} local-class="created-at" data-test-created-at>
66-
Created {{date-format-distance-to-now token.created_at addSuffix=true}}
67-
</span>
68-
<span title={{token.last_used_at}} local-class="last-used-at" data-test-last-used-at>
68+
<div title={{token.last_used_at}} local-class="last-used-at" data-test-last-used-at>
6969
{{#if token.last_used_at}}
7070
Last used {{date-format-distance-to-now token.last_used_at addSuffix=true}}
7171
{{else}}
7272
Never used
7373
{{/if}}
74-
</span>
75-
</div>
74+
</div>
7675

77-
<div local-class="actions">
78-
<button
79-
type="button"
80-
local-class="revoke-button"
81-
disabled={{token.isSaving}}
82-
data-test-revoke-token-button
83-
{{on "click" (perform this.revokeTokenTask token)}}
84-
>
85-
Revoke
86-
</button>
87-
{{#if token.isSaving}}
88-
<LoadingSpinner local-class="spinner" data-test-saving-spinner />
89-
{{/if}}
90-
</div>
91-
</div>
76+
<div title={{token.created_at}} local-class="created-at" data-test-created-at>
77+
Created {{date-format-distance-to-now token.created_at addSuffix=true}}
78+
</div>
9279

93-
{{#if token.token}}
94-
<div local-class="row new-token" data-test-token>
95-
<div>
96-
Please record this token somewhere, you cannot retrieve
97-
its value again. For use on the command line you can save it to <code>~/.cargo/credentials</code>
98-
with:
80+
{{#if token.token}}
81+
<div local-class="new-token">
82+
<div local-class="new-token-explainer">
83+
Make sure to copy your API token now. You won’t be able to see it again!
84+
</div>
85+
86+
<div local-class="token-display">
87+
<span local-class="token-value" data-test-token>{{token.token}}</span>
88+
89+
{{#if (is-clipboard-supported)}}
90+
<CopyButton @copyText={{token.token}} local-class="copy-button">
91+
<span local-class="copy-button-label">Copy</span>
92+
{{svg-jar "copy" aria-hidden="true" local-class="copy-button-icon"}}
93+
</CopyButton>
94+
{{/if}}
95+
</div>
96+
</div>
97+
{{/if}}
9998

100-
<pre class="terminal">cargo login {{token.token}}</pre>
99+
<div local-class="actions">
100+
<button
101+
type="button"
102+
local-class="revoke-button"
103+
disabled={{token.isSaving}}
104+
data-test-revoke-token-button
105+
{{on "click" (perform this.revokeTokenTask token)}}
106+
>
107+
Revoke
108+
</button>
109+
{{#if token.isSaving}}
110+
<LoadingSpinner local-class="spinner" data-test-saving-spinner />
111+
{{/if}}
101112
</div>
102-
</div>
103-
{{/if}}
104-
{{/each}}
105-
</div>
113+
</li>
114+
{{/each}}
115+
</ul>
116+
{{else}}
117+
<div local-class="empty-state">
118+
<div local-class="empty-state-label">
119+
You have not generated any API tokens yet.
120+
</div>
121+
122+
<button
123+
type="button"
124+
local-class="empty-state-button"
125+
disabled={{this.newToken}}
126+
data-test-empty-state-button
127+
{{on "click" this.startNewToken}}
128+
>
129+
New Token
130+
</button>
131+
</div>
132+
{{/if}}

app/components/settings/api-tokens.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ import Component from '@glimmer/component';
44
import { tracked } from '@glimmer/tracking';
55

66
import { task } from 'ember-concurrency';
7-
import { sortBy } from 'macro-decorators';
7+
import { filterBy, sortBy } from 'macro-decorators';
88

99
export default class ApiTokens extends Component {
1010
@service store;
1111
@service notifications;
1212

1313
@tracked newToken;
1414

15-
@sortBy('args.tokens', 'created_at', false) sortedTokens;
15+
@filterBy('args.tokens', 'isNew', false) filteredTokens;
16+
@sortBy('filteredTokens', 'created_at', false) sortedTokens;
1617

1718
@action startNewToken() {
1819
this.newToken = this.store.createRecord('api-token');

0 commit comments

Comments
 (0)