diff --git a/addons/api/addon/models/auth-method.js b/addons/api/addon/models/auth-method.js index 66f34757d..8e6c4f198 100644 --- a/addons/api/addon/models/auth-method.js +++ b/addons/api/addon/models/auth-method.js @@ -4,7 +4,7 @@ import { fragment } from 'ember-data-model-fragments/attributes'; import { equal } from '@ember/object/computed'; /** - * Enum ptions per auth method type and field. + * Enum options per auth method type and field. */ export const options = { oidc: { @@ -75,6 +75,27 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel { return this.type === 'oidc'; } + /** + * @type {boolean} + */ + get isInactive() { + return this.attributes.state === 'inactive'; + } + + /** + * @type {boolean} + */ + get isPrivate() { + return this.attributes.state === 'active-private'; + } + + /** + * @type {boolean} + */ + get isPublic() { + return this.attributes.state === 'active-public'; + } + // =methods /** diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 769e7e810..007950f69 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -106,8 +106,9 @@ export default function () { } ); - // Authenticate/deauthenticate routes + // Authenticate + auth methods custom routes this.post('/auth-methods/:id_method', authHandler); + // Deauthenticate route this.post('/scopes/:id_method', deauthHandler); // IAM : Users diff --git a/addons/api/mirage/route-handlers/auth.js b/addons/api/mirage/route-handlers/auth.js index bd4fca7ac..6f9a51634 100644 --- a/addons/api/mirage/route-handlers/auth.js +++ b/addons/api/mirage/route-handlers/auth.js @@ -107,14 +107,34 @@ const commandHandlers = { }, }; +// Handles all custom methods on /auth-methods/:id route export function authHandler({ scopes, authMethods }, request) { - const payload = JSON.parse(request.requestBody); - const [, id] = request.params.id_method.match(/(?.[^:]*)/); - const { command } = payload; + const [, id, method] = request.params.id_method.match( + /(?.[^:]*):(?(.*))/ + ); const authMethod = authMethods.find(id); - const scope = scopes.find(authMethod.scopeId); - const scopeAttrs = this.serialize(scopes.find(scope.id)); - return commandHandlers[authMethod.type][command](payload, scopeAttrs); + + if (method === 'authenticate') { + const payload = JSON.parse(request.requestBody); + const { command } = payload; + const scope = scopes.find(authMethod.scopeId); + const scopeAttrs = this.serialize(scopes.find(scope.id)); + return commandHandlers[authMethod.type][command](payload, scopeAttrs); + } + + // TODO: this handler doesn't really belong here, but we already route + // POST requests on existing auth methods to this route handler file under the + // assumption it would be for authentication. While authentication should + // still occur here, we should handle other custom methods in the + // mirage config and route here only for auth. + if (method === 'change-state') { + const attrs = this.normalizedRequestAttrs(); + return authMethod.update({ + attributes: { + state: attrs.attributes.state, + }, + }); + } } export function deauthHandler() { diff --git a/addons/core/app/helpers/app-name.js b/addons/core/app/helpers/app-name.js index ee117ad2f..6caf08d2e 100644 --- a/addons/core/app/helpers/app-name.js +++ b/addons/core/app/helpers/app-name.js @@ -1 +1 @@ -export { default, appName } from 'core/helpers/app-name'; +export { default } from 'core/helpers/app-name'; diff --git a/addons/core/app/helpers/company-copyright.js b/addons/core/app/helpers/company-copyright.js index d76da80c8..c846d26c1 100644 --- a/addons/core/app/helpers/company-copyright.js +++ b/addons/core/app/helpers/company-copyright.js @@ -1 +1 @@ -export { default, companyCopyright } from 'core/helpers/company-copyright'; +export { default } from 'core/helpers/company-copyright'; diff --git a/addons/core/app/helpers/company-name.js b/addons/core/app/helpers/company-name.js index da699e089..01921c115 100644 --- a/addons/core/app/helpers/company-name.js +++ b/addons/core/app/helpers/company-name.js @@ -1 +1 @@ -export { default, companyName } from 'core/helpers/company-name'; +export { default } from 'core/helpers/company-name'; diff --git a/addons/core/app/helpers/doc-url.js b/addons/core/app/helpers/doc-url.js index a8f150ce1..ae356804f 100644 --- a/addons/core/app/helpers/doc-url.js +++ b/addons/core/app/helpers/doc-url.js @@ -1 +1 @@ -export { default, docUrl } from 'core/helpers/doc-url'; +export { default } from 'core/helpers/doc-url'; diff --git a/addons/core/app/helpers/format-date-iso-human.js b/addons/core/app/helpers/format-date-iso-human.js index 947f5e926..3ed9c0ca2 100644 --- a/addons/core/app/helpers/format-date-iso-human.js +++ b/addons/core/app/helpers/format-date-iso-human.js @@ -1,4 +1 @@ -export { - default, - formatDateIsoHuman, -} from 'core/helpers/format-date-iso-human'; +export { default } from 'core/helpers/format-date-iso-human'; diff --git a/addons/core/app/helpers/format-date-iso.js b/addons/core/app/helpers/format-date-iso.js index f82d799e1..ef7aab468 100644 --- a/addons/core/app/helpers/format-date-iso.js +++ b/addons/core/app/helpers/format-date-iso.js @@ -1 +1 @@ -export { default, formatDateIso } from 'core/helpers/format-date-iso'; +export { default } from 'core/helpers/format-date-iso'; diff --git a/addons/core/app/helpers/is-loading.js b/addons/core/app/helpers/is-loading.js index 0645984c8..27b232c3d 100644 --- a/addons/core/app/helpers/is-loading.js +++ b/addons/core/app/helpers/is-loading.js @@ -1 +1 @@ -export { default, isLoading } from 'core/helpers/is-loading'; +export { default } from 'core/helpers/is-loading'; diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml index eccbad6eb..2c501df04 100644 --- a/addons/core/translations/actions/en-us.yaml +++ b/addons/core/translations/actions/en-us.yaml @@ -31,3 +31,4 @@ set-password: Set Password change-password: Change Password edit-form: Edit Form change-origin: Change Origin URL +change-state: Change State diff --git a/addons/core/translations/states/en-us.yaml b/addons/core/translations/states/en-us.yaml index aa8e846bd..aca77b801 100644 --- a/addons/core/translations/states/en-us.yaml +++ b/addons/core/translations/states/en-us.yaml @@ -8,3 +8,6 @@ connection: success: description: "Local proxy address ({protocol}): {address}:{port}" primary: Primary +inactive: Inactive +active-private: Private +active-public: Public diff --git a/addons/rose/app/components/rose/layout/tabs.js b/addons/rose/app/components/rose/layout/tabs.js deleted file mode 100644 index 9de968192..000000000 --- a/addons/rose/app/components/rose/layout/tabs.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/layout/tabs'; diff --git a/addons/rose/app/components/rose/tab.js b/addons/rose/app/components/rose/tab.js deleted file mode 100644 index 37b6e680c..000000000 --- a/addons/rose/app/components/rose/tab.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'rose/components/rose/tab'; diff --git a/addons/rose/package.json b/addons/rose/package.json index aa389d5a0..2226f0281 100644 --- a/addons/rose/package.json +++ b/addons/rose/package.json @@ -43,7 +43,7 @@ "@ember/test-helpers": "^2.1.4", "@glimmer/component": "^1.0.3", "@glimmer/tracking": "^1.0.3", - "@hashicorp/structure-icons": "^1.8.1", + "@hashicorp/structure-icons": "^1.9.0-0", "@storybook/addon-actions": "^6.0.26", "@storybook/addon-docs": "^6.0.26", "@storybook/addon-knobs": "^6.0.26", diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method.js b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method.js index 1005f0216..1aa269744 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/auth-method.js @@ -1,4 +1,5 @@ import Controller from '@ember/controller'; +import { options } from 'api/models/auth-method'; export default class ScopesScopeAuthMethodsAuthMethodController extends Controller { // =attributes @@ -10,4 +11,12 @@ export default class ScopesScopeAuthMethodsAuthMethodController extends Controll get breadCrumb() { return this.model.displayName; } + + /** + * OIDC auth-method states + * @type {[string]} + */ + get oidcStates() { + return options.oidc.state; + } } diff --git a/ui/admin/app/index.html b/ui/admin/app/index.html index 1af9cc9af..befb5d7b5 100644 --- a/ui/admin/app/index.html +++ b/ui/admin/app/index.html @@ -4,7 +4,7 @@ Admin - + {{content-for "head"}} diff --git a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js index 3c608f660..c0678ed0a 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method.js @@ -1,4 +1,6 @@ import Route from '@ember/routing/route'; +import { action } from '@ember/object'; +import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeAuthMethodsAuthMethodRoute extends Route { // =methods @@ -36,4 +38,18 @@ export default class ScopesScopeAuthMethodsAuthMethodRoute extends Route { outlet: 'actions', }); } + + // =actions + + /** + * Update state of OIDC auth method + * @param {string} state + */ + @action + @notifyError(({ message }) => message) + @notifySuccess('notifications.save-success') + async changeState(state) { + const model = this.modelFor('scopes.scope.auth-methods.auth-method'); + await model.changeState(state); + } } diff --git a/ui/admin/app/styles/app.scss b/ui/admin/app/styles/app.scss index 9defaac7b..8ee952891 100644 --- a/ui/admin/app/styles/app.scss +++ b/ui/admin/app/styles/app.scss @@ -83,9 +83,9 @@ .rose-form-fieldset { .rose-table { .rose-form-label { + left: -9999px; position: absolute; top: -9999px; - left: -9999px; } } } 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 c46e656f8..612a5e408 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,3 +1,36 @@ +{{#if @model.isOIDC}} + + + + + {{#each this.oidcStates as |state|}} + + + + {{/each}} + + + + +{{/if}} + { + // // Only respond to state update with error + // if (request.params.idMethod.match(/(change-state)/i)) { + // return new Response( + // 400, + // {}, + // { + // status: 400, + // code: 'error', + // message: 'Sorry!', + // } + // ); + // } + // return request; + // }); + // const newState = 'inactive'; + // await visit(urls.authMethod); + // await click('.rose-layout-page-actions .rose-dropdown-trigger'); + // await click(`.rose-dropdown[open] input[value="${newState}"]`); + // // debugger; + // const authMethod = this.server.db.authMethods.find(instances.authMethod.id); + // assert.notEqual( + // newState, + // authMethod.attributes.state, + // 'Auth method state is not be updated.' + // ); + // assert.ok( + // find('[role="alert"]').textContent.trim(), + // 'Sorry!', + // 'Displays error message.' + // ); + // }); +}); diff --git a/yarn.lock b/yarn.lock index f01866ca4..f2e14d85f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2023,10 +2023,10 @@ resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-1.1.0.tgz#d6dbc7574774b238114582410e8fee0dc3532bdf" integrity sha512-rR7tJoSwJ2eooOpYGxGGW95sLq6GXUaS1UtWvN7pei6n2/okYvCGld9vsUTvkl2migxbkszsycwtMf/GEc1k1A== -"@hashicorp/structure-icons@^1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.8.1.tgz#d29945df2b41dcb317b141e51a26bd4be796a164" - integrity sha512-XFYdCIshmaR3Igc8eWpOZ2Gr3IR/0TogXZ4PQ9bz1E9cLzF3njBcs3tCpJUOwRwe/wMI5YTlL/sOGvcZ77AB/Q== +"@hashicorp/structure-icons@^1.9.0-0": + version "1.9.0-0" + resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.9.0-0.tgz#7bd2f4a61d2dd81247090d2cfb86f1f89d4ea22a" + integrity sha512-khvUS/zThfR6pLW4hGVRpcGY2Ta5azeS/Vzb9iCfr3A8OhSZFdnrlkqjYknpBg4RwrQDBpWTzZhe/Z35Ne4Wxg== "@iarna/cli@^1.2.0": version "1.2.0" @@ -21816,9 +21816,9 @@ xmldom@^0.5.0: integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA== xmlhttprequest-ssl@^1.6.2, xmlhttprequest-ssl@~1.5.4: - version "1.6.2" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.2.tgz#dd6899bfbcf684b554e393c30b13b9f3b001a7ee" - integrity sha512-tYOaldF/0BLfKuoA39QMwD4j2m8lq4DIncqj1yuNELX4vz9+z/ieG/vwmctjJce+boFHXstqhWnHSxc4W8f4qg== + version "1.6.3" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" + integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q== xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2"