From 12588a17abc3878c6acf7ad1b9937beb4b48c3f4 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Fri, 4 Jun 2021 13:38:23 -0400 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20type-specific=20?= =?UTF-8?q?account=20serialization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/fragment-account-attributes.js | 8 ++++++ addons/api/addon/serializers/account.js | 23 ++++++++++++++++ .../fragment-account-attributes.js | 26 +++++++++++++++++++ .../fragment-account-attributes.js | 1 + .../fragment-account-attributes-test.js | 23 ++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 addons/api/addon/serializers/fragment-account-attributes.js create mode 100644 addons/api/app/serializers/fragment-account-attributes.js create mode 100644 addons/api/tests/unit/serializers/fragment-account-attributes-test.js diff --git a/addons/api/addon/models/fragment-account-attributes.js b/addons/api/addon/models/fragment-account-attributes.js index bb0371398..0297f4399 100644 --- a/addons/api/addon/models/fragment-account-attributes.js +++ b/addons/api/addon/models/fragment-account-attributes.js @@ -2,8 +2,16 @@ import Fragment from 'ember-data-model-fragments/fragment'; import { attr } from '@ember-data/model'; export default class FragmentAccountAttributesModel extends Fragment { + // =attributes (password) @attr('string', { + for: 'password', description: 'The account login name', }) login_name; + + // =attributes (OIDC) + @attr('string', { for: 'oidc' }) subject; + @attr('string', { for: 'oidc' }) issuer; + @attr('string', { for: 'oidc', readOnly: true }) email; + @attr('string', { for: 'oidc', readOnly: true }) full_name; } diff --git a/addons/api/addon/serializers/account.js b/addons/api/addon/serializers/account.js index dfbb7e580..939aceb70 100644 --- a/addons/api/addon/serializers/account.js +++ b/addons/api/addon/serializers/account.js @@ -20,13 +20,36 @@ export default class AccountSerializer extends ApplicationSerializer { * @return {object} */ serialize(snapshot) { + switch (snapshot.record.type) { + case 'password': + return this.serializePassword(...arguments); + } + } + + /** + * Password serialization omits `attributes` and handles password-related + * custom methods. + * @param {Snapshot} snapshot + * @return {object} + */ + serializePassword(snapshot) { const password = snapshot?.adapterOptions?.password; let serialized = super.serialize(...arguments); + // Only login_name is serialized into password attributes. + const { login_name } = serialized.attributes; + if (login_name) { + serialized.attributes = { login_name }; + } else { + serialized.attributes = {}; + } + // New record case if (password && snapshot?.record?.isNew) serialized.attributes.password = password; + // Set password custom method if (snapshot?.adapterOptions?.method === 'set-password') { serialized = this.serializeForSetPassword(snapshot, password); } + // Change password custom method if (snapshot?.adapterOptions?.method === 'change-password') { const { currentPassword, newPassword } = snapshot?.adapterOptions; serialized = this.serializeForChangePassword( diff --git a/addons/api/addon/serializers/fragment-account-attributes.js b/addons/api/addon/serializers/fragment-account-attributes.js new file mode 100644 index 000000000..a9dcb590c --- /dev/null +++ b/addons/api/addon/serializers/fragment-account-attributes.js @@ -0,0 +1,26 @@ +import JSONSerializer from '@ember-data/serializer/json'; + +export default class FragmentAccountAttributesSerializer extends JSONSerializer { + /** + * If an attribute is annotated as readOnly in the model, don't serialize it. + * Otherwise delegate to default attribute serializer. + * + * @override + * @method serializeAttribute + * @param {Snapshot} snapshot + * @param {Object} json + * @param {String} key + * @param {Object} attribute + */ + serializeAttribute(snapshot, json, key, attribute) { + const { type, options } = attribute; + let value = super.serializeAttribute(...arguments); + // Convert empty strings to null. + if (type === 'string' && json[key] === '') json[key] = null; + // Do not serialize read-only attributes. + if (options.readOnly) delete json[key]; + // Client secret cannot be unset. If it's falsy, it must be removed. + if (key === 'client_secret' && !json[key]) delete json[key]; + return value; + } +} diff --git a/addons/api/app/serializers/fragment-account-attributes.js b/addons/api/app/serializers/fragment-account-attributes.js new file mode 100644 index 000000000..b37aa8148 --- /dev/null +++ b/addons/api/app/serializers/fragment-account-attributes.js @@ -0,0 +1 @@ +export { default } from 'api/serializers/fragment-account-attributes'; diff --git a/addons/api/tests/unit/serializers/fragment-account-attributes-test.js b/addons/api/tests/unit/serializers/fragment-account-attributes-test.js new file mode 100644 index 000000000..3245f8b80 --- /dev/null +++ b/addons/api/tests/unit/serializers/fragment-account-attributes-test.js @@ -0,0 +1,23 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Serializer | fragment account attributes', function (hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function (assert) { + let store = this.owner.lookup('service:store'); + let serializer = store.serializerFor('fragment-account-attributes'); + + assert.ok(serializer); + }); + + test('it serializes records', function (assert) { + let store = this.owner.lookup('service:store'); + let record = store.createRecord('fragment-account-attributes', {}); + + let serializedRecord = record.serialize(); + + assert.ok(serializedRecord); + }); +}); From 13df776c180712d063cc3757519421a84040045c Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Fri, 4 Jun 2021 14:23:08 -0400 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20OIDC=20account?= =?UTF-8?q?=20listing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/api/addon/models/account.js | 5 + addons/core/translations/form/en-us.yaml | 6 + .../auth-methods/auth-method/-actions.hbs | 38 ++++-- .../auth-methods/auth-method/-navigation.hbs | 14 +- .../auth-method/accounts/index.hbs | 123 ++++++++++++------ 5 files changed, 122 insertions(+), 64 deletions(-) diff --git a/addons/api/addon/models/account.js b/addons/api/addon/models/account.js index 90ad55c42..e5f702541 100644 --- a/addons/api/addon/models/account.js +++ b/addons/api/addon/models/account.js @@ -17,6 +17,11 @@ export default class AccountModel extends GeneratedAccountModel { */ @equal('type', 'password') isPassword; + /** + * @type {boolean} + */ + @equal('type', 'oidc') isOIDC; + /** * Convenience for getting username in account. * @type {string} diff --git a/addons/core/translations/form/en-us.yaml b/addons/core/translations/form/en-us.yaml index 65277af78..56af46588 100644 --- a/addons/core/translations/form/en-us.yaml +++ b/addons/core/translations/form/en-us.yaml @@ -100,3 +100,9 @@ signing_algorithms: help: The signing algorithms allowed for the auth method. algorithm: label: Algorithm +subject: + label: Subject +email: + label: Email +full_name: + label: Full Name 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 612a5e408..1ae2b32b3 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 @@ -37,14 +37,6 @@ as |dropdown| > {{#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'}} + {{else}} + + {{t 'resources.auth-method.actions.make-primary'}} + {{/if}} {{/if}} - - {{t 'resources.account.actions.create'}} - + {{#if @model.isOIDC}} + {{#if (feature-flag 'oidc-account-crud')}} + + {{t 'resources.account.actions.create'}} + + {{/if}} + {{else}} + + {{t 'resources.account.actions.create'}} + + {{/if}} {{t 'titles.details'}} - {{#if @model.isOIDC}} - {{#if (feature-flag 'oidc-account-crud')}} - - {{t 'resources.account.title_plural'}} - - {{/if}} - {{else}} - - {{t 'resources.account.title_plural'}} - - {{/if}} + + {{t 'resources.account.title_plural'}} + \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index 850e78c93..dd16fcb1b 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -1,46 +1,91 @@ {{#if @model}} - - - - {{t 'form.name.label'}} - - {{#if @model.firstObject.isPassword}} - {{t 'form.login_name.label'}} - {{/if}} - - {{t 'form.id.label'}} - - - - {{#each @model as |account|}} - - - + {{! OIDC accounts display more fields }} + {{#if @model.firstObject.isOIDC}} + + + + {{t 'form.name.label'}} + {{t 'form.issuer.label'}} + {{t 'form.subject.label'}} + {{t 'form.email.label'}} + {{t 'form.full_name.label'}} + {{t 'form.id.label'}} + + + + {{#each @model as |account|}} + + {{account.displayName}} - -

{{account.description}}

+
+ + {{account.attributes.issuer}} + + + {{account.attributes.subject}} + + + {{account.attributes.email}} + + + {{account.attributes.full_name}} + + + + {{account.id}} + + +
+ {{/each}} +
+
+ {{else}} + + + + {{t 'form.name.label'}} + + {{#if @model.firstObject.isPassword}} + {{t 'form.login_name.label'}} + {{/if}} - - {{account.username}} - - - - {{account.id}} - - - - {{/each}} - - - + {{t 'form.id.label'}} + + + + {{#each @model as |account|}} + + + + {{account.displayName}} + +

{{account.description}}

+
+ + {{account.username}} + + + + {{account.id}} + + +
+ {{/each}} +
+ + {{/if}} {{else}}