From 71ec7b465a824186e24cd0c3f1186056b16700bd Mon Sep 17 00:00:00 2001 From: Dharini Date: Tue, 10 Feb 2026 14:25:00 -0800 Subject: [PATCH] =?UTF-8?q?chore:=20=F0=9F=A4=96=20migrate=20oidc=20fields?= =?UTF-8?q?=20to=20keyvalue=20component=20(#3160)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/auth-method/oidc/index.hbs | 228 +++++++++--------- .../components/form/auth-method/oidc/index.js | 74 +++--- .../scopes/scope/auth-methods/index.js | 33 +++ .../routes/scopes/scope/auth-methods/new.js | 6 +- .../acceptance/auth-methods/selectors.js | 33 ++- .../acceptance/auth-methods/update-test.js | 3 - 6 files changed, 202 insertions(+), 175 deletions(-) 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 63f2b5ada..45150cfb1 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.hbs +++ b/ui/admin/app/components/form/auth-method/oidc/index.hbs @@ -146,113 +146,109 @@ {{/unless}} - {{! Signing Algorithms }} - - <:fieldset as |F|> - - {{t 'form.signing_algorithms.label'}} - - - {{t 'form.signing_algorithms.help'}} - - - {{#if @model.errors.signing_algorithms}} - - {{#each @model.errors.signing_algorithms as |error|}} - {{error.message}} - {{/each}} - - {{/if}} - - - <:field as |F|> - - - - - {{! Allowed Audiences }} - - <:fieldset as |F|> - - {{t 'form.allowed_audiences.label'}} - - - {{t 'form.allowed_audiences.help'}} - - - {{#if @model.errors.allowed_audiences}} - - {{#each @model.errors.allowed_audiences as |error|}} - {{error.message}} + <:row as |R|> + + + + {{#each this.signingAlgorithms as |algorithm|}} + {{/each}} - + + + {{#if R.canDelete}} + {{/if}} - + + - <:field as |F|> - - - - + {{! Allowed audiences }} + + <:row as |R|> + + + + {{#if R.canDelete}} + + {{/if}} + + {{! Claims Scopes }} - - - <:fieldset as |F|> - - {{t 'form.claims_scopes.label'}} - - - {{t 'form.claims_scopes.help'}} - - - {{#if @model.errors.claims_scopes}} - - {{#each @model.errors.claims_scopes as |error|}} - {{error.message}} - {{/each}} - + <:row as |R|> + + + + {{#if R.canDelete}} + {{/if}} - - - <:field as |F|> - - - - + + {{! Account Claim Maps }} {{! Certificates }} - - <:fieldset as |F|> - - {{t 'form.idp_ca_certs.label'}} - - - {{t 'form.idp_ca_certs.help'}} - - - {{#if @model.errors.idp_ca_certs}} - - {{#each @model.errors.idp_ca_certs as |error|}} - {{error.message}} - {{/each}} - + <:row as |R|> + + + + {{#if R.canDelete}} + {{/if}} - - - <:field as |F|> - - - - + + ({ value: '' }); + + // For fields with key and value properties + createEmptyKeyValue = () => ({ key: '', value: '' }); // =attributes /** @@ -55,45 +60,6 @@ export default class FormAuthMethodOidcComponent extends Component { //actions - /** - * Adds a new empty row to account claim maps - */ - @action - addAccountClaimMap() { - this.args.model.account_claim_maps = [ - ...this.args.model.account_claim_maps, - { key: '', value: '' }, - ]; - } - - /** - * Removes a row from account claim maps - * @param {Object} rowData - The row to remove - */ - @action - removeAccountClaimMap(rowData) { - let rows = this.args.model.account_claim_maps.filter( - (item) => item !== rowData, - ); - - // Ensure at least one empty row exists for editing - if (rows.length === 0) { - rows = [{ key: '', value: '' }]; - } - this.args.model.account_claim_maps = rows; - } - - /** - * Updates the account claim maps in the model - */ - @action - updateAccountClaimMap(rowData, property, { target: { value } }) { - rowData[property] = value; - this.args.model.account_claim_maps = [ - ...this.args.model.account_claim_maps, - ]; - } - /** * @param {string} value */ @@ -128,4 +94,34 @@ export default class FormAuthMethodOidcComponent extends Component { this.args.model.prompts = [...removeSelection]; } } + + /** + * Adds a new empty row to account claim maps + */ + @action + addRow(field, emptyRow) { + this.args.model[field] = [...this.args.model[field], emptyRow()]; + } + + /** + * Removes a row from account claim maps + */ + @action + removeRow(field, emptyRow, rowData) { + let rows = this.args.model[field].filter((item) => item !== rowData); + // Ensure at least one empty row exists for editing + if (rows.length === 0) { + rows = [emptyRow()]; + } + this.args.model[field] = rows; + } + + /** + * Updates the account claim maps in the model + */ + @action + updateRow(field, rowData, property, { target: { value } }) { + rowData[property] = value; + this.args.model[field] = [...this.args.model[field]]; + } } diff --git a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js index f41d059b5..8b287d3a4 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js @@ -153,6 +153,26 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { (item) => item.key?.trim(), ); } + if (authMethod.claims_scopes) { + authMethod.claims_scopes = authMethod.claims_scopes.filter((item) => + item.value?.trim(), + ); + } + if (authMethod.allowed_audiences) { + authMethod.allowed_audiences = authMethod.allowed_audiences.filter( + (item) => item.value?.trim(), + ); + } + if (authMethod.signing_algorithms) { + authMethod.signing_algorithms = authMethod.signing_algorithms.filter( + (item) => item.value?.trim(), + ); + } + if (authMethod.idp_ca_certs) { + authMethod.idp_ca_certs = authMethod.idp_ca_certs.filter((item) => + item.value?.trim(), + ); + } await authMethod.save(); if (this.abilities.can('read model', authMethod)) { await this.router.transitionTo( @@ -296,19 +316,32 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { edit(authMethod) { if (authMethod.claims_scopes) { authMethod.claims_scopes = structuredClone(authMethod.claims_scopes); + // Ensure at least one empty row exists for editing + if (authMethod.claims_scopes.length === 0) { + authMethod.claims_scopes = [{ value: '' }]; + } } if (authMethod.signing_algorithms) { authMethod.signing_algorithms = structuredClone( authMethod.signing_algorithms, ); + if (authMethod.signing_algorithms.length === 0) { + authMethod.signing_algorithms = [{ value: '' }]; + } } if (authMethod.allowed_audiences) { authMethod.allowed_audiences = structuredClone( authMethod.allowed_audiences, ); + if (authMethod.allowed_audiences.length === 0) { + authMethod.allowed_audiences = [{ value: '' }]; + } } if (authMethod.idp_ca_certs) { authMethod.idp_ca_certs = structuredClone(authMethod.idp_ca_certs); + if (authMethod.idp_ca_certs.length === 0) { + authMethod.idp_ca_certs = [{ value: '' }]; + } } if (authMethod.account_claim_maps) { authMethod.account_claim_maps = structuredClone( diff --git a/ui/admin/app/routes/scopes/scope/auth-methods/new.js b/ui/admin/app/routes/scopes/scope/auth-methods/new.js index 8e7a59fce..5a9833da7 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods/new.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods/new.js @@ -49,9 +49,13 @@ export default class ScopesScopeAuthMethodsNewRoute extends Route { }); record.scopeModel = scopeModel; - // if the auth method type is OIDC, initialize account_claim_maps with an empty row + // If the auth-method is of type OIDC, initialize the keyValue fields with an empty object. if (params.type === TYPE_AUTH_METHOD_OIDC) { record.account_claim_maps = [{ key: '', value: '' }]; + record.claims_scopes = [{ value: '' }]; + record.allowed_audiences = [{ value: '' }]; + record.signing_algorithms = [{ value: '' }]; + record.idp_ca_certs = [{ value: '' }]; } return record; diff --git a/ui/admin/tests/acceptance/auth-methods/selectors.js b/ui/admin/tests/acceptance/auth-methods/selectors.js index f3b0d8fef..df9f6f8a2 100644 --- a/ui/admin/tests/acceptance/auth-methods/selectors.js +++ b/ui/admin/tests/acceptance/auth-methods/selectors.js @@ -9,34 +9,41 @@ export const FIELD_CLIENT_ID = '[name=client_id]'; export const FIELD_CLIENT_ID_VALUE = 'Client id value'; export const FIELD_CLIENT_SECRET = '[name=client_secret]'; export const FIELD_CLIENT_SECRET_VALUE = 'Client secret value'; -export const FIELD_SIGNING_ALGORITHMS = '[name=signing_algorithms] select'; +export const FIELD_SIGNING_ALGORITHMS = + '[name=signing_algorithms] [data-test-value-input]'; export const FIELD_SIGNING_ALGORITHMS_VALUE = 'RS384'; -export const FIELD_SIGNING_ALGORITHMS_ADD_BTN = '[data-test-add-option-button]'; +export const FIELD_SIGNING_ALGORITHMS_ADD_BTN = + '[name=signing_algorithms] [data-test-add-button]'; export const FIELD_SIGNING_ALGORITHMS_DELETE_BTN = - '[name=signing_algorithms] tbody td:last-child button[aria-label=Remove]'; -export const FIELD_ALLOWED_AUDIENCES = '[name=allowed_audiences] input'; + '[name=signing_algorithms] [data-test-delete-button]'; +export const FIELD_ALLOWED_AUDIENCES = + '[name=allowed_audiences] [data-test-value-input]'; export const FIELD_ALLOWED_AUDIENCES_VALUE = 'Allowed audiences'; export const FIELD_ALLOWED_AUDIENCES_ADD_BTN = - '[name=allowed_audiences] button'; + '[name=allowed_audiences] [data-test-add-button]'; export const FIELD_ALLOWED_AUDIENCES_DELETE_BTN = - '[name=allowed_audiences] tbody td:last-child button[aria-label=Remove]'; -export const FIELD_CLAIMS_SCOPES = '[name=claims_scopes] input'; + '[name=allowed_audiences] [data-test-delete-button]'; +export const FIELD_CLAIMS_SCOPES = + '[name=claims_scopes] [data-test-value-input]'; export const FIELD_CLAIMS_SCOPES_VALUE = 'Claim scopes'; -export const FIELD_CLAIMS_SCOPES_ADD_BTN = '[name=claims_scopes] button'; +export const FIELD_CLAIMS_SCOPES_ADD_BTN = + '[name=claims_scopes] [data-test-add-button]'; export const FIELD_CLAIMS_SCOPES_DELETE_BTN = - '[name=claims_scopes] tbody td:last-child button[aria-label=Remove]'; + '[name=claims_scopes] [data-test-delete-button]'; export const FIELD_ACCOUNT_CLAIM_MAPS_FROM_CLAIM = '[name=account_claim_maps] [data-test-key-input]'; export const FIELD_ACCOUNT_CLAIM_MAPS_FROM_CLAIM_VALUE = 'from_claim'; export const FIELD_ACCOUNT_CLAIM_MAPS_TO_CLAIM = '[name=account_claim_maps] [data-test-value-input]'; export const FIELD_ACCOUNT_CLAIM_MAPS_TO_CLAIM_VALUE = 'email'; -export const FIELD_ACCOUNT_CLAIM_MAPS_DELETE_BTN = '[data-test-delete-button]'; -export const FIELD_IDP_CERTS = '[name=idp_ca_certs] textarea'; +export const FIELD_ACCOUNT_CLAIM_MAPS_DELETE_BTN = + '[name=account_claim_maps] [data-test-delete-button]'; +export const FIELD_IDP_CERTS = '[name=idp_ca_certs] [data-test-value-input]'; export const FIELD_IDP_CERTS_VALUE = 'IDP certificates'; -export const FIELD_IDP_CERTS_ADD_BTN = '[name=idp_ca_certs] button'; +export const FIELD_IDP_CERTS_ADD_BTN = + '[name=idp_ca_certs] [data-test-add-button]'; export const FIELD_IDP_CERTS_DELETE_BTN = - '[name=idp_ca_certs] tbody td:last-child button[aria-label=Remove]'; + '[name=idp_ca_certs] [data-test-delete-button]'; export const FIELD_MAX_AGE = '[name=max_age]'; export const FIELD_MAX_AGE_VALUE = '5'; export const FIELD_API_URL_PREFIX = '[name=api_url_prefix]'; diff --git a/ui/admin/tests/acceptance/auth-methods/update-test.js b/ui/admin/tests/acceptance/auth-methods/update-test.js index 4f4b63bed..f917ce9fe 100644 --- a/ui/admin/tests/acceptance/auth-methods/update-test.js +++ b/ui/admin/tests/acceptance/auth-methods/update-test.js @@ -132,7 +132,6 @@ module('Acceptance | auth-methods | update', function (hooks) { selectors.FIELD_SIGNING_ALGORITHMS, selectors.FIELD_SIGNING_ALGORITHMS_VALUE, ); - await click(selectors.FIELD_SIGNING_ALGORITHMS_ADD_BTN); // Remove all allowed audiences const allowedAudiencesList = findAll( @@ -147,7 +146,6 @@ module('Acceptance | auth-methods | update', function (hooks) { selectors.FIELD_ALLOWED_AUDIENCES, selectors.FIELD_ALLOWED_AUDIENCES_VALUE, ); - await click(selectors.FIELD_ALLOWED_AUDIENCES_ADD_BTN); // Remove all claims scopes const claimsScopeList = await Promise.all( @@ -162,7 +160,6 @@ module('Acceptance | auth-methods | update', function (hooks) { selectors.FIELD_CLAIMS_SCOPES, selectors.FIELD_CLAIMS_SCOPES_VALUE, ); - await click(selectors.FIELD_CLAIMS_SCOPES_ADD_BTN); // Remove all claim maps const claimMaps = await Promise.all(