From 5c47a5b079bc54ef0e11762133ebb0514d03c906 Mon Sep 17 00:00:00 2001 From: Dharini Date: Fri, 30 Jan 2026 17:02:34 -0800 Subject: [PATCH 1/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20migrate=20auth=20me?= =?UTF-8?q?thod=20fields=20to=20keyvalue=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: 🤖 name chore: 🤖 comments --- .../app/controllers/scopes/scope/auth-methods/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) 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 1605d86022..cc0398e334 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js @@ -167,11 +167,19 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { authMethod.signing_algorithms = authMethod.signing_algorithms.filter( (item) => item.value?.trim(), ); +<<<<<<< HEAD } if (authMethod.idp_ca_certs) { authMethod.idp_ca_certs = authMethod.idp_ca_certs.filter((item) => item.value?.trim(), ); +======= + if (authMethod.idp_ca_certs) { + authMethod.idp_ca_certs = authMethod.idp_ca_certs.filter((item) => + item.value?.trim(), + ); + } +>>>>>>> 04729632d (chore: 🤖 migrate auth method fields to keyvalue component) } await authMethod.save(); if (this.can.can('read model', authMethod)) { From 0fee48c5d800f2bdf037da9f0ca8e6eaaf80d587 Mon Sep 17 00:00:00 2001 From: Dharini Date: Wed, 4 Feb 2026 15:52:28 -0800 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=F0=9F=90=9B=20empty=20idp=20cert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controllers/scopes/scope/auth-methods/index.js | 8 -------- 1 file changed, 8 deletions(-) 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 cc0398e334..1605d86022 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js @@ -167,19 +167,11 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { authMethod.signing_algorithms = authMethod.signing_algorithms.filter( (item) => item.value?.trim(), ); -<<<<<<< HEAD } if (authMethod.idp_ca_certs) { authMethod.idp_ca_certs = authMethod.idp_ca_certs.filter((item) => item.value?.trim(), ); -======= - if (authMethod.idp_ca_certs) { - authMethod.idp_ca_certs = authMethod.idp_ca_certs.filter((item) => - item.value?.trim(), - ); - } ->>>>>>> 04729632d (chore: 🤖 migrate auth method fields to keyvalue component) } await authMethod.save(); if (this.can.can('read model', authMethod)) { From 5043fdf1f3d1056f83d344b97bb5fcaf0579085a Mon Sep 17 00:00:00 2001 From: Dharini Date: Thu, 29 Jan 2026 16:10:16 -0800 Subject: [PATCH 3/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20use=20hds=20keyvalu?= =?UTF-8?q?e=20component=20(#3027)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/form/auth-method/oidc/index.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/ui/admin/app/components/form/auth-method/oidc/index.js b/ui/admin/app/components/form/auth-method/oidc/index.js index f0355e4261..ee0e303b56 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.js +++ b/ui/admin/app/components/form/auth-method/oidc/index.js @@ -60,6 +60,45 @@ 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 */ From 671da74217d7d002129345d5c2c7b564c39a7645 Mon Sep 17 00:00:00 2001 From: Dharini Date: Wed, 4 Feb 2026 16:28:19 -0800 Subject: [PATCH 4/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20migrate=20ldap=20li?= =?UTF-8?q?stwrapper=20field=20to=20keyval?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: 🤖 remove comment chore: 🤖 remove unused chore: 🤖 account_attr_maps migration chore: 🤖 name fix: 🐛 name --- .../app/components/form/auth-method/index.hbs | 3 + .../app/components/form/auth-method/index.js | 40 ++++++ .../form/auth-method/ldap/index.hbs | 127 +++++++++--------- .../components/form/auth-method/ldap/index.js | 3 + .../components/form/auth-method/oidc/index.js | 70 ---------- .../scopes/scope/auth-methods/index.js | 16 +++ .../routes/scopes/scope/auth-methods/new.js | 10 +- .../acceptance/auth-methods/create-test.js | 4 +- .../acceptance/auth-methods/selectors.js | 15 ++- .../acceptance/auth-methods/update-test.js | 2 - 10 files changed, 145 insertions(+), 145 deletions(-) diff --git a/ui/admin/app/components/form/auth-method/index.hbs b/ui/admin/app/components/form/auth-method/index.hbs index b90392ee01..1b49fc1dfa 100644 --- a/ui/admin/app/components/form/auth-method/index.hbs +++ b/ui/admin/app/components/form/auth-method/index.hbs @@ -11,5 +11,8 @@ @removeItemByIndex={{@removeItemByIndex}} @addStringItem={{@addStringItem}} @addAccountMapItem={{@addAccountMapItem}} + @addRow={{this.addRow}} + @removeRow={{this.removeRow}} + @updateRow={{this.updateRow}} /> {{/if}} \ No newline at end of file diff --git a/ui/admin/app/components/form/auth-method/index.js b/ui/admin/app/components/form/auth-method/index.js index 168acb9f39..d441282ef2 100644 --- a/ui/admin/app/components/form/auth-method/index.js +++ b/ui/admin/app/components/form/auth-method/index.js @@ -5,6 +5,7 @@ import Component from '@glimmer/component'; import { assert } from '@ember/debug'; +import { action } from '@ember/object'; import oidc from './oidc'; import ldap from './ldap'; import password from './password'; @@ -24,4 +25,43 @@ export default class FormAuthMethodIndex extends Component { ); return component; } + + /** + * Adds a new empty row to the specified field + * @param {string} field - The field name to add a row to + * @param {function} emptyRow - Function that returns an empty row object + */ + @action + addRow(field, emptyRow) { + this.args.model[field] = [...this.args.model[field], emptyRow()]; + } + + /** + * Removes a row from the specified field + * @param {string} field - The field name to remove a row from + * @param {function} emptyRow - Function that returns an empty row object (to ensure at least one row exists) + * @param {object} rowData - The row data to remove + */ + @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 a specific property in a row + * @param {string} field - The field name containing the row + * @param {object} rowData - The row object to update + * @param {string} property - The property name to update + * @param {object} event - The DOM event containing the new value + */ + @action + updateRow(field, rowData, property, { target: { value } }) { + rowData[property] = value; + this.args.model[field] = [...this.args.model[field]]; + } } diff --git a/ui/admin/app/components/form/auth-method/ldap/index.hbs b/ui/admin/app/components/form/auth-method/ldap/index.hbs index 15b7bf96c0..8c3ba94940 100644 --- a/ui/admin/app/components/form/auth-method/ldap/index.hbs +++ b/ui/admin/app/components/form/auth-method/ldap/index.hbs @@ -82,37 +82,31 @@ {{/if}} - - <:fieldset as |F|> - - {{t 'resources.auth-method.form.certificates.label'}} - - - {{t 'resources.auth-method.form.certificates.help'}} - - - {{#if @model.errors.certificates}} - - {{#each @model.errors.certificates as |error|}} - {{error.message}} - {{/each}} - + <:row as |R|> + + + + {{#if R.canDelete}} + {{/if}} - - - <:field as |F|> - - - - + + {{#if @model.isNew}} - - <:fieldset as |F|> - - {{t 'resources.auth-method.form.account_attribute_maps.label'}} - - - {{t 'resources.auth-method.form.account_attribute_maps.help'}} - - - {{#if @model.errors.account_attribute_maps}} - - {{#each @model.errors.account_attribute_maps as |error|}} - {{error.message}} + <:row as |R|> + + {{t 'resources.auth-method.titles.from-attr'}} + + + + {{t 'resources.auth-method.titles.to-attr'}} + + + {{#each this.toAttributes as |attr|}} + {{/each}} - + + + {{#if R.canDelete}} + {{/if}} - - <:field as |F|> - - <:key as |K|> - - - <:value as |V|> - - - - - + +
({ value: '' }); + createEmptyAttributeMaps = () => ({ key: '', value: '' }); + // =attributes /** * @type {object} diff --git a/ui/admin/app/components/form/auth-method/oidc/index.js b/ui/admin/app/components/form/auth-method/oidc/index.js index ee0e303b56..d1dbfa4747 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.js +++ b/ui/admin/app/components/form/auth-method/oidc/index.js @@ -59,46 +59,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 */ @@ -133,34 +93,4 @@ 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 1605d86022..453eae29e8 100644 --- a/ui/admin/app/controllers/scopes/scope/auth-methods/index.js +++ b/ui/admin/app/controllers/scopes/scope/auth-methods/index.js @@ -173,6 +173,15 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { item.value?.trim(), ); } + if (authMethod.certificates) { + authMethod.certificates = authMethod.certificates.filter((item) => + item.value?.trim(), + ); + } + if (authMethod.account_attribute_maps) { + authMethod.account_attribute_maps = + authMethod.account_attribute_maps.filter((item) => item.key?.trim()); + } await authMethod.save(); if (this.can.can('read model', authMethod)) { await this.router.transitionTo( @@ -354,11 +363,18 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller { } if (authMethod.certificates) { authMethod.certificates = structuredClone(authMethod.certificates); + if (authMethod.certificates.length === 0) { + authMethod.certificates = [{ value: '' }]; + } } if (authMethod.account_attribute_maps) { authMethod.account_attribute_maps = structuredClone( authMethod.account_attribute_maps, ); + // Ensure at least one empty row exists for editing + if (authMethod.account_attribute_maps.length === 0) { + authMethod.account_attribute_maps = [{ key: '', value: '' }]; + } } } 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 bce8065534..318257ba55 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods/new.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods/new.js @@ -5,7 +5,10 @@ import Route from '@ember/routing/route'; import { service } from '@ember/service'; -import { TYPE_AUTH_METHOD_OIDC } from 'api/models/auth-method'; +import { + TYPE_AUTH_METHOD_OIDC, + TYPE_AUTH_METHOD_LDAP, +} from 'api/models/auth-method'; export default class ScopesScopeAuthMethodsNewRoute extends Route { // =services @@ -57,6 +60,11 @@ export default class ScopesScopeAuthMethodsNewRoute extends Route { record.signing_algorithms = [{ value: '' }]; record.idp_ca_certs = [{ value: '' }]; } + // If the auth-method is of type LDAP, initialize the certificates field with an empty object. + if (params.type === TYPE_AUTH_METHOD_LDAP) { + record.certificates = [{ value: '' }]; + record.account_attribute_maps = [{ key: '', value: '' }]; + } return record; } diff --git a/ui/admin/tests/acceptance/auth-methods/create-test.js b/ui/admin/tests/acceptance/auth-methods/create-test.js index d9db1ca772..88084c3a13 100644 --- a/ui/admin/tests/acceptance/auth-methods/create-test.js +++ b/ui/admin/tests/acceptance/auth-methods/create-test.js @@ -214,7 +214,7 @@ module('Acceptance | auth-methods | create', function (hooks) { selectors.FIELD_CERTIFICATES, selectors.FIELD_CERTIFICATES_VALUE, ); - await click(selectors.FIELD_CERTIFICATES_ADD_BTN); + await fillIn( selectors.FIELD_CLIENT_CERTIFICATE, selectors.FIELD_CLIENT_CERTIFICATE_VALUE, @@ -247,7 +247,7 @@ module('Acceptance | auth-methods | create', function (hooks) { selectors.FIELD_ACCOUNT_ATTRIBUTE_MAPS_TO, selectors.FIELD_ACCOUNT_ATTRIBUTE_MAPS_TO_VALUE, ); - await click(selectors.FIELD_ACCOUNT_ATTRIBUTE_MAPS_ADD_BTN); + await fillIn(selectors.FIELD_GROUP_DN, selectors.FIELD_GROUP_DN_VALUE); await fillIn(selectors.FIELD_GROUP_ATTR, selectors.FIELD_GROUP_ATTR_VALUE); await fillIn( diff --git a/ui/admin/tests/acceptance/auth-methods/selectors.js b/ui/admin/tests/acceptance/auth-methods/selectors.js index df9f6f8a2c..535d4b6c55 100644 --- a/ui/admin/tests/acceptance/auth-methods/selectors.js +++ b/ui/admin/tests/acceptance/auth-methods/selectors.js @@ -54,11 +54,12 @@ export const FIELD_PROMPTS_SELECT_ACCOUNT = '[id=select_account]'; export const NEW_DROPDOWN = '[data-test-new-dropdown] button'; export const FIELD_URLS = '[name=urls]'; export const FIELD_URLS_VALUE = 'url1,url2'; -export const FIELD_CERTIFICATES = '[name=certificates] textarea'; +export const FIELD_CERTIFICATES = '[name=certificates] [data-test-value-input]'; export const FIELD_CERTIFICATES_VALUE = 'certificate'; -export const FIELD_CERTIFICATES_ADD_BTN = '[name=certificates] button'; +export const FIELD_CERTIFICATES_ADD_BTN = + '[name=certificates] [data-test-add-button]'; export const FIELD_CERTIFICATES_DELETE_BTN = - '[name="certificates"] button[aria-label=Remove]'; + '[name="certificates"] [data-test-delete-button]'; export const FIELD_CLIENT_CERTIFICATE = '[name=client_certificate]'; export const FIELD_CLIENT_CERTIFICATE_VALUE = 'Client certificate value'; export const FIELD_CLIENT_CERTIFICATE_KEY = '[name=client_certificate_key]'; @@ -81,15 +82,15 @@ export const FIELD_USER_ATTR_VALUE = 'User attribute value'; export const FIELD_USER_FILTER = '[name=user_filter]'; export const FIELD_USER_FILTER_VALUE = 'User filter value'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_FROM = - '[name=account_attribute_maps] input'; + '[name=account_attribute_maps] [data-test-key-input]'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_FROM_VALUE = 'attribute'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_TO = - '[name=account_attribute_maps] select'; + '[name=account_attribute_maps] [data-test-value-input]'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_TO_VALUE = 'email'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_ADD_BTN = - '[name=account_attribute_maps] button'; + '[name=account_attribute_maps] [data-test-add-button]'; export const FIELD_ACCOUNT_ATTRIBUTE_MAPS_DELETE_BTN = - '[name=account_attribute_maps] button[aria-label=Remove]'; + '[name=account_attribute_maps] [data-test-delete-button]'; export const FIELD_GROUP_DN = '[name=group_dn]'; export const FIELD_GROUP_DN_VALUE = 'Group dn value'; export const FIELD_GROUP_ATTR = '[name=group_attr]'; diff --git a/ui/admin/tests/acceptance/auth-methods/update-test.js b/ui/admin/tests/acceptance/auth-methods/update-test.js index f917ce9fe0..eabdf1bacd 100644 --- a/ui/admin/tests/acceptance/auth-methods/update-test.js +++ b/ui/admin/tests/acceptance/auth-methods/update-test.js @@ -267,8 +267,6 @@ module('Acceptance | auth-methods | update', function (hooks) { selectors.FIELD_CERTIFICATES, selectors.FIELD_CERTIFICATES_VALUE, ); - await click(selectors.FIELD_CERTIFICATES_ADD_BTN); - await click(selectors.FIELD_START_TLS); await click(selectors.FIELD_INSECURE_TLS); await fillIn(selectors.FIELD_BIND_DN, selectors.FIELD_BIND_DN_VALUE); From 7c229b7042fd2a0d3c4e08847f79094044aa1197 Mon Sep 17 00:00:00 2001 From: Dharini Date: Tue, 10 Feb 2026 15:12:21 -0800 Subject: [PATCH 5/8] =?UTF-8?q?chore:=20=F0=9F=A4=96=20feedback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form/auth-method/ldap/index.hbs | 10 ++--- .../components/form/auth-method/ldap/index.js | 7 +++- .../form/auth-method/oidc/index.hbs | 38 +++++++++---------- .../acceptance/auth-methods/selectors.js | 6 +-- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/ui/admin/app/components/form/auth-method/ldap/index.hbs b/ui/admin/app/components/form/auth-method/ldap/index.hbs index 8c3ba94940..d0ffd3101b 100644 --- a/ui/admin/app/components/form/auth-method/ldap/index.hbs +++ b/ui/admin/app/components/form/auth-method/ldap/index.hbs @@ -85,8 +85,8 @@ - {{#each this.toAttributes as |attr|}} diff --git a/ui/admin/app/components/form/auth-method/ldap/index.js b/ui/admin/app/components/form/auth-method/ldap/index.js index 32152e7327..afc4321e99 100644 --- a/ui/admin/app/components/form/auth-method/ldap/index.js +++ b/ui/admin/app/components/form/auth-method/ldap/index.js @@ -10,8 +10,11 @@ import { options } from 'api/models/auth-method'; import { set } from '@ember/object'; export default class FormAuthMethodLdapComponent extends Component { - createEmptyCertificates = () => ({ value: '' }); - createEmptyAttributeMaps = () => ({ key: '', value: '' }); + // For fields with just a value property + createEmptyValue = () => ({ value: '' }); + + // For fields with key and value properties + createEmptyKeyValue = () => ({ key: '', value: '' }); // =attributes /** 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 45150cfb19..d54f1713e5 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.hbs +++ b/ui/admin/app/components/form/auth-method/oidc/index.hbs @@ -150,9 +150,9 @@