From 3361aa180048b73b359fc6dfe8344735d7847482 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Mon, 29 Mar 2021 19:24:21 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20make/remove=20prim?= =?UTF-8?q?ary=20to=20auth=20method=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/core/addon/decorators/confirm.js | 4 +-- addons/core/translations/resources/en-us.yaml | 12 +++++---- .../app/routes/scopes/scope/auth-methods.js | 8 ++++-- ui/admin/app/templates/application.hbs | 2 +- .../scopes/scope/auth-methods/index.hbs | 25 +++++++++++++++++++ .../tests/acceptance/auth-methods-test.js | 24 ++++++++++++++++++ 6 files changed, 65 insertions(+), 10 deletions(-) diff --git a/addons/core/addon/decorators/confirm.js b/addons/core/addon/decorators/confirm.js index 5ae4c28df..46e337cd6 100644 --- a/addons/core/addon/decorators/confirm.js +++ b/addons/core/addon/decorators/confirm.js @@ -5,7 +5,7 @@ import { getOwner } from '@ember/application'; * confirmation via the confirmation service. If the user accepts, the * original method is executed. If the user denies, it is not. */ -export function confirm(confirmationTextKey) { +export function confirm(confirmationTextKey, options) { return function (_target, _propertyKey, desc) { const method = desc.value; desc.value = function () { @@ -15,7 +15,7 @@ export function confirm(confirmationTextKey) { const text = intl.t(confirmationTextKey); return ( confirmService - .confirm(text) + .confirm(text, options) // If user confirmed, execute the decorated method .then(() => method.apply(this, arguments)) // If the user denied, gracefully handle promise rejection with no-op diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index 0ac406a25..2ff67fd59 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -16,7 +16,7 @@ account: auth-method: title: Auth Method title_plural: Auth Methods - description: Auth methods govern how an org's users can login to Boundary. Boundary’s default auth method is username & passwords. + description: Auth methods enable authentication within a scope. The primary auth method within a scope auto-creates users on their first authentication attempt. messages: welcome: title: Welcome to Auth Methods @@ -25,8 +25,8 @@ auth-method: title: No Auth Methods description: No auth methods were found for this scope. no-primary-auth-method: - title: No Primary Auth Method Found - description: A primary auth method auto-vivifies users when they authenticate for the first time. The primary auth method is also presented first to unauthenticated users. Each scope may have one primary auth method. Please choose a primary auth method for this scope. + title: "Recommendation: Select a Primary Auth Method" + description: A primary auth method auto-creates users when they authenticate for the first time. Scopes without primary auth methods may experience authentication failures. types: password: Password actions: @@ -38,8 +38,10 @@ auth-method: make-primary-success: Auth method successfully elected to primary. remove-as-primary-success: Auth method successfully removed as primary. questions: - make-primary-confirm: Are you sure you want to elect this auth method to primary? - remove-as-primary-confirm: Are you sure you want to remove as primary this auth method? A primary auth method is recommended for every scope. + make-primary: Make primary auth method? + remove-as-primary: Remove primary auth method? + make-primary-confirm: "A primary auth method auto-creates users on their first authentication attempt if needed. Note: if you change the primary auth method, the previous primary will no longer auto-create users." + remove-as-primary-confirm: Removing the primary auth method may lead to authentication failures for this scope. group: title: Group title_plural: Groups diff --git a/ui/admin/app/routes/scopes/scope/auth-methods.js b/ui/admin/app/routes/scopes/scope/auth-methods.js index 9767b3586..291a9573d 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods.js @@ -87,7 +87,9 @@ export default class ScopesScopeAuthMethodsRoute extends Route { */ @action @loading - @confirm('resources.auth-method.questions.make-primary-confirm') + @confirm('resources.auth-method.questions.make-primary-confirm', { + title: 'resources.auth-method.questions.make-primary', + }) @notifyError(({ message }) => message, { catch: true }) @notifySuccess('resources.auth-method.notifications.make-primary-success') async makePrimary({ id }) { @@ -112,7 +114,9 @@ export default class ScopesScopeAuthMethodsRoute extends Route { */ @action @loading - @confirm('resources.auth-method.questions.remove-as-primary-confirm') + @confirm('resources.auth-method.questions.remove-as-primary-confirm', { + title: 'resources.auth-method.questions.remove-as-primary', + }) @notifyError(({ message }) => message, { catch: true }) @notifySuccess( 'resources.auth-method.notifications.remove-as-primary-success' diff --git a/ui/admin/app/templates/application.hbs b/ui/admin/app/templates/application.hbs index 2b9175a76..710575f9c 100644 --- a/ui/admin/app/templates/application.hbs +++ b/ui/admin/app/templates/application.hbs @@ -113,7 +113,7 @@ {{else}} {{t 'form.id.label'}} {{#if (feature-flag 'primary-auth-method')}} + {{t 'titles.actions'}} {{/if}} @@ -87,6 +88,30 @@ {{/if}} + + + {{#unless authMethod.isPrimary}} + + {{t 'resources.auth-method.actions.make-primary'}} + + {{/unless}} + {{#if authMethod.isPrimary}} + + {{t 'resources.auth-method.actions.remove-as-primary'}} + + {{/if}} + + {{/if}} {{/each}} diff --git a/ui/admin/tests/acceptance/auth-methods-test.js b/ui/admin/tests/acceptance/auth-methods-test.js index e6ffacb4d..5c46e1353 100644 --- a/ui/admin/tests/acceptance/auth-methods-test.js +++ b/ui/admin/tests/acceptance/auth-methods-test.js @@ -361,4 +361,28 @@ module('Acceptance | auth methods', function (hooks) { ); assert.ok(find('.rose-notification')); }); + + test('user can make and remove primary auth methods from index', async function (assert) { + assert.expect(3); + assert.notOk( + instances.scopes.org.primaryAuthMethodId, + 'Primary auth method is not yet set.' + ); + enableFeature('primary-auth-method'); + await visit(urls.authMethods); + await click( + '.rose-table-body .rose-table-row:first-child .rose-dropdown-content [type="button"]:first-child' + ); + let scope = this.server.schema.scopes.find(instances.scopes.org.id); + assert.equal( + scope.primaryAuthMethodId, + instances.authMethod.id, + 'Primary auth method is set.' + ); + await click( + '.rose-table-body .rose-table-row:first-child .rose-dropdown-content [type="button"]:first-child' + ); + scope = this.server.schema.scopes.find(instances.scopes.org.id); + assert.notOk(scope.primaryAuthMethodId, 'Primary auth method is unset.'); + }); });