diff --git a/addons/api/addon/generated/models/auth-method.js b/addons/api/addon/generated/models/auth-method.js index 610f565f3..ccf7675d3 100644 --- a/addons/api/addon/generated/models/auth-method.js +++ b/addons/api/addon/generated/models/auth-method.js @@ -49,4 +49,26 @@ export default class GeneratedAuthMethodModel extends BaseModel { description: 'Current version number of this resource.', }) version; + + @attr('string', { readOnly: true, isNestedAttribute: true }) state; + + @attr('string', { isNestedAttribute: true }) issuer; + + @attr('string', { isNestedAttribute: true }) client_id; + + @attr('string', { isNestedAttribute: true }) client_secret; + + @attr('string', { readOnly: true, isNestedAttribute: true }) + client_secret_hmac; + + @attr('number', { isNestedAttribute: true }) max_age; + + @attr('string', { isNestedAttribute: true }) api_url_prefix; + + @attr('string', { readOnly: true, isNestedAttribute: true }) callback_url; + + @attr('boolean', { isNestedAttribute: true }) + disable_discovered_config_validation; + + @attr('boolean', { isNestedAttribute: true }) dry_run; } diff --git a/addons/api/addon/models/auth-method.js b/addons/api/addon/models/auth-method.js index f0832cc91..57a69cf90 100644 --- a/addons/api/addon/models/auth-method.js +++ b/addons/api/addon/models/auth-method.js @@ -1,6 +1,5 @@ import GeneratedAuthMethodModel from '../generated/models/auth-method'; -import { attr } from '@ember-data/model'; -import { fragment } from 'ember-data-model-fragments/attributes'; +import { fragmentArray } from 'ember-data-model-fragments/attributes'; import { equal } from '@ember/object/computed'; /** @@ -28,33 +27,37 @@ export const options = { }; export default class AuthMethodModel extends GeneratedAuthMethodModel { - // =error attributes - // These attributes exist solely to capture errors on nested fields. - // See the application adapter's error normalization method for - // more information. - - @attr('string', { readOnly: true }) attributes_state; - @attr('string', { readOnly: true }) attributes_issuer; - @attr('string', { readOnly: true }) attributes_client_id; - @attr('string', { readOnly: true }) attributes_client_secret; - @attr('string', { readOnly: true }) attributes_max_age; - @attr('string', { readOnly: true }) attributes_api_url_prefix; - @attr('string', { readOnly: true }) - attributes_disable_discovered_config_validation; - @attr('string', { readOnly: true }) attributes_dry_run; - @attr('string', { readOnly: true }) attributes_account_claim_maps; - @attr('string', { readOnly: true }) attributes_claims_scopes; - @attr('string', { readOnly: true }) attributes_signing_algorithms; - @attr('string', { readOnly: true }) attributes_allowed_audiences; - @attr('string', { readOnly: true }) attributes_idp_ca_certs; - // =attributes - /** - * Attributes of this resource, if any, represented as a JSON fragment. - * @type {FragmentAuthMethodAttributesModel} - */ - @fragment('fragment-auth-method-attributes', { defaultValue: {} }) attributes; + @fragmentArray('fragment-auth-method-attributes-account-claim-map', { + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + account_claim_maps; + + @fragmentArray('fragment-string', { + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + claims_scopes; + + @fragmentArray('fragment-string', { + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + signing_algorithms; + + @fragmentArray('fragment-string', { + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + allowed_audiences; + + @fragmentArray('fragment-string', { + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + idp_ca_certs; /** * @type {boolean} @@ -81,21 +84,21 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel { * @type {boolean} */ get isInactive() { - return this.attributes.state === 'inactive'; + return this.state === 'inactive'; } /** * @type {boolean} */ get isPrivate() { - return this.attributes.state === 'active-private'; + return this.state === 'active-private'; } /** * @type {boolean} */ get isPublic() { - return this.attributes.state === 'active-public'; + return this.state === 'active-public'; } // =methods diff --git a/addons/api/addon/models/fragment-auth-method-attributes.js b/addons/api/addon/models/fragment-auth-method-attributes.js deleted file mode 100644 index 3fdcb8e47..000000000 --- a/addons/api/addon/models/fragment-auth-method-attributes.js +++ /dev/null @@ -1,40 +0,0 @@ -import Fragment from 'ember-data-model-fragments/fragment'; -import { attr } from '@ember-data/model'; -import { fragmentArray } from 'ember-data-model-fragments/attributes'; - -export default class FragmentAuthMethodAttributesModel extends Fragment { - // =attributes (OIDC) - - @attr('string', { readOnly: true }) state; - @attr('string') issuer; - @attr('string') client_id; - @attr('string') client_secret; - @attr('string', { readOnly: true }) client_secret_hmac; - @attr('number') max_age; - @attr('string') api_url_prefix; - @attr('string', { readOnly: true }) callback_url; - @attr('boolean') disable_discovered_config_validation; - @attr('boolean') dry_run; - - @fragmentArray('fragment-auth-method-attributes-account-claim-map', { - emptyArrayIfMissing: true, - }) - account_claim_maps; - - @fragmentArray('fragment-string', { - emptyArrayIfMissing: true, - }) - claims_scopes; - - @fragmentArray('fragment-string', { - emptyArrayIfMissing: true, - }) - signing_algorithms; - - @fragmentArray('fragment-string', { - emptyArrayIfMissing: true, - }) - allowed_audiences; - - @fragmentArray('fragment-string', { emptyArrayIfMissing: true }) idp_ca_certs; -} diff --git a/addons/api/addon/serializers/fragment-auth-method-attributes.js b/addons/api/addon/serializers/fragment-auth-method-attributes.js deleted file mode 100644 index 1abc73573..000000000 --- a/addons/api/addon/serializers/fragment-auth-method-attributes.js +++ /dev/null @@ -1,26 +0,0 @@ -import JSONSerializer from '@ember-data/serializer/json'; - -export default class FragmentAuthMethodAttributesSerializer 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/models/fragment-auth-method-attributes.js b/addons/api/app/models/fragment-auth-method-attributes.js deleted file mode 100644 index 46bd1e0f2..000000000 --- a/addons/api/app/models/fragment-auth-method-attributes.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'api/models/fragment-auth-method-attributes'; diff --git a/addons/api/app/serializers/fragment-auth-method-attributes.js b/addons/api/app/serializers/fragment-auth-method-attributes.js deleted file mode 100644 index 031baf9e3..000000000 --- a/addons/api/app/serializers/fragment-auth-method-attributes.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from 'api/serializers/fragment-auth-method-attributes'; diff --git a/addons/api/tests/unit/models/fragment-auth-method-attributes-test.js b/addons/api/tests/unit/models/fragment-auth-method-attributes-test.js deleted file mode 100644 index 433c2045d..000000000 --- a/addons/api/tests/unit/models/fragment-auth-method-attributes-test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Model | fragment auth method attributes', function (hooks) { - setupTest(hooks); - - test('it exists', function (assert) { - let store = this.owner.lookup('service:store'); - let model = store.createRecord('fragment-auth-method-attributes', {}); - assert.ok(model); - }); -}); diff --git a/addons/api/tests/unit/serializers/auth-method-test.js b/addons/api/tests/unit/serializers/auth-method-test.js index ae878d744..1d9dcc1c5 100644 --- a/addons/api/tests/unit/serializers/auth-method-test.js +++ b/addons/api/tests/unit/serializers/auth-method-test.js @@ -33,27 +33,25 @@ module('Unit | Serializer | auth method', function (hooks) { let record = store.createRecord('auth-method', { type: 'oidc', name: 'OIDC Auth Method', - attributes: { - state: 'foo', - account_claim_maps: [{ from: 'foo', to: 'bar' }], - claims_scopes: [{ value: 'profile' }, { value: 'email' }], - signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }], - allowed_audiences: [ - { value: 'www.alice.com' }, - { value: 'www.alice.com/admin' }, - ], - idp_ca_certs: [ - { value: 'certificate-1234' }, - { value: 'certificate-5678' }, - ], - api_url_prefix: 'protocol://host:port/foo', - client_id: 'id123', - client_secret: 'secret456', - disable_discovered_config_validation: true, - dry_run: true, - issuer: 'http://www.example.net', - max_age: 500, - }, + state: 'foo', + account_claim_maps: [{ from: 'foo', to: 'bar' }], + claims_scopes: [{ value: 'profile' }, { value: 'email' }], + signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }], + allowed_audiences: [ + { value: 'www.alice.com' }, + { value: 'www.alice.com/admin' }, + ], + idp_ca_certs: [ + { value: 'certificate-1234' }, + { value: 'certificate-5678' }, + ], + api_url_prefix: 'protocol://host:port/foo', + client_id: 'id123', + client_secret: 'secret456', + disable_discovered_config_validation: true, + dry_run: true, + issuer: 'http://www.example.net', + max_age: 500, }); let serializedRecord = record.serialize(); @@ -148,19 +146,56 @@ module('Unit | Serializer | auth method', function (hooks) { test('it normalizes OIDC records', async function (assert) { const store = this.owner.lookup('service:store'); + + const apiUrlPrefix = 'protocol://host:port/foo'; + const clientId = 'id123'; + const clientSecret = 'secret456'; + const disableDiscoveredConfigValidation = true; + const dryRun = true; + const issuer = 'http://www.example.net'; + const maxAge = 500; this.server.get('/v1/auth-methods/oidc123', () => ({ attributes: { account_claim_maps: ['from=to', 'foo=bar'], + claims_scopes: [{ value: 'profile' }, { value: 'email' }], + signing_algorithms: [{ value: 'RS256' }, { value: 'RS384' }], + allowed_audiences: [ + { value: 'www.alice.com' }, + { value: 'www.alice.com/admin' }, + ], + idp_ca_certs: [ + { value: 'certificate-1234' }, + { value: 'certificate-5678' }, + ], + api_url_prefix: apiUrlPrefix, + client_id: clientId, + client_secret: clientSecret, + disable_discovered_config_validation: disableDiscoveredConfigValidation, + dry_run: dryRun, + issuer: issuer, + max_age: maxAge, }, version: 1, type: 'oidc', id: 'oidc123', })); + const record = await store.findRecord('auth-method', 'oidc123'); - const { account_claim_maps } = record.attributes; + const { account_claim_maps } = record; + assert.strictEqual(account_claim_maps.firstObject.from, 'from'); assert.strictEqual(account_claim_maps.firstObject.to, 'to'); assert.strictEqual(account_claim_maps.lastObject.from, 'foo'); assert.strictEqual(account_claim_maps.lastObject.to, 'bar'); + assert.strictEqual(record.api_url_prefix, apiUrlPrefix); + assert.strictEqual(record.client_id, clientId); + assert.strictEqual(record.client_secret, clientSecret); + assert.strictEqual( + record.disable_discovered_config_validation, + disableDiscoveredConfigValidation + ); + assert.strictEqual(record.dry_run, dryRun); + assert.strictEqual(record.issuer, issuer); + assert.strictEqual(record.max_age, maxAge); }); }); diff --git a/addons/api/tests/unit/serializers/fragment-auth-method-attributes-test.js b/addons/api/tests/unit/serializers/fragment-auth-method-attributes-test.js deleted file mode 100644 index a099c1944..000000000 --- a/addons/api/tests/unit/serializers/fragment-auth-method-attributes-test.js +++ /dev/null @@ -1,37 +0,0 @@ -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; - -module('Unit | Serializer | fragment auth method attributes', function (hooks) { - setupTest(hooks); - - test('it serializes empty strings to null', function (assert) { - assert.expect(1); - const store = this.owner.lookup('service:store'); - const record = store.createRecord('user', { - name: '', - description: '', - version: null, - }); - let serializedRecord = record.serialize(); - assert.deepEqual(serializedRecord, { - name: null, - description: null, - }); - }); - - test('it does not serialize client_secret if present but falsy', function (assert) { - assert.expect(1); - const store = this.owner.lookup('service:store'); - const record = store.createRecord('user', { - name: '', - description: '', - version: null, - client_secret: false, - }); - let serializedRecord = record.serialize(); - assert.deepEqual(serializedRecord, { - name: null, - description: null, - }); - }); -}); diff --git a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs index 743b8f3e3..3dbeaf185 100644 --- a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs +++ b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs @@ -1,6 +1,6 @@ {{#if @model.isOIDC}} diff --git a/ui/admin/app/components/form/auth-method/oidc/index.hbs b/ui/admin/app/components/form/auth-method/oidc/index.hbs index aff616334..eae4ad4e7 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.hbs +++ b/ui/admin/app/components/form/auth-method/oidc/index.hbs @@ -59,16 +59,16 @@ - {{#if @model.errors.attributes_issuer}} + {{#if @model.errors.issuer}} - {{#each @model.errors.attributes_issuer as |error|}} + {{#each @model.errors.issuer as |error|}} {{error.message}} {{/each}} @@ -78,26 +78,26 @@ - {{#if @model.errors.attributes_client_id}} + {{#if @model.errors.client_id}} - {{#each @model.errors.attributes_client_id as |error|}} + {{#each @model.errors.client_id as |error|}} {{error.message}} {{/each}} @@ -107,16 +107,16 @@ - {{#if @model.errors.attributes_client_secret}} + {{#if @model.errors.client_secret}} - {{#each @model.errors.attributes_client_secret as |error|}} + {{#each @model.errors.client_secret as |error|}} {{error.message}} {{/each}} @@ -125,7 +125,7 @@ {{#unless @model.isNew}} {{t 'form.signing_algorithms.label'}} <:description>{{t 'form.signing_algorithms.help'}} <:body> - {{#if @model.errors.attributes_signing_algorithms}} + {{#if @model.errors.signing_algorithms}} - {{#each @model.errors.attributes_signing_algorithms as |error|}} + {{#each @model.errors.signing_algorithms as |error|}} {{error.message}} {{/each}} @@ -152,13 +152,13 @@ - {{#each @model.attributes.signing_algorithms as |algorithm i|}} + {{#each @model.signing_algorithms as |algorithm i|}} {{t 'actions.remove'}} @@ -233,9 +230,7 @@ {{on 'click' (fn - @addStringItem - 'attributes.signing_algorithms' - this.newSigningAlgorithm + @addStringItem 'signing_algorithms' this.newSigningAlgorithm ) }} > @@ -253,9 +248,9 @@ <:title>{{t 'form.allowed_audiences.label'}} <:description>{{t 'form.allowed_audiences.help'}} <:body> - {{#if @model.errors.attributes_allowed_audiences}} + {{#if @model.errors.allowed_audiences}} - {{#each @model.errors.attributes_allowed_audiences as |error|}} + {{#each @model.errors.allowed_audiences as |error|}} {{error.message}} {{/each}} @@ -268,13 +263,14 @@ - {{#each @model.attributes.allowed_audiences as |audience i|}} + {{#each @model.allowed_audiences as |audience i|}} @@ -292,10 +288,7 @@ false (if form.isEditable false true) }} - {{on - 'click' - (fn @removeItemByIndex 'attributes.allowed_audiences' i) - }} + {{on 'click' (fn @removeItemByIndex 'allowed_audiences' i)}} > {{t 'actions.remove'}} @@ -307,6 +300,7 @@ @@ -323,9 +317,7 @@ {{on 'click' (fn - @addStringItem - 'attributes.allowed_audiences' - this.newAllowedAudience + @addStringItem 'allowed_audiences' this.newAllowedAudience ) }} > @@ -343,9 +335,9 @@ <:title>{{t 'form.claims_scopes.label'}} <:description>{{t 'form.claims_scopes.help'}} <:body> - {{#if @model.errors.attributes_claims_scopes}} + {{#if @model.errors.claims_scopes}} - {{#each @model.errors.attributes_claims_scopes as |error|}} + {{#each @model.errors.claims_scopes as |error|}} {{error.message}} {{/each}} @@ -358,13 +350,14 @@ - {{#each @model.attributes.claims_scopes as |claimsScope i|}} + {{#each @model.claims_scopes as |claimsScope i|}} @@ -382,10 +375,7 @@ false (if form.isEditable false true) }} - {{on - 'click' - (fn @removeItemByIndex 'attributes.claims_scopes' i) - }} + {{on 'click' (fn @removeItemByIndex 'claims_scopes' i)}} > {{t 'actions.remove'}} @@ -397,6 +387,7 @@ @@ -412,11 +403,7 @@ }} {{on 'click' - (fn - @addStringItem - 'attributes.claims_scopes' - this.newClaimsScope - ) + (fn @addStringItem 'claims_scopes' this.newClaimsScope) }} > {{t 'actions.add'}} @@ -433,9 +420,9 @@ <:title>{{t 'form.account_claim_maps.label'}} <:description>{{t 'form.account_claim_maps.help'}} <:body> - {{#if @model.errors.attributes_account_claim_maps}} + {{#if @model.errors.account_claim_maps}} - {{#each @model.errors.attributes_account_claim_maps as |error|}} + {{#each @model.errors.account_claim_maps as |error|}} {{error.message}} {{/each}} @@ -449,13 +436,14 @@ - {{#each @model.attributes.account_claim_maps as |claimMap i|}} + {{#each @model.account_claim_maps as |claimMap i|}} @@ -467,7 +455,7 @@ {{t 'actions.remove'}} @@ -509,6 +494,7 @@ @@ -563,9 +549,9 @@ <:title>{{t 'form.idp_ca_certs.label'}} <:description>{{t 'form.idp_ca_certs.help'}} <:body> - {{#if @model.errors.attributes_idp_ca_certs}} + {{#if @model.errors.idp_ca_certs}} - {{#each @model.errors.attributes_idp_ca_certs as |error|}} + {{#each @model.errors.idp_ca_certs as |error|}} {{error.message}} {{/each}} @@ -578,12 +564,12 @@ - {{#each @model.attributes.idp_ca_certs as |cert i|}} + {{#each @model.idp_ca_certs as |cert i|}} @@ -601,10 +587,7 @@ false (if form.isEditable false true) }} - {{on - 'click' - (fn @removeItemByIndex 'attributes.idp_ca_certs' i) - }} + {{on 'click' (fn @removeItemByIndex 'idp_ca_certs' i)}} > {{t 'actions.remove'}} @@ -630,9 +613,7 @@ }} {{on 'click' - (fn - @addStringItem 'attributes.idp_ca_certs' this.newCertificate - ) + (fn @addStringItem 'idp_ca_certs' this.newCertificate) }} > {{t 'actions.add'}} @@ -647,18 +628,18 @@ - {{#if @model.errors.attributes_max_age}} + {{#if @model.errors.max_age}} - {{#each @model.errors.attributes_max_age as |error|}} + {{#each @model.errors.max_age as |error|}} {{error.message}} {{/each}} @@ -668,16 +649,16 @@ - {{#if @model.errors.attributes_api_url_prefix}} + {{#if @model.errors.api_url_prefix}} - {{#each @model.errors.attributes_api_url_prefix as |error|}} + {{#each @model.errors.api_url_prefix as |error|}} {{error.message}} {{/each}} @@ -686,7 +667,7 @@ {{#unless @model.isNew}} + this.server.schema.authMethods.all().models.length; }); test('Users can create new auth method', async function (assert) { assert.expect(1); - const authMethodsCount = this.server.db.authMethods.length; + const count = getAuthMethodsCount(); + await visit(urls.newAuthMethod); await fillIn('[name="name"]', 'AuthMethod name'); await fillIn('[name="description"]', 'description'); await click('form [type="submit"]:not(:disabled)'); - assert.strictEqual(this.server.db.authMethods.length, authMethodsCount + 1); + assert.strictEqual(getAuthMethodsCount(), count + 1); + }); + + test('Users can create new oidc auth method', async function (assert) { + assert.expect(13); + const count = getAuthMethodsCount(); + + await visit(`${urls.authMethods}/new?type=oidc`); + const name = 'oidc name'; + await fillIn('[name="name"]', name); + await fillIn('[name="description"]', 'description'); + await fillIn('[name="issuer"]', 'issuer'); + await fillIn('[name="client_id"]', 'client_id'); + await fillIn('[name="client_secret"]', 'client_secret'); + await select('form fieldset:nth-of-type(1) select', 'RS384'); + await click('form fieldset:nth-of-type(1) [title="Add"]'); + await fillIn('[name="allowed_audiences"]', 'allowed_audiences'); + await click('form fieldset:nth-of-type(2) [title="Add"]'); + await fillIn('[name="claims_scopes"]', 'claims_scopes'); + await click('form fieldset:nth-of-type(3) [title="Add"]'); + await fillIn('[name="from_claim"]', 'from_claim'); + await select('form fieldset:nth-of-type(4) select', 'email'); + await click('form fieldset:nth-of-type(4) [title="Add"]'); + await fillIn('form fieldset:nth-of-type(5) textarea', 'certificates'); + await click('form fieldset:nth-of-type(5) [title="Add"]'); + await fillIn('[name="max_age"]', '5'); + await fillIn('[name="api_url_prefix"]', 'api_url_prefix'); + await click('form [type="submit"]:not(:disabled)'); + + assert.strictEqual(getAuthMethodsCount(), count + 1); + const authMethod = this.server.schema.authMethods.findBy({ name }); + assert.strictEqual(authMethod.name, name); + assert.strictEqual(authMethod.description, 'description'); + assert.strictEqual(authMethod.attributes.issuer, 'issuer'); + assert.strictEqual(authMethod.attributes.client_id, 'client_id'); + assert.strictEqual(authMethod.attributes.client_secret, 'client_secret'); + assert.deepEqual(authMethod.attributes.signing_algorithms, ['RS384']); + assert.deepEqual(authMethod.attributes.allowed_audiences, [ + 'allowed_audiences', + ]); + assert.deepEqual(authMethod.attributes.claims_scopes, ['claims_scopes']); + assert.deepEqual(authMethod.attributes.account_claim_maps, [ + 'from_claim=email', + ]); + assert.deepEqual(authMethod.attributes.idp_ca_certs, ['certificates']); + assert.strictEqual(authMethod.attributes.max_age, 5); + assert.strictEqual(authMethod.attributes.api_url_prefix, 'api_url_prefix'); }); test('Users can navigate to new auth-methods route with proper authorization', async function (assert) { @@ -97,12 +154,12 @@ module('Acceptance | auth-methods | create ', function (hooks) { test('can cancel new auth method creation', async function (assert) { assert.expect(2); - const authMethodsCount = this.server.db.authMethods.length; + const count = getAuthMethodsCount(); await visit(urls.newAuthMethod); await fillIn('[name="name"]', 'AuthMethod name'); await fillIn('[name="description"]', 'description'); await click('form button:not([type="submit"])'); - assert.strictEqual(this.server.db.authMethods.length, authMethodsCount); + assert.strictEqual(getAuthMethodsCount(), count); assert.strictEqual(currentURL(), urls.authMethods); }); diff --git a/ui/admin/tests/acceptance/auth-methods/update-test.js b/ui/admin/tests/acceptance/auth-methods/update-test.js index 4c32cfce3..3f605706f 100644 --- a/ui/admin/tests/acceptance/auth-methods/update-test.js +++ b/ui/admin/tests/acceptance/auth-methods/update-test.js @@ -1,5 +1,12 @@ import { module, test } from 'qunit'; -import { visit, click, find, fillIn } from '@ember/test-helpers'; +import { + visit, + click, + find, + fillIn, + select, + findAll, +} from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import a11yAudit from 'ember-a11y-testing/test-support/audit'; @@ -57,6 +64,84 @@ module('Acceptance | auth methods | update', function (hooks) { assert.strictEqual(this.server.db.authMethods[0].name, 'update name'); }); + test('can update an oidc auth method and save changes', async function (assert) { + assert.expect(12); + instances.authMethod = this.server.create('auth-method', { + scope: instances.scopes.org, + type: 'oidc', + }); + await visit(`${urls.authMethods}/${instances.authMethod.id}`); + await click('form [type="button"]:not(:disabled)', 'Activate edit mode'); + const name = 'oidc name'; + await fillIn('[name="name"]', name); + await fillIn('[name="description"]', 'description'); + await fillIn('[name="issuer"]', 'issuer'); + await fillIn('[name="client_id"]', 'client_id'); + await fillIn('[name="client_secret"]', 'client_secret'); + // Remove all signing algorithms + await Promise.all( + findAll('form fieldset:nth-of-type(1) [title="Remove"]').map((element) => + click(element) + ) + ); + await select('form fieldset:nth-of-type(1) select', 'RS384'); + await click('form fieldset:nth-of-type(1) [title="Add"]'); + // Remove all allowed audiences + await Promise.all( + findAll('form fieldset:nth-of-type(2) [title="Remove"]').map((element) => + click(element) + ) + ); + await fillIn('[name="allowed_audiences"]', 'allowed_audiences'); + await click('form fieldset:nth-of-type(2) [title="Add"]'); + // Remove all claims scopes + await Promise.all( + findAll('form fieldset:nth-of-type(3) [title="Remove"]').map((element) => + click(element) + ) + ); + await fillIn('[name="claims_scopes"]', 'claims_scopes'); + await click('form fieldset:nth-of-type(3) [title="Add"]'); + // Remove all claim maps + await Promise.all( + findAll('form fieldset:nth-of-type(4) [title="Remove"]').map((element) => + click(element) + ) + ); + await fillIn('[name="from_claim"]', 'from_claim'); + await select('form fieldset:nth-of-type(4) select', 'email'); + await click('form fieldset:nth-of-type(4) [title="Add"]'); + // Remove all certificates + await Promise.all( + findAll('form fieldset:nth-of-type(5) [title="Remove"]').map((element) => + click(element) + ) + ); + await fillIn('form fieldset:nth-of-type(5) textarea', 'certificates'); + await click('form fieldset:nth-of-type(5) [title="Add"]'); + await fillIn('[name="max_age"]', '5'); + await fillIn('[name="api_url_prefix"]', 'api_url_prefix'); + await click('form [type="submit"]:not(:disabled)'); + + const authMethod = this.server.schema.authMethods.findBy({ name }); + assert.strictEqual(authMethod.name, name); + assert.strictEqual(authMethod.description, 'description'); + assert.strictEqual(authMethod.attributes.issuer, 'issuer'); + assert.strictEqual(authMethod.attributes.client_id, 'client_id'); + assert.strictEqual(authMethod.attributes.client_secret, 'client_secret'); + assert.deepEqual(authMethod.attributes.signing_algorithms, ['RS384']); + assert.deepEqual(authMethod.attributes.allowed_audiences, [ + 'allowed_audiences', + ]); + assert.deepEqual(authMethod.attributes.claims_scopes, ['claims_scopes']); + assert.deepEqual(authMethod.attributes.account_claim_maps, [ + 'from_claim=email', + ]); + assert.deepEqual(authMethod.attributes.idp_ca_certs, ['certificates']); + assert.strictEqual(authMethod.attributes.max_age, 5); + assert.strictEqual(authMethod.attributes.api_url_prefix, 'api_url_prefix'); + }); + test('can update an auth method and cancel changes', async function (assert) { assert.expect(1); await visit(urls.authMethod);