Icu 10104 ldap accounts update (#1785)
* chore: 🤖 Add support for ldap account creation
This commit is contained in:
1 parent
e3557e297b
commit
05d62f3da5
9 files changed
+238
-122
No files matched your search
@@ -32,7 +32,7 @@ export default factory.extend({
|
||||
case TYPE_AUTH_METHOD_PASSWORD:
|
||||
return { login_name: faker.internet.userName() };
|
||||
case TYPE_AUTH_METHOD_LDAP: {
|
||||
const groupsAmount = faker.datatype.number({ min: 1, max: 3 });
|
||||
const groupsAmount = faker.datatype.number({ min: 3, max: 5 });
|
||||
let groups = [];
|
||||
for (let i = 0; i < groupsAmount; i++) {
|
||||
groups.push(faker.random.word());
|
||||
|
||||
@@ -173,3 +173,6 @@ secret-editor:
|
||||
edit: Click to replace this secret
|
||||
created:
|
||||
label: Created
|
||||
other_fields:
|
||||
label: Other Fields
|
||||
help: This information is provided by the server and cannot be edited in Boundary
|
||||
@@ -14,11 +14,23 @@ account:
|
||||
types:
|
||||
password: Password
|
||||
oidc: OIDC
|
||||
ldap: LDAP
|
||||
titles:
|
||||
new: New Account
|
||||
actions:
|
||||
create: Create Account
|
||||
delete: Delete Account
|
||||
form:
|
||||
login_name:
|
||||
label: Login Name
|
||||
email:
|
||||
label: Email
|
||||
dn:
|
||||
label: Dn
|
||||
member_of_groups:
|
||||
label: Group Names
|
||||
full_name:
|
||||
label: Full Name
|
||||
auth-method:
|
||||
title: Auth Method
|
||||
title_plural: Auth Methods
|
||||
|
||||
@@ -52,27 +52,64 @@
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
{{#if @model.isNew}}
|
||||
<Hds::Form::TextInput::Field
|
||||
@isRequired={{true}}
|
||||
name='login_name'
|
||||
@value={{@model.login_name}}
|
||||
@isInvalid={{@model.errors.login_name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'login_name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.login_name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.login_name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.login_name}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.login_name as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
<Hds::Form::TextInput::Field
|
||||
@isRequired={{true}}
|
||||
name='login_name'
|
||||
@value={{@model.login_name}}
|
||||
@isInvalid={{@model.errors.login_name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'login_name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.login_name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.login_name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.login_name}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.login_name as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{#unless @model.isNew}}
|
||||
<Hds::Form::Fieldset class='ldap-read-only-fields' as |F|>
|
||||
|
||||
<F.Control>
|
||||
<div class='ldap-section'>
|
||||
<p class='hds-typography-display-300 hds-font-weight-bold'>{{t
|
||||
'form.other_fields.label'
|
||||
}}</p>
|
||||
<Hds::Form::HelperText @controlId='helper-text-for-section'>{{t
|
||||
'form.other_fields.help'
|
||||
}}</Hds::Form::HelperText>
|
||||
</div>
|
||||
<InfoField @value={{@model.login_name}} as |F|>
|
||||
<F.Label>{{t 'form.login_name.label'}}</F.Label>
|
||||
</InfoField>
|
||||
<InfoField @value={{@model.email}} as |F|>
|
||||
<F.Label>{{t 'resources.account.form.email.label'}}</F.Label>
|
||||
</InfoField>
|
||||
<InfoField @value={{@model.full_name}} as |F|>
|
||||
<F.Label>{{t 'resources.account.form.full_name.label'}}</F.Label>
|
||||
</InfoField>
|
||||
<InfoField @value={{@model.dn}} as |F|>
|
||||
<F.Label>{{t 'resources.account.form.dn.label'}}</F.Label>
|
||||
</InfoField>
|
||||
<p class='hds-font-weight-semibold'>{{t
|
||||
'resources.account.form.member_of_groups.label'
|
||||
}}</p>
|
||||
{{#each @model.member_of_groups as |group|}}
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{group.value}}
|
||||
disabled={{true}}
|
||||
/>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
</F.Control>
|
||||
</Hds::Form::Fieldset>
|
||||
{{/unless}}
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
@enableEditText={{t 'actions.edit-form'}}
|
||||
|
||||
@@ -908,6 +908,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ldap-read-only-fields .hds-form-field--layout-vertical {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
// Session recording - List
|
||||
.session-recording-list-cell-item {
|
||||
display: flex;
|
||||
|
||||
@@ -25,110 +25,148 @@
|
||||
{{#if @model.accounts}}
|
||||
{{! OIDC accounts display more fields }}
|
||||
{{#if @model.accounts.firstObject.isOIDC}}
|
||||
<Rose::Table as |table|>
|
||||
<table.header as |header|>
|
||||
<header.row as |row|>
|
||||
<row.headerCell>{{t 'form.name.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.issuer.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.subject.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.email.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.full_name.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.type.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.id.label'}}</row.headerCell>
|
||||
</header.row>
|
||||
</table.header>
|
||||
<table.body as |body|>
|
||||
{{#each @model.accounts as |account|}}
|
||||
<body.row as |row|>
|
||||
<row.headerCell scope='row'>
|
||||
{{#if (can 'read account' account)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account'
|
||||
@model={{account.id}}
|
||||
>
|
||||
{{account.accountName}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
{{account.accountName}}
|
||||
{{/if}}
|
||||
<p>{{account.description}}</p>
|
||||
</row.headerCell>
|
||||
<row.cell>
|
||||
<code>{{account.issuer}}</code>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<code>{{account.subject}}</code>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<code>{{account.email}}</code>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
{{account.full_name}}
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Hds::Badge @text={{account.type}} />
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Copyable
|
||||
@text={{account.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
<Hds::Table
|
||||
@model={{@model.accounts}}
|
||||
@columns={{array
|
||||
(hash label=(t 'form.name.label'))
|
||||
(hash label=(t 'form.issuer.label'))
|
||||
(hash label=(t 'form.subject.label'))
|
||||
(hash label=(t 'form.email.label'))
|
||||
(hash label=(t 'form.full_name.label'))
|
||||
(hash label=(t 'form.type.label'))
|
||||
(hash label=(t 'form.id.label'))
|
||||
}}
|
||||
@valign='middle'
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
{{#if (can 'read account' B.data)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account'
|
||||
@model={{B.data.id}}
|
||||
>
|
||||
<code>{{account.id}}</code>
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
</table.body>
|
||||
</Rose::Table>
|
||||
{{B.data.accountName}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
{{B.data.accountName}}
|
||||
{{/if}}
|
||||
<p>{{B.data.description}}</p>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.issuer}}
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.subject}}
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.email}}
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.full_name}}
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Hds::Badge @text={{B.data.type}} />
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Copyable
|
||||
@text={{B.data.account.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{B.data.account.id}}</code>
|
||||
</Copyable>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{else if @model.accounts.firstObject.isLDAP}}
|
||||
<Hds::Table
|
||||
@model={{@model.accounts}}
|
||||
@columns={{array
|
||||
(hash label=(t 'resources.account.form.login_name.label'))
|
||||
(hash label=(t 'resources.account.form.email.label'))
|
||||
(hash label=(t 'resources.account.form.full_name.label'))
|
||||
(hash label=(t 'resources.account.form.dn.label'))
|
||||
(hash label=(t 'resources.account.form.member_of_groups.label'))
|
||||
}}
|
||||
@valign='middle'
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
{{#if (can 'read account' B.data)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account'
|
||||
@model={{B.data.id}}
|
||||
>
|
||||
{{B.data.displayName}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
{{B.data.displayName}}
|
||||
{{/if}}
|
||||
<p>{{B.data.description}}</p>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.email}}
|
||||
</B.Td>
|
||||
<B.Td>{{B.data.full_name}}</B.Td>
|
||||
|
||||
<B.Td>{{B.data.dn}}</B.Td>
|
||||
<B.Td>
|
||||
<div class='truncated-list'>
|
||||
{{truncate-list 'actions.more' B.data.member_of_groups 3}}
|
||||
</div>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{else}}
|
||||
<Rose::Table as |table|>
|
||||
<table.header as |header|>
|
||||
<header.row as |row|>
|
||||
<row.headerCell>{{t 'form.name.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.login_name.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.type.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.id.label'}}</row.headerCell>
|
||||
</header.row>
|
||||
</table.header>
|
||||
<table.body as |body|>
|
||||
{{#each @model.accounts as |account|}}
|
||||
<body.row as |row|>
|
||||
<row.headerCell>
|
||||
{{#if (can 'read account' account)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account'
|
||||
@model={{account.id}}
|
||||
>
|
||||
{{account.accountName}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
{{account.accountName}}
|
||||
{{/if}}
|
||||
<p>{{account.description}}</p>
|
||||
</row.headerCell>
|
||||
<row.cell>
|
||||
{{account.login_name}}
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Hds::Badge @text={{account.type}} />
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Copyable
|
||||
@text={{account.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
<Hds::Table
|
||||
@model={{@model.accounts}}
|
||||
@columns={{array
|
||||
(hash label=(t 'form.name.label'))
|
||||
(hash label=(t 'form.login_name.label'))
|
||||
(hash label=(t 'form.type.label'))
|
||||
(hash label=(t 'form.id.label'))
|
||||
}}
|
||||
@valign='middle'
|
||||
>
|
||||
<:body as |B|>
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
{{#if (can 'read account' B.data)}}
|
||||
<LinkTo
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account'
|
||||
@model={{B.data.id}}
|
||||
>
|
||||
<code>{{account.id}}</code>
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
</table.body>
|
||||
</Rose::Table>
|
||||
{{B.data.accountName}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
{{B.data.accountName}}
|
||||
{{/if}}
|
||||
<p>{{B.data.description}}</p>
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
{{B.data.login_name}}
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Hds::Badge @text={{B.data.type}} />
|
||||
</B.Td>
|
||||
<B.Td>
|
||||
<Copyable
|
||||
@text={{B.data.account.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{B.data.account.id}}</code>
|
||||
</Copyable>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
|
||||
<Rose::Layout::Centered>
|
||||
<Rose::Message
|
||||
@title={{t 'resources.account.messages.welcome.title'}}
|
||||
|
||||
@@ -93,7 +93,10 @@ module('Acceptance | accounts | create', function (hooks) {
|
||||
await fillIn('[name="description"]', 'description');
|
||||
await fillIn('[name="login_name"]', 'username');
|
||||
await click('form [type="submit"]:not(:disabled)');
|
||||
assert.strictEqual(this.server.schema.accounts.all().models.length, accountsCount + 1);
|
||||
assert.strictEqual(
|
||||
this.server.schema.accounts.all().models.length,
|
||||
accountsCount + 1
|
||||
);
|
||||
});
|
||||
|
||||
test('Users cannot create a new account without proper authorization', async function (assert) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
module('Acceptance | accounts | read', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupMirage(hooks);
|
||||
const ACCOUNT_SELECTOR = 'main tbody .hds-table__td:nth-child(1) a';
|
||||
|
||||
const instances = {
|
||||
scopes: {
|
||||
@@ -66,7 +67,8 @@ module('Acceptance | accounts | read', function (hooks) {
|
||||
test('can navigate to an account form', async function (assert) {
|
||||
assert.expect(1);
|
||||
await visit(urls.accounts);
|
||||
await click('main tbody .rose-table-header-cell:nth-child(1) a');
|
||||
await click(ACCOUNT_SELECTOR);
|
||||
|
||||
await a11yAudit();
|
||||
assert.strictEqual(currentURL(), urls.account);
|
||||
});
|
||||
@@ -76,6 +78,6 @@ module('Acceptance | accounts | read', function (hooks) {
|
||||
instances.account.authorized_actions =
|
||||
instances.account.authorized_actions.filter((item) => item !== 'read');
|
||||
await visit(urls.accounts);
|
||||
assert.notOk(find('main tbody .rose-table-header-cell:nth-child(1) a'));
|
||||
assert.dom(ACCOUNT_SELECTOR).doesNotExist();
|
||||
});
|
||||
});
|
||||
@@ -73,6 +73,23 @@ module('Acceptance | accounts | update', function (hooks) {
|
||||
assert.strictEqual(this.server.db.accounts[0].name, 'update name');
|
||||
});
|
||||
|
||||
test('can update resource and save LDAP account changes', async function (assert) {
|
||||
assert.expect(2);
|
||||
await visit(urls.account);
|
||||
await click('form [type="button"]', 'Activate edit mode');
|
||||
await fillIn('[name="name"]', 'updated name');
|
||||
await fillIn('[name="description"]', 'updated desc');
|
||||
await click('form [type="submit"]:not(:disabled)');
|
||||
assert.strictEqual(
|
||||
this.server.schema.accounts.all().models[0].name,
|
||||
'updated name'
|
||||
);
|
||||
assert.strictEqual(
|
||||
this.server.schema.accounts.all().models[0].description,
|
||||
'updated desc'
|
||||
);
|
||||
});
|
||||
|
||||
test('cannot update resource without proper authorization', async function (assert) {
|
||||
assert.expect(1);
|
||||
instances.account.authorized_actions =
|
||||
|
||||
Reference in new issue
Block a user