diff --git a/addons/api/addon/generated/models/auth-method.js b/addons/api/addon/generated/models/auth-method.js index eeef31ec0..b13a3fd71 100644 --- a/addons/api/addon/generated/models/auth-method.js +++ b/addons/api/addon/generated/models/auth-method.js @@ -55,55 +55,241 @@ export default class GeneratedAuthMethodModel extends BaseModel { }) version; - @attr('string', { readOnly: true, isNestedAttribute: true }) state; + // =attributes(oidc, ldap) - @attr('string', { isNestedAttribute: true }) issuer; + @attr('string', { + for: ['oidc', 'ldap'], + readOnly: true, + isNestedAttribute: true, + }) + state; - @attr('string', { isNestedAttribute: true }) client_id; + // =attributes(oidc) - @attr('string', { isNestedAttribute: true, isSecret: true }) client_secret; + @attr('string', { + for: 'oidc', + isNestedAttribute: true, + }) + issuer; - @attr('string', { readOnly: true, isNestedAttribute: true }) + @attr('string', { + for: 'oidc', + isNestedAttribute: true, + }) + client_id; + + @attr('string', { + for: 'oidc', + isNestedAttribute: true, + isSecret: true, + }) + client_secret; + + @attr('string', { + for: 'oidc', + readOnly: true, + isNestedAttribute: true, + }) client_secret_hmac; - @attr('number', { isNestedAttribute: true }) max_age; + @attr('number', { + for: 'oidc', + isNestedAttribute: true, + }) + max_age; - @attr('string', { isNestedAttribute: true }) api_url_prefix; + @attr('string', { + for: 'oidc', + isNestedAttribute: true, + }) + api_url_prefix; - @attr('string', { readOnly: true, isNestedAttribute: true }) callback_url; + @attr('string', { + for: 'oidc', + readOnly: true, + isNestedAttribute: true, + }) + callback_url; - @attr('boolean', { isNestedAttribute: true }) + @attr('boolean', { + for: 'oidc', + isNestedAttribute: true, + }) disable_discovered_config_validation; - @attr('boolean', { isNestedAttribute: true }) dry_run; + @attr('boolean', { + for: 'oidc', + isNestedAttribute: true, + }) + dry_run; @attr('string-array', { + for: 'oidc', emptyArrayIfMissing: true, isNestedAttribute: true, }) claims_scopes; @attr('string-array', { + for: 'oidc', emptyArrayIfMissing: true, isNestedAttribute: true, }) signing_algorithms; @attr('string-array', { + for: 'oidc', emptyArrayIfMissing: true, isNestedAttribute: true, }) allowed_audiences; @attr('string-array', { + for: 'oidc', emptyArrayIfMissing: true, isNestedAttribute: true, }) idp_ca_certs; - @attr('account-claim-map-array', { + @attr('account-value-map-array', { + for: 'oidc', emptyArrayIfMissing: true, isNestedAttribute: true, }) account_claim_maps; + + // =attributes(ldap) + + @attr('boolean', { + for: 'ldap', + isNestedAttribute: true, + }) + start_tls; + + @attr('boolean', { + for: 'ldap', + isNestedAttribute: true, + }) + insecure_tls; + + @attr('boolean', { + for: 'ldap', + isNestedAttribute: true, + }) + discover_dn; + + @attr('boolean', { + for: 'ldap', + isNestedAttribute: true, + }) + anon_group_search; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + upn_domain; + + @attr('string-array', { + for: 'ldap', + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + urls; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + user_dn; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + user_attr; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + user_filter; + + @attr('boolean', { + for: 'ldap', + isNestedAttribute: true, + }) + enable_groups; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + group_dn; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + group_attr; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + group_filter; + + @attr('string-array', { + for: 'ldap', + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + certificates; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + client_certificate; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + isSecret: true, + }) + client_certificate_key; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + readOnly: true, + }) + client_certificate_key_hmac; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + }) + bind_dn; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + isSecret: true, + }) + bind_password; + + @attr('string', { + for: 'ldap', + isNestedAttribute: true, + readOnly: true, + }) + bind_password_hmac; + + @attr('account-value-map-array', { + for: 'ldap', + emptyArrayIfMissing: true, + isNestedAttribute: true, + }) + account_attribute_maps; } diff --git a/addons/api/addon/models/auth-method.js b/addons/api/addon/models/auth-method.js index 8599160f1..083d6fb1f 100644 --- a/addons/api/addon/models/auth-method.js +++ b/addons/api/addon/models/auth-method.js @@ -38,6 +38,12 @@ export const options = { to: ['sub', 'name', 'email'], }, }, + ldap: { + account_attribute_maps: { + to: ['fullName', 'email'], + }, + state: ['inactive', 'active-private', 'active-public'], + }, }; export default class AuthMethodModel extends GeneratedAuthMethodModel { @@ -102,9 +108,9 @@ export default class AuthMethodModel extends GeneratedAuthMethodModel { // =methods /** - * Change the active and visibility state of an OIDC auth method + * Change the active and visibility state of an OIDC and LDAP auth method * given its ID. - * For OIDC auth methods only. + * For OIDC and LDAP auth methods only. * @param {[string]} state * @param {object} options * @param {object} options.adapterOptions diff --git a/addons/api/addon/serializers/auth-method.js b/addons/api/addon/serializers/auth-method.js index 01488e4e6..8ceb461ab 100644 --- a/addons/api/addon/serializers/auth-method.js +++ b/addons/api/addon/serializers/auth-method.js @@ -4,7 +4,7 @@ */ import ApplicationSerializer from './application'; -import { TYPE_AUTH_METHOD_OIDC } from 'api/models/auth-method'; +import { TYPE_AUTH_METHOD_PASSWORD } from 'api/models/auth-method'; export default class AuthMethodSerializer extends ApplicationSerializer { // =methods @@ -17,18 +17,33 @@ export default class AuthMethodSerializer extends ApplicationSerializer { */ serialize(snapshot) { switch (snapshot.record.type) { - case TYPE_AUTH_METHOD_OIDC: - return this.serializeOIDC(...arguments); + case TYPE_AUTH_METHOD_PASSWORD: + return this.serializePassword(...arguments); default: return this.serializeDefault(...arguments); } } + serializeAttribute(snapshot, json, key, attribute) { + const { type } = snapshot.record; + super.serializeAttribute(...arguments); + const { options } = attribute; + + // If an attribute has a `for` option, it must match the + // record's `type`, else the attribute is excluded + // from serialization. + if (options?.for && !options.for.includes(type)) { + if (options.isNestedAttribute) { + delete json?.attributes?.[key]; + } + } + } + /** - * Default serialization omits `attributes`. + * Password serialization omits `attributes`. * @return {object} */ - serializeDefault() { + serializePassword() { let serialized = super.serialize(...arguments); delete serialized.attributes; return serialized; @@ -40,11 +55,11 @@ export default class AuthMethodSerializer extends ApplicationSerializer { * @param {Snapshot} snapshot * @return {object} */ - serializeOIDC(snapshot) { + serializeDefault(snapshot) { let serialized = super.serialize(...arguments); const state = snapshot?.adapterOptions?.state; if (state) { - serialized = this.serializeOIDCWithState(snapshot, state); + serialized = this.serializeWithState(snapshot, state); } else { delete serialized.attributes.state; } @@ -57,7 +72,7 @@ export default class AuthMethodSerializer extends ApplicationSerializer { * @param {string} state * @return {object} */ - serializeOIDCWithState(snapshot, state) { + serializeWithState(snapshot, state) { return { version: snapshot.attr('version'), attributes: { state }, diff --git a/addons/api/addon/transforms/account-claim-map-array.js b/addons/api/addon/transforms/account-claim-map-array.js deleted file mode 100644 index 17d519892..000000000 --- a/addons/api/addon/transforms/account-claim-map-array.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) HashiCorp, Inc. - * SPDX-License-Identifier: MPL-2.0 - */ - -import Transform from '@ember-data/serializer/transform'; - -export default class AccountClaimMapArrayTransform extends Transform { - deserialize(serialized) { - const accountClaims = serialized || []; - return accountClaims.map((accountClaimString) => ({ - from: accountClaimString.split('=')[0], - to: accountClaimString.split('=')[1], - })); - } - - serialize(deserialized) { - const accountClaims = deserialized || []; - return accountClaims.map(({ from, to }) => `${from}=${to}`); - } -} diff --git a/addons/api/addon/transforms/account-value-map-array.js b/addons/api/addon/transforms/account-value-map-array.js new file mode 100644 index 000000000..f4b9aa7d7 --- /dev/null +++ b/addons/api/addon/transforms/account-value-map-array.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +import Transform from '@ember-data/serializer/transform'; + +export default class AccountValueMapArrayTransform extends Transform { + deserialize(serialized) { + const accountValues = serialized || []; + return accountValues.map((accountValueString) => ({ + from: accountValueString.split('=')[0], + to: accountValueString.split('=')[1], + })); + } + + serialize(deserialized) { + const accountValues = deserialized || []; + return accountValues.map(({ from, to }) => `${from}=${to}`); + } +} diff --git a/addons/api/app/transforms/account-claim-map-array.js b/addons/api/app/transforms/account-value-map-array.js similarity index 55% rename from addons/api/app/transforms/account-claim-map-array.js rename to addons/api/app/transforms/account-value-map-array.js index 696213b2f..14083164e 100644 --- a/addons/api/app/transforms/account-claim-map-array.js +++ b/addons/api/app/transforms/account-value-map-array.js @@ -3,4 +3,4 @@ * SPDX-License-Identifier: MPL-2.0 */ -export { default } from 'api/transforms/account-claim-map-array'; +export { default } from 'api/transforms/account-value-map-array'; diff --git a/addons/api/tests/unit/transforms/account-claim-map-array-test.js b/addons/api/tests/unit/transforms/account-value-map-array-test.js similarity index 80% rename from addons/api/tests/unit/transforms/account-claim-map-array-test.js rename to addons/api/tests/unit/transforms/account-value-map-array-test.js index acba3091d..ba7e75fbc 100644 --- a/addons/api/tests/unit/transforms/account-claim-map-array-test.js +++ b/addons/api/tests/unit/transforms/account-value-map-array-test.js @@ -6,12 +6,12 @@ import { module, test } from 'qunit'; import { setupTest } from 'ember-qunit'; -module('Unit | Transform | account claim map array', function (hooks) { +module('Unit | Transform | account value map array', function (hooks) { setupTest(hooks); test('it deserializes an array of account claims', function (assert) { assert.expect(1); - const transform = this.owner.lookup('transform:account-claim-map-array'); + const transform = this.owner.lookup('transform:account-value-map-array'); const deserialized = transform.deserialize(['oid=sub', 'full_name=name']); assert.deepEqual(deserialized, [ { from: 'oid', to: 'sub' }, @@ -21,7 +21,7 @@ module('Unit | Transform | account claim map array', function (hooks) { test('it serializes an array of account claims', function (assert) { assert.expect(1); - const transform = this.owner.lookup('transform:account-claim-map-array'); + const transform = this.owner.lookup('transform:account-value-map-array'); const serialized = transform.serialize([ { from: 'oid', to: 'sub' }, { from: 'full_name', to: 'name' },