Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ui/admin/app/components/form/auth-method/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@
@removeItemByIndex={{@removeItemByIndex}}
@addStringItem={{@addStringItem}}
@addAccountMapItem={{@addAccountMapItem}}
@addRow={{this.addRow}}
@removeRow={{this.removeRow}}
@updateRow={{this.updateRow}}
/>
{{/if}}
44 changes: 44 additions & 0 deletions ui/admin/app/components/form/auth-method/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -24,4 +25,47 @@ 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 {Array<string>} properties - Array of property names for the empty row (e.g., ['value'] or ['key', 'value'])
*/
@action
addRow(field, properties) {
const emptyRow = Object.fromEntries(properties.map((prop) => [prop, '']));
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 {object} rowData - The row data to remove
*/
@action
removeRow(field, rowData) {
let rows = this.args.model[field].filter((item) => item !== rowData);
// Ensure at least one empty row exists for editing
if (rows.length === 0) {
const emptyRow = Object.fromEntries(
Object.keys(rowData).map((key) => [key, '']),
);
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]];
}
}
123 changes: 60 additions & 63 deletions ui/admin/app/components/form/auth-method/ldap/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -82,37 +82,31 @@
{{/if}}
</Hds::Form::TextInput::Field>

<Form::Field::ListWrapper
@layout='horizontal'
@isOptional={{true}}
<Form::Field::KeyValue
@name='certificates'
@data={{@model.certificates}}
@onAdd={{fn @addRow 'certificates' (array 'value')}}
@onRemove={{fn @removeRow 'certificates'}}
@onUpdate={{fn @updateRow 'certificates'}}
@legend={{t 'resources.auth-method.form.certificates.label'}}
@helperText={{t 'resources.auth-method.form.certificates.help'}}
@errors={{@model.errors.certificates}}
@disabled={{form.disabled}}
@isOptional={{true}}
>
<:fieldset as |F|>
<F.Legend>
{{t 'resources.auth-method.form.certificates.label'}}
</F.Legend>
<F.HelperText>
{{t 'resources.auth-method.form.certificates.help'}}
</F.HelperText>

{{#if @model.errors.certificates}}
<F.Error as |E|>
{{#each @model.errors.certificates as |error|}}
<E.Message>{{error.message}}</E.Message>
{{/each}}
</F.Error>
<:row as |R|>
<R.Field as |F|>
<F.Textarea
data-test-value-input
@value={{R.rowData.value}}
{{on 'input' (fn R.updateRow 'value')}}
/>
</R.Field>
{{#if R.canDelete}}
<R.DeleteRowButton data-test-delete-button @onClick={{R.removeRow}} />
{{/if}}
</:fieldset>

<:field as |F|>
<F.Textarea
@name='certificates'
@options={{@model.certificates}}
@model={{@model}}
/>
</:field>

</Form::Field::ListWrapper>
</:row>
</Form::Field::KeyValue>

{{#if @model.isNew}}
<Hds::Form::TextInput::Field
Expand Down Expand Up @@ -406,45 +400,48 @@
}}</F.HelperText>
</Hds::Form::TextInput::Field>

<Form::Field::ListWrapper
@layout='horizontal'
@isOptional={{true}}
<Form::field::KeyValue
@name='account_attribute_maps'
@data={{@model.account_attribute_maps}}
@onAdd={{fn @addRow 'account_attribute_maps' (array 'key' 'value')}}
@onRemove={{fn @removeRow 'account_attribute_maps'}}
@onUpdate={{fn @updateRow 'account_attribute_maps'}}
@legend={{t 'resources.auth-method.form.account_attribute_maps.label'}}
@helperText={{t 'resources.auth-method.form.account_attribute_maps.help'}}
@errors={{@model.errors.account_attribute_maps}}
@disabled={{form.disabled}}
@isOptional={{true}}
>
<:fieldset as |F|>
<F.Legend>
{{t 'resources.auth-method.form.account_attribute_maps.label'}}
</F.Legend>
<F.HelperText>
{{t 'resources.auth-method.form.account_attribute_maps.help'}}
</F.HelperText>

{{#if @model.errors.account_attribute_maps}}
<F.Error as |E|>
{{#each @model.errors.account_attribute_maps as |error|}}
<E.Message>{{error.message}}</E.Message>
<:row as |R|>
<R.Field as |F|>
<F.Label>{{t 'resources.auth-method.titles.from-attr'}}</F.Label>
<F.TextInput
data-test-key-input
@value={{R.rowData.key}}
{{on 'input' (fn R.updateRow 'key')}}
/>
</R.Field>
<R.Field as |F|>
<F.Label>{{t 'resources.auth-method.titles.to-attr'}}</F.Label>
<F.Select
data-test-value-select
{{on 'change' (fn R.updateRow 'value')}}
>
<option disabled hidden selected value=''>
{{t 'titles.choose-an-option'}}
</option>
{{#each this.toAttributes as |attr|}}
<option value={{attr}} selected={{eq R.rowData.value attr}}>
{{attr}}
</option>
{{/each}}
</F.Error>
</F.Select>
</R.Field>
{{#if R.canDelete}}
<R.DeleteRowButton data-test-delete-button @onClick={{R.removeRow}} />
{{/if}}
</:fieldset>
<:field as |F|>
<F.KeyValue
@name='account_attribute_maps'
@options={{@model.account_attribute_maps}}
@model={{@model}}
@keyLabel={{t 'resources.auth-method.titles.from-attr'}}
@valueLabel={{t 'resources.auth-method.titles.to-attr'}}
@width='100%'
>
<:key as |K|>
<K.text />
</:key>
<:value as |V|>
<V.select @selectOptions={{this.toAttributes}} />
</:value>
</F.KeyValue>
</:field>
</Form::Field::ListWrapper>
</:row>
</Form::field::KeyValue>

<div class='ldap-section'>
<Hds::Text::Display
Expand Down
38 changes: 17 additions & 21 deletions ui/admin/app/components/form/auth-method/oidc/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@
<Form::Field::KeyValue
@name='signing_algorithms'
@data={{@model.signing_algorithms}}
@onAdd={{fn this.addRow 'signing_algorithms' this.createEmptyValue}}
@onRemove={{fn this.removeRow 'signing_algorithms' this.createEmptyValue}}
@onUpdate={{fn this.updateRow 'signing_algorithms'}}
@onAdd={{fn @addRow 'signing_algorithms' (array 'value')}}
@onRemove={{fn @removeRow 'signing_algorithms'}}
@onUpdate={{fn @updateRow 'signing_algorithms'}}
@legend={{t 'form.signing_algorithms.label'}}
@helperText={{t 'form.signing_algorithms.help'}}
@errors={{@model.errors.signing_algorithms}}
Expand All @@ -162,7 +162,7 @@
<:row as |R|>
<R.Field as |F|>
<F.Select
data-test-value-input
data-test-value-select
{{on 'change' (fn R.updateRow 'value')}}
>
<option disabled hidden selected value=''>
Expand All @@ -188,9 +188,9 @@
<Form::Field::KeyValue
@name='allowed_audiences'
@data={{@model.allowed_audiences}}
@onAdd={{fn this.addRow 'allowed_audiences' this.createEmptyValue}}
@onRemove={{fn this.removeRow 'allowed_audiences' this.createEmptyValue}}
@onUpdate={{fn this.updateRow 'allowed_audiences'}}
@onAdd={{fn @addRow 'allowed_audiences' (array 'value')}}
@onRemove={{fn @removeRow 'allowed_audiences'}}
@onUpdate={{fn @updateRow 'allowed_audiences'}}
@legend={{t 'form.allowed_audiences.label'}}
@helperText={{t 'form.allowed_audiences.help'}}
@errors={{@model.errors.allowed_audiences}}
Expand All @@ -215,9 +215,9 @@
<Form::Field::KeyValue
@name='claims_scopes'
@data={{@model.claims_scopes}}
@onAdd={{fn this.addRow 'claims_scopes' this.createEmptyValue}}
@onRemove={{fn this.removeRow 'claims_scopes' this.createEmptyValue}}
@onUpdate={{fn this.updateRow 'claims_scopes'}}
@onAdd={{fn @addRow 'claims_scopes' (array 'value')}}
@onRemove={{fn @removeRow 'claims_scopes'}}
@onUpdate={{fn @updateRow 'claims_scopes'}}
@legend={{t 'form.claims_scopes.label'}}
@helperText={{t 'form.claims_scopes.help'}}
@errors={{@model.errors.claims_scopes}}
Expand All @@ -242,13 +242,9 @@
<Form::Field::KeyValue
@name='account_claim_maps'
@data={{@model.account_claim_maps}}
@onAdd={{fn this.addRow 'account_claim_maps' this.createEmptyKeyValue}}
@onRemove={{fn
this.removeRow
'account_claim_maps'
this.createEmptyKeyValue
}}
@onUpdate={{fn this.updateRow 'account_claim_maps'}}
@onAdd={{fn @addRow 'account_claim_maps' (array 'key' 'value')}}
@onRemove={{fn @removeRow 'account_claim_maps'}}
@onUpdate={{fn @updateRow 'account_claim_maps'}}
@legend={{t 'form.account_claim_maps.label'}}
@helperText={{t 'form.account_claim_maps.help'}}
@errors={{@model.errors.account_claim_maps}}
Expand All @@ -268,7 +264,7 @@
<R.Field as |F|>
<F.Label>{{t 'form.to_claim.label'}}</F.Label>
<F.Select
data-test-value-input
data-test-value-select
{{on 'change' (fn R.updateRow 'value')}}
>
<option disabled hidden selected value=''>
Expand All @@ -292,9 +288,9 @@
<Form::Field::KeyValue
@name='idp_ca_certs'
@data={{@model.idp_ca_certs}}
@onAdd={{fn this.addRow 'idp_ca_certs' this.createEmptyValue}}
@onRemove={{fn this.removeRow 'idp_ca_certs' this.createEmptyValue}}
@onUpdate={{fn this.updateRow 'idp_ca_certs'}}
@onAdd={{fn @addRow 'idp_ca_certs' (array 'value')}}
@onRemove={{fn @removeRow 'idp_ca_certs'}}
@onUpdate={{fn @updateRow 'idp_ca_certs'}}
@legend={{t 'form.idp_ca_certs.label'}}
@helperText={{t 'form.idp_ca_certs.help'}}
@errors={{@model.errors.idp_ca_certs}}
Expand Down
36 changes: 0 additions & 36 deletions ui/admin/app/components/form/auth-method/oidc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';

export default class FormAuthMethodOidcComponent extends Component {
// For fields with just a value property
createEmptyValue = () => ({ value: '' });

// For fields with key and value properties
createEmptyKeyValue = () => ({ key: '', value: '' });
// =attributes

/**
Expand Down Expand Up @@ -59,7 +54,6 @@ export default class FormAuthMethodOidcComponent extends Component {
}

//actions

/**
* @param {string} value
*/
Expand Down Expand Up @@ -94,34 +88,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]];
}
}
2 changes: 1 addition & 1 deletion ui/admin/app/components/form/field/key-value/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (c) HashiCorp, Inc.
* Copyright IBM Corp. 2021, 2026
* SPDX-License-Identifier: BUSL-1.1
*/

Expand Down
16 changes: 16 additions & 0 deletions ui/admin/app/controllers/scopes/scope/auth-methods/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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: '' }];
}
}
}

Expand Down
Loading