{{this.tokenRecord.accessor}}
{{this.tokenRecord.secret}}
diff --git a/.changelog/15073.txt b/.changelog/15073.txt new file mode 100644 index 00000000000..bed479b4605 --- /dev/null +++ b/.changelog/15073.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: redirect users to Sign In should their tokens ever come back expired or not-found +``` diff --git a/ui/app/controllers/settings/tokens.js b/ui/app/controllers/settings/tokens.js index 7fe6df52fac..6a63e5a8dd8 100644 --- a/ui/app/controllers/settings/tokens.js +++ b/ui/app/controllers/settings/tokens.js @@ -25,6 +25,7 @@ export default class Tokens extends Controller { clearTokenProperties() { this.token.setProperties({ secret: undefined, + tokenNotFound: false, }); this.setProperties({ tokenIsValid: false, @@ -54,6 +55,7 @@ export default class Tokens extends Controller { tokenIsValid: true, tokenIsInvalid: false, }); + this.token.set('tokenNotFound', false); }, () => { this.set('token.secret', undefined); diff --git a/ui/app/models/token.js b/ui/app/models/token.js index 17937cc1ff5..47faeeabbb6 100644 --- a/ui/app/models/token.js +++ b/ui/app/models/token.js @@ -11,6 +11,11 @@ export default class Token extends Model { @attr('string') type; @hasMany('policy') policies; @attr() policyNames; + @attr('date') expirationTime; @alias('id') accessor; + + get isExpired() { + return this.expirationTime && this.expirationTime < new Date(); + } } diff --git a/ui/app/routes/application.js b/ui/app/routes/application.js index be815bd44c8..c4d60aec1b7 100644 --- a/ui/app/routes/application.js +++ b/ui/app/routes/application.js @@ -13,6 +13,7 @@ export default class ApplicationRoute extends Route { @service system; @service store; @service token; + @service router; queryParams = { region: { @@ -140,7 +141,17 @@ export default class ApplicationRoute extends Route { @action error(error) { if (!(error instanceof AbortError)) { - this.controllerFor('application').set('error', error); + if ( + error.errors?.any( + (e) => + e.detail === 'ACL token expired' || + e.detail === 'ACL token not found' + ) + ) { + this.router.transitionTo('settings.tokens'); + } else { + this.controllerFor('application').set('error', error); + } } } } diff --git a/ui/app/services/token.js b/ui/app/services/token.js index de591393c07..514c9b371be 100644 --- a/ui/app/services/token.js +++ b/ui/app/services/token.js @@ -12,9 +12,12 @@ import classic from 'ember-classic-decorator'; export default class TokenService extends Service { @service store; @service system; + @service router; aclEnabled = true; + tokenNotFound = false; + @computed get secret() { return window.localStorage.nomadTokenSecret; @@ -39,6 +42,9 @@ export default class TokenService extends Service { if (errors.find((error) => error === 'ACL support disabled')) { this.set('aclEnabled', false); } + if (errors.find((error) => error === 'ACL token not found')) { + this.set('tokenNotFound', true); + } return null; } }) diff --git a/ui/app/templates/settings/tokens.hbs b/ui/app/templates/settings/tokens.hbs index d95274ba10d..416fb1133c4 100644 --- a/ui/app/templates/settings/tokens.hbs +++ b/ui/app/templates/settings/tokens.hbs @@ -5,17 +5,43 @@
Tokens are stored client-side in local storage. This will persist your token across sessions. You can manually clear your token here.
+ {{#if this.tokenRecord.isExpired}} +Expired {{moment-from-now this.tokenRecord.expirationTime interval=1000}} ({{this.tokenRecord.expirationTime}})
+It may have expired, or been entered incorrectly.
+Tokens are stored client-side in local storage. This will persist your token across sessions. You can manually clear your token here.
+{{this.tokenRecord.accessor}}
{{this.tokenRecord.secret}}
{{this.tokenRecord.accessor}}
{{this.tokenRecord.secret}}
- {{#if policy.description}} - {{policy.description}} - {{else}} - No description - {{/if}} -
-{{policy.rules}}
+ + {{#if policy.description}} + {{policy.description}} + {{else}} + No description + {{/if}} +
+{{policy.rules}}
+