diff --git a/addons/api/addon/models/auth-method.js b/addons/api/addon/models/auth-method.js index 2c5b708ea..a0a8e1b27 100644 --- a/addons/api/addon/models/auth-method.js +++ b/addons/api/addon/models/auth-method.js @@ -2,5 +2,10 @@ import GeneratedAuthMethodModel from '../generated/models/auth-method'; import { equal } from '@ember/object/computed'; export default class AuthMethodModel extends GeneratedAuthMethodModel { + // =attributes + + /** + * @type {boolean} + */ @equal('primary', true) isPrimary; } diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 538df19de..243467bc7 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -66,8 +66,8 @@ export default function () { authMethod.destroy(); // If the primary auth method is deleted, the associated scope's // primary_auth_method_id field should be set to null. - if (scope.primary_auth_method_id === id) { - scope.update({ primary_auth_method_id: null }); + if (scope.primaryAuthMethodId === id) { + scope.update({ primaryAuthMethodId: null }); } return new Response(204); }); diff --git a/addons/api/mirage/scenarios/default.js b/addons/api/mirage/scenarios/default.js index b5a5c88d3..62018788c 100644 --- a/addons/api/mirage/scenarios/default.js +++ b/addons/api/mirage/scenarios/default.js @@ -34,8 +34,8 @@ export default function (server) { ); // Assign primary auth methods per scope // TODO make this generic - globalScope.update({ primary_auth_method_id: globalAuthMethods[0].id }); - orgScope.update({ primary_auth_method_id: orgAuthMethods[1].id }); + globalScope.update({ primaryAuthMethodId: globalAuthMethods[0].id }); + orgScope.update({ primaryAuthMethodId: orgAuthMethods[1].id }); // Groups and Users server.createList('group', 1, { scope: globalScope }, 'withMembers'); diff --git a/addons/api/mirage/serializers/auth-method.js b/addons/api/mirage/serializers/auth-method.js index 058487279..ecdcdf33c 100644 --- a/addons/api/mirage/serializers/auth-method.js +++ b/addons/api/mirage/serializers/auth-method.js @@ -10,9 +10,9 @@ export default ApplicationSerializer.extend({ ); // If the scope marks this auth method as primary, designate it // as such with a read-only boolean field (this is how the API behaves). - if (model.scope && model.scope.primary_auth_method_id === model.id) { - json.primary = true; - } + const isPrimary = + model.scope && model.scope.primaryAuthMethodId === model.id; + json.primary = isPrimary; return json; }, }); diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index 86d80732c..0ac406a25 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -32,6 +32,14 @@ auth-method: actions: create: Create Auth Method delete: Delete Auth Method + make-primary: Make Primary + remove-as-primary: Remove as Primary + notifications: + 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. 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 fe2f7905b..9767b3586 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods.js @@ -79,4 +79,55 @@ export default class ScopesScopeAuthMethodsRoute extends Route { await this.replaceWith('scopes.scope.auth-methods'); this.refresh(); } + + /** + * Elects the specified auth method to primary for the current scope. + * @param {AuthMethodModel} authMethod + * @param {string} authMethod.id + */ + @action + @loading + @confirm('resources.auth-method.questions.make-primary-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess('resources.auth-method.notifications.make-primary-success') + async makePrimary({ id }) { + const scopeModel = this.modelFor('scopes.scope'); + scopeModel.primary_auth_method_id = id; + // Attempt to save the change to the scope. If this operation fails, + // we rollback the change and rethrow the error so the user can be notified. + try { + await scopeModel.save(); + } catch (e) { + scopeModel.rollbackAttributes(); + throw e; + } + await this.refresh(); + } + + /** + * Sets the `primary_auth_method_id` field to null for the current scope + * and saves it if and only if the specified auth method is in fact primary + * for the current scope. + * @param {AuthMethodModel} authMethod + */ + @action + @loading + @confirm('resources.auth-method.questions.remove-as-primary-confirm') + @notifyError(({ message }) => message, { catch: true }) + @notifySuccess( + 'resources.auth-method.notifications.remove-as-primary-success' + ) + async removeAsPrimary(authMethod) { + const scopeModel = this.modelFor('scopes.scope'); + scopeModel.primary_auth_method_id = null; + // Attempt to save the change to the scope. If this operation fails, + // we rollback the change and rethrow the error so the user can be notified. + try { + await scopeModel.save(); + } catch (e) { + scopeModel.rollbackAttributes(); + throw e; + } + await authMethod.reload(); + } } diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs index ddc511c68..d60954dfc 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs @@ -1,4 +1,22 @@ + {{#if (feature-flag 'primary-auth-method')}} + {{#unless @model.isPrimary}} + + {{t 'resources.auth-method.actions.make-primary'}} + + {{/unless}} + {{#if @model.isPrimary}} + + {{t 'resources.auth-method.actions.remove-as-primary'}} + + {{/if}} + {{/if}}