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); + }); +});