Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
798cfc6828 | ||
|
|
d93986c4e2 | ||
|
|
879c196887 | ||
|
|
98170ed01e | ||
|
|
47a218cf8f | ||
|
|
879a58dcb8 | ||
|
|
f100190ac1 | ||
|
|
0902e42cb0 | ||
|
|
6b0958e4d8 | ||
|
|
82ea70f44b | ||
|
|
0bb72040db | ||
|
|
9d9a38510b | ||
|
|
a54aecee07 | ||
|
|
7dab184bb9 | ||
|
|
f068ac0b0c | ||
|
|
d07c33ca41 | ||
|
|
f073de774d | ||
|
|
1040a05880 | ||
|
|
002f64d676 | ||
|
|
c09efbae10 | ||
|
|
060f995f94 | ||
|
|
f1c5c99664 | ||
|
|
af5fb8e814 | ||
|
|
cf5334556f | ||
|
|
5c6c9bb69f | ||
|
|
26a77edbc7 | ||
|
|
3fc865d226 | ||
|
|
47d7ceccf7 | ||
|
|
38df28be55 | ||
|
|
6d7c86a08c | ||
|
|
58a31b880b | ||
|
|
453ab7911d | ||
|
|
93c8d481fd | ||
|
|
956f6fd04d | ||
|
|
912be13744 | ||
|
|
fc1b91c8f9 | ||
|
|
8e40b01caf | ||
|
|
20181c978f | ||
|
|
db78f1ae4d | ||
|
|
592bb15022 | ||
|
|
f002e14673 | ||
|
|
a1b455e5eb | ||
|
|
786e6130cd | ||
|
|
4db8b8e1e7 | ||
|
|
4be8d10323 | ||
|
|
c79a1fca79 | ||
|
|
d2d332b7d1 | ||
|
|
022ac0fffe | ||
|
|
f3622fb92b | ||
|
|
f8b5dcd824 | ||
|
|
056008e13e | ||
|
|
ea03d6e488 |
No files matched your search
@@ -12,14 +12,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn install
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
@@ -37,17 +37,17 @@ jobs:
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:oss
|
||||
- name: Upload artifact admin-ui
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: admin-ui
|
||||
path: ./ui/admin/dist/
|
||||
- name: Upload artifact OSS admin UI
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: admin-ui-oss
|
||||
path: ./ui/admin/dist/
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
@@ -65,12 +65,12 @@ jobs:
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:enterprise
|
||||
- name: Upload artifact enterprise admin UI
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: admin-ui-ent
|
||||
path: ./ui/admin/dist/
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
@@ -88,12 +88,12 @@ jobs:
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- name: Build
|
||||
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run build:ui:admin:hcp
|
||||
- name: Upload artifact HCP admin UI
|
||||
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
|
||||
with:
|
||||
name: admin-ui-hcp
|
||||
path: ./ui/admin/dist/
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4b6aa0b07da05d6e43d0e5f9c8596a6532ce1c85 # codeql-bundle-v2.15.3
|
||||
uses: github/codeql-action/init@592977e6ae857384aa79bb31e7a1d62d63449ec5 # codeql-bundle-v2.16.3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -54,4 +54,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@4b6aa0b07da05d6e43d0e5f9c8596a6532ce1c85 # codeql-bundle-v2.15.3
|
||||
uses: github/codeql-action/analyze@592977e6ae857384aa79bb31e7a1d62d63449ec5 # codeql-bundle-v2.16.3
|
||||
@@ -7,14 +7,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn install
|
||||
@@ -25,14 +25,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn run compliance:licenses
|
||||
@@ -44,14 +44,14 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
node-modules-
|
||||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn lint
|
||||
@@ -63,12 +63,12 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
id: node-modules-cache
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 16
|
||||
- run: yarn test
|
||||
@@ -21,6 +21,14 @@ export default class SessionRecordingAbility extends ModelAbility {
|
||||
return !this.model.isUnknown && super.canRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only "known" session recording types may be deleted.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canDelete() {
|
||||
return !this.model.isUnknown && super.canDelete && this.model.isAvailable;
|
||||
}
|
||||
|
||||
get canDownload() {
|
||||
return this.hasAuthorizedAction('download');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import BaseModel from '../../models/base';
|
||||
import { attr } from '@ember-data/model';
|
||||
|
||||
/**
|
||||
* Alias contains all fields related to an Alias resource
|
||||
*/
|
||||
export default class GeneratedAliasModel extends BaseModel {
|
||||
// =attributes
|
||||
|
||||
@attr('string', {
|
||||
description: 'The type of the resource, to help differentiate schemas',
|
||||
})
|
||||
type;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional name for identification purposes.',
|
||||
})
|
||||
name;
|
||||
|
||||
@attr('string', {
|
||||
description: 'Optional user-set description for identification purposes.',
|
||||
})
|
||||
description;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was created\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
created_time;
|
||||
|
||||
@attr('date', {
|
||||
description: 'The time this resource was last updated\nOutput only.',
|
||||
readOnly: true,
|
||||
})
|
||||
updated_time;
|
||||
|
||||
@attr('number', {
|
||||
description: 'Current version number of this resource.',
|
||||
})
|
||||
version;
|
||||
|
||||
@attr('string', {
|
||||
description: 'This is the id of the resource that this Alias points to.',
|
||||
})
|
||||
destination_id;
|
||||
|
||||
@attr('object', {
|
||||
isNestedAttribute: true,
|
||||
description:
|
||||
'This contains a host_id which is the id of the host that the session will be authorized for.',
|
||||
})
|
||||
authorize_session_arguments;
|
||||
}
|
||||
@@ -75,6 +75,18 @@ export default class GeneratedCredentialLibraryModel extends BaseModel {
|
||||
})
|
||||
path;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-generic',
|
||||
description: 'It indicates the type of credential the library returns.',
|
||||
})
|
||||
credential_type;
|
||||
|
||||
@attr('object', {
|
||||
for: 'vault-generic',
|
||||
description: 'It indicates the credential mapping overrides.',
|
||||
})
|
||||
credential_mapping_overrides;
|
||||
|
||||
@attr('string', {
|
||||
for: 'vault-ssh-certificate',
|
||||
isNestedAttribute: true,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import GeneratedAliasModel from '../generated/models/alias';
|
||||
|
||||
export const TYPE_ALIAS_TARGET = 'target';
|
||||
export const TYPES_ALIAS = Object.freeze([TYPE_ALIAS_TARGET]);
|
||||
export default class AliasModel extends GeneratedAliasModel {}
|
||||
@@ -11,6 +11,18 @@ import GeneratedCredentialLibraryModel from '../generated/models/credential-libr
|
||||
export const options = {
|
||||
http_method: ['GET', 'POST'],
|
||||
key_type: ['ed25519', 'ecdsa', 'rsa'],
|
||||
credential_types: ['ssh_private_key', 'username_password'],
|
||||
mapping_overrides: {
|
||||
username_password: {
|
||||
username_attribute: 'Username',
|
||||
password_attribute: 'Password',
|
||||
},
|
||||
ssh_private_key: {
|
||||
private_key_attribute: 'Private Key',
|
||||
private_key_passphrase_attribute: 'Private Key Passphrase',
|
||||
username_attribute: 'Username',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC = 'vault-generic';
|
||||
|
||||
@@ -7,6 +7,7 @@ import ApplicationSerializer from './application';
|
||||
import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
options,
|
||||
} from '../models/credential-library';
|
||||
|
||||
export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
@@ -31,9 +32,34 @@ export default class CredentialLibrarySerializer extends ApplicationSerializer {
|
||||
return super.serialize(...arguments);
|
||||
}
|
||||
}
|
||||
serializeAttribute(snapshot, json) {
|
||||
const value = super.serializeAttribute(...arguments);
|
||||
const { credential_type, type, credential_mapping_overrides, isNew } =
|
||||
snapshot.record;
|
||||
if (
|
||||
type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC &&
|
||||
credential_mapping_overrides &&
|
||||
credential_type &&
|
||||
!isNew
|
||||
) {
|
||||
// API expects to send null to fields if it is undefined or deleted
|
||||
json.credential_mapping_overrides = Object.keys(
|
||||
options.mapping_overrides[credential_type],
|
||||
).reduce((obj, key) => {
|
||||
if (credential_mapping_overrides[key]) {
|
||||
obj[key] = credential_mapping_overrides[key];
|
||||
} else {
|
||||
obj[key] = null;
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
serializeVaultGeneric() {
|
||||
const serialized = super.serialize(...arguments);
|
||||
|
||||
if (serialized.attributes) {
|
||||
// Set `http_request_body` only if `http_method` is POST
|
||||
// otherwise set to null to have the field removed
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
export { default } from 'api/models/alias';
|
||||
@@ -753,6 +753,22 @@ function routes() {
|
||||
return policies.create(attrs);
|
||||
});
|
||||
|
||||
// Alias
|
||||
this.get(
|
||||
'/aliases',
|
||||
({ aliases }, { queryParams: { scope_id: scopeId } }) => {
|
||||
return aliases.where({ scopeId });
|
||||
},
|
||||
);
|
||||
this.get('/aliases/:id');
|
||||
this.del('/aliases/:id');
|
||||
this.patch('/aliases/:id');
|
||||
this.post('/aliases', function ({ aliases }) {
|
||||
const attrs = this.normalizedRequestAttrs();
|
||||
|
||||
return aliases.create(attrs);
|
||||
});
|
||||
|
||||
// session recordings
|
||||
this.get(
|
||||
'/session-recordings',
|
||||
@@ -798,6 +814,8 @@ function routes() {
|
||||
},
|
||||
);
|
||||
|
||||
this.del('/session-recordings/:id');
|
||||
|
||||
/* Uncomment the following line and the Response import above
|
||||
* Then change the response code to simulate error responses.
|
||||
* this.get('/scopes', () => new Response(505));
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import factory from '../generated/factories/alias';
|
||||
import permissions from '../helpers/permissions';
|
||||
import generateId from '../helpers/id';
|
||||
|
||||
const destinationIDs = ['', generateId('t_')];
|
||||
|
||||
export default factory.extend({
|
||||
id: () => generateId('alt_'),
|
||||
destination_id: (i) => destinationIDs[i % destinationIDs.length],
|
||||
authorized_actions: () =>
|
||||
permissions.authorizedActionsFor('alias') || [
|
||||
'no-op',
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
],
|
||||
});
|
||||
@@ -11,12 +11,18 @@ import {
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
TYPES_CREDENTIAL_LIBRARY,
|
||||
options,
|
||||
} from 'api/models/credential-library';
|
||||
|
||||
export default factory.extend({
|
||||
id: () => generateId('cl_'),
|
||||
type: (i) => TYPES_CREDENTIAL_LIBRARY[i % TYPES_CREDENTIAL_LIBRARY.length],
|
||||
|
||||
credential_type(i) {
|
||||
if (this.type === TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC) {
|
||||
return options.credential_types[i % options.credential_types.length];
|
||||
}
|
||||
},
|
||||
authorized_actions: () =>
|
||||
permissions.authorizedActionsFor('credential-library') || [
|
||||
'no-op',
|
||||
|
||||
@@ -33,12 +33,13 @@ export default factory.extend({
|
||||
roles: ['create', 'list'],
|
||||
};
|
||||
|
||||
// Worker permissions only available on the global scope
|
||||
// Resources that are available only on the global scope
|
||||
if (this.type === 'global') {
|
||||
collectionActions.workers = ['create:worker-led', 'list'];
|
||||
collectionActions.aliases = ['create', 'list'];
|
||||
}
|
||||
|
||||
// Session recording resources are only available on global or org scope
|
||||
// Resources that are only available on the global or the org scope
|
||||
if (this.type === 'global' || this.type === 'org') {
|
||||
collectionActions['storage-buckets'] = ['create', 'list'];
|
||||
collectionActions['session-recordings'] = ['list'];
|
||||
|
||||
@@ -60,6 +60,7 @@ export default factory.extend({
|
||||
'read',
|
||||
'download',
|
||||
'reapply-storage-policy',
|
||||
'delete',
|
||||
],
|
||||
|
||||
withNonExistingUserAndTarget: trait({
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { Factory } from 'miragejs';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { TYPE_ALIAS_TARGET } from 'api/models/alias';
|
||||
|
||||
/**
|
||||
* GeneratedAliasModelFactory
|
||||
*/
|
||||
export default Factory.extend({
|
||||
name: () => faker.word.words(),
|
||||
type: TYPE_ALIAS_TARGET,
|
||||
value: () => faker.word.words(),
|
||||
description: () => faker.word.words(),
|
||||
created_time: () => faker.date.recent(),
|
||||
updated_time: () => faker.date.recent(),
|
||||
version: () => faker.number.int(),
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { belongsTo } from 'miragejs';
|
||||
import Model from './base';
|
||||
|
||||
export default Model.extend({
|
||||
scope: belongsTo(),
|
||||
});
|
||||
@@ -108,6 +108,9 @@ export default function (server) {
|
||||
server.createList('policy', 3, { scope: globalScope });
|
||||
server.createList('policy', 3, { scope: orgScope });
|
||||
|
||||
// Aliases
|
||||
server.createList('alias', 3, { scope: globalScope });
|
||||
|
||||
// Other resources
|
||||
server.schema.scopes.where({ type: 'project' }).models.forEach((scope) => {
|
||||
server.createList('host-catalog', 8, { scope }, 'withChildren');
|
||||
|
||||
@@ -14,6 +14,17 @@ export default ApplicationSerializer.extend({
|
||||
arguments,
|
||||
);
|
||||
json.credential_store_id = model.credentialStoreId;
|
||||
|
||||
// BE API only updates these fields if there's an update mask, otherwise they remain unmodified
|
||||
// but we don't need this flow in our mocks, so we are deleting fields with null value
|
||||
|
||||
if (json.credential_mapping_overrides) {
|
||||
Object.keys(json.credential_mapping_overrides).forEach((key) => {
|
||||
if (json.credential_mapping_overrides[key] === null) {
|
||||
delete json.credential_mapping_overrides[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
return json;
|
||||
},
|
||||
});
|
||||
@@ -5,6 +5,11 @@
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import {
|
||||
STATE_SESSION_RECORDING_AVAILABLE,
|
||||
STATE_SESSION_RECORDING_STARTED,
|
||||
TYPE_SESSION_RECORDING_SSH,
|
||||
} from 'api/models/session-recording';
|
||||
|
||||
module('Unit | Ability | session-recording', function (hooks) {
|
||||
setupTest(hooks);
|
||||
@@ -49,4 +54,36 @@ module('Unit | Ability | session-recording', function (hooks) {
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('can delete a session with proper authorization and in available state', function (assert) {
|
||||
const recordingNotinAvaialableState = store.createRecord(
|
||||
'session-recording',
|
||||
{
|
||||
authorized_actions: ['delete'],
|
||||
type: TYPE_SESSION_RECORDING_SSH,
|
||||
state: STATE_SESSION_RECORDING_STARTED,
|
||||
},
|
||||
);
|
||||
const recordingInAvailableState = store.createRecord('session-recording', {
|
||||
authorized_actions: ['delete'],
|
||||
type: TYPE_SESSION_RECORDING_SSH,
|
||||
state: STATE_SESSION_RECORDING_AVAILABLE,
|
||||
});
|
||||
assert.false(
|
||||
canService.can('delete session-recording', recordingNotinAvaialableState),
|
||||
);
|
||||
assert.true(
|
||||
canService.can('delete session-recording', recordingInAvailableState),
|
||||
);
|
||||
});
|
||||
|
||||
test('can re-apply Storage policy with proper authorization', function (assert) {
|
||||
const recording = store.createRecord('session', {
|
||||
authorized_actions: ['reapply-storage-policy'],
|
||||
});
|
||||
|
||||
assert.true(
|
||||
canService.can('reapplyStoragePolicy session-recording', recording),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Model | alias', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let store = this.owner.lookup('service:store');
|
||||
let model = store.createRecord('alias', {});
|
||||
assert.ok(model);
|
||||
});
|
||||
});
|
||||
@@ -23,6 +23,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
path: '/vault/path',
|
||||
http_method: 'GET',
|
||||
version: 1,
|
||||
credential_type: 'ssh_private_key',
|
||||
credential_mapping_overrides: { username_attribute: 'user' },
|
||||
});
|
||||
const snapshot = record._createSnapshot();
|
||||
const serializedRecord = serializer.serialize(snapshot);
|
||||
@@ -32,6 +34,10 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
version: 1,
|
||||
credential_type: 'ssh_private_key',
|
||||
credential_mapping_overrides: {
|
||||
username_attribute: 'user',
|
||||
},
|
||||
attributes: {
|
||||
path: '/vault/path',
|
||||
http_method: 'GET',
|
||||
@@ -54,6 +60,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
path: '/vault/path',
|
||||
http_method: 'GET',
|
||||
version: 1,
|
||||
credential_type: 'ssh_private_key',
|
||||
credential_mapping_overrides: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -65,6 +73,12 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
credential_store_id: null,
|
||||
name: 'Name',
|
||||
description: 'Description',
|
||||
credential_type: 'ssh_private_key',
|
||||
credential_mapping_overrides: {
|
||||
private_key_attribute: null,
|
||||
private_key_passphrase_attribute: null,
|
||||
username_attribute: null,
|
||||
},
|
||||
attributes: {
|
||||
path: '/vault/path',
|
||||
http_method: 'GET',
|
||||
@@ -80,6 +94,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
http_method: '',
|
||||
path: null,
|
||||
credential_type: null,
|
||||
credential_mapping_overrides: {},
|
||||
});
|
||||
const vaultSSHCertificateRecord = store.createRecord('credential-library', {
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
|
||||
@@ -99,6 +115,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
description: null,
|
||||
name: null,
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
credential_type: null,
|
||||
credential_mapping_overrides: {},
|
||||
});
|
||||
assert.deepEqual(serializedVaultSSHCertificateRecord, {
|
||||
attributes: {
|
||||
@@ -138,6 +156,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
description: null,
|
||||
name: null,
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
credential_type: null,
|
||||
credential_mapping_overrides: {},
|
||||
},
|
||||
'http_request_body attribute is not expected',
|
||||
);
|
||||
@@ -156,6 +176,8 @@ module('Unit | Serializer | credential library', function (hooks) {
|
||||
description: null,
|
||||
name: null,
|
||||
type: TYPE_CREDENTIAL_LIBRARY_VAULT_GENERIC,
|
||||
credential_type: null,
|
||||
credential_mapping_overrides: {},
|
||||
},
|
||||
'http_request_body attribute is expected',
|
||||
);
|
||||
|
||||
@@ -48,6 +48,8 @@ session_max_seconds:
|
||||
session_connection_limit:
|
||||
label: Maximum Connections
|
||||
help: The maximum number of connections allowed per session. For unlimited, specify "-1".
|
||||
session_id:
|
||||
label: Session ID
|
||||
worker_release_version:
|
||||
label: Release Version
|
||||
help: The version of the Boundary binary the worker is running.
|
||||
@@ -58,8 +60,6 @@ worker_last_seen:
|
||||
help: Last time the worker reported status.
|
||||
worker_address:
|
||||
help: URL and port for this worker.
|
||||
worker_type:
|
||||
help: Type of worker
|
||||
host_set:
|
||||
label: Host Set
|
||||
grant_scope:
|
||||
|
||||
@@ -354,6 +354,8 @@ session-recording:
|
||||
up: '{bytes} up'
|
||||
down: '{bytes} down'
|
||||
duration: '{time} duration'
|
||||
questions:
|
||||
delete: Are you sure you want to delete this recording?
|
||||
connection:
|
||||
title: Connection
|
||||
title_index: Connection {index}
|
||||
@@ -761,6 +763,12 @@ credential-library:
|
||||
description: A credential library is a resource that provides credentials.
|
||||
titles:
|
||||
new: New Credential Library
|
||||
ssh_private_key: SSH Private Key
|
||||
username_password: Username & Password
|
||||
username_attribute: Username
|
||||
password_attribute: Password
|
||||
private_key_passphrase_attribute: Private Key Passphrase
|
||||
private_key_attribute: Private Key
|
||||
actions:
|
||||
create: New Credential Library
|
||||
delete: Delete Credential Library
|
||||
@@ -772,6 +780,12 @@ credential-library:
|
||||
vault_path:
|
||||
label: Vault Path
|
||||
help: The path the library uses when requesting credentials from Vault.
|
||||
credential_type:
|
||||
label: Credential Type
|
||||
help: Specify the type of credential this library will issue. This must be set to use credential injection. After this data is saved, it cannot be changed later.
|
||||
credential_mapping_overrides:
|
||||
label: Credential mapping overrides
|
||||
help: Specify the credential fields to use instead of the defaults
|
||||
http_method:
|
||||
label: HTTP Method
|
||||
help: The HTTP method the library uses when requesting credentials from Vault.
|
||||
@@ -839,7 +853,6 @@ credential:
|
||||
help: The private key to use when connecting with this credential store.
|
||||
private_key_passphrase:
|
||||
label: Passphrase
|
||||
help: Optional.
|
||||
json:
|
||||
label: JSON
|
||||
help: This is the JSON blob that provides credentials to the host. After this data is saved, you will not be able to edit it again without replacing it.
|
||||
@@ -917,7 +930,7 @@ worker:
|
||||
title: 1. Configure your new worker
|
||||
create_directory: Create a configuration file in a new directory on your server
|
||||
create_config: 'Open the file with a text editor, such as Vi. Paste the following configuration into the worker config file:'
|
||||
save_config: Save the configuration in your `pki-worker.hcl` file.
|
||||
save_config: Save the configuration in your <code>pki-worker.hcl</code> file.
|
||||
2:
|
||||
title: 2. Install & start Boundary on your server
|
||||
run_command: 'Run this command on your server to install Boundary:'
|
||||
@@ -944,11 +957,13 @@ policy:
|
||||
create_policy_description: Enable session recording for projects in this org.
|
||||
retain_until: Retain until
|
||||
actions:
|
||||
detach: Detach Storage Policy
|
||||
delete: Delete Storage Policy
|
||||
add: Add Storage Policy
|
||||
apply: Apply the storage policy to this scope and its children
|
||||
new: Add a new storage policy
|
||||
update: Re-apply storage policy
|
||||
delete_recording: Delete recording
|
||||
questions:
|
||||
detach: Are you sure you want to detach this storage policy?
|
||||
messages:
|
||||
@@ -975,8 +990,8 @@ policy:
|
||||
label: Custom
|
||||
do_not_protect:
|
||||
label: Do not protect, allow deletion any time
|
||||
hippa:
|
||||
label: HIPPA (6 years)
|
||||
hipaa:
|
||||
label: HIPAA (6 years)
|
||||
soc:
|
||||
label: SOC 2 (7 years)
|
||||
deletion_policy_options:
|
||||
@@ -984,3 +999,8 @@ policy:
|
||||
label: Do not delete
|
||||
custom:
|
||||
label: Custom
|
||||
alias:
|
||||
title: Alias
|
||||
title_plural: Aliases
|
||||
titles:
|
||||
new: New Alias
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@embroider/test-setup": "^2.1.1",
|
||||
"@hashicorp/design-system-components": "^3.2.0",
|
||||
"@hashicorp/design-system-components": "^3.5.0",
|
||||
"codemirror": "5.65.7",
|
||||
"ember-auto-import": "^2.6.3",
|
||||
"ember-cli-babel": "^7.26.11",
|
||||
|
||||
@@ -29,4 +29,14 @@ export default class OverrideSessionRecordingAbility extends SessionRecordingAbi
|
||||
? this.hasAuthorizedAction('reapply-storage-policy')
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This override ensures that session recordings may be deleted only if the
|
||||
* session-recording feature flag is enabled.
|
||||
*/
|
||||
get canDelete() {
|
||||
return this.features.isEnabled('ssh-session-recording')
|
||||
? super.canDelete
|
||||
: false;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
@disabled={{@model.canSave}}
|
||||
{{on 'click' (route-action 'deleteAccount' @model)}}
|
||||
{{on 'click' (fn @delete @model)}}
|
||||
>
|
||||
{{t 'resources.account.actions.delete'}}
|
||||
</dropdown.button>
|
||||
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='account' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.account.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -13,10 +13,4 @@
|
||||
<DocLink @doc='auth-method' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.auth-method.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
@disabled={{@model.canSave}}
|
||||
{{on 'click' (route-action 'deleteManagedGroup' @model)}}
|
||||
{{on 'click' (fn @delete @model)}}
|
||||
>
|
||||
{{t 'resources.managed-group.actions.delete'}}
|
||||
</dropdown.button>
|
||||
|
||||
+1
-7
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='managed-groups' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.managed-group.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -1,35 +0,0 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
}}
|
||||
|
||||
<span
|
||||
id={{this.id}}
|
||||
class='copyable'
|
||||
{{did-insert this.register}}
|
||||
{{will-destroy this.tearDown}}
|
||||
>
|
||||
|
||||
{{#if this.copied}}
|
||||
<mark class='copyable-content'>
|
||||
{{yield}}
|
||||
</mark>
|
||||
{{else}}
|
||||
<span class='copyable-content'>
|
||||
{{yield}}
|
||||
</span>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.isClipboardLibrarySupported}}
|
||||
<Rose::Button
|
||||
id={{this.copyableButtonId}}
|
||||
aria-describedby={{this.id}}
|
||||
class='copyable-button'
|
||||
@style='ghost'
|
||||
@iconOnly={{if this.copied this.successIcon this.actionIcon}}
|
||||
title={{if this.copied this.successText this.actionText}}
|
||||
>
|
||||
{{this.actionText}}
|
||||
</Rose::Button>
|
||||
{{/if}}
|
||||
</span>
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import ClipboardJS from 'clipboard';
|
||||
import { action } from '@ember/object';
|
||||
import { generateComponentID } from 'rose/utilities/component-auto-id';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { later } from '@ember/runloop';
|
||||
|
||||
export default class CopyableComponent extends Component {
|
||||
// =attributes
|
||||
|
||||
id = generateComponentID();
|
||||
copyableButtonId = `copyable-button-${this.id}`;
|
||||
|
||||
actionIcon = 'flight-icons/svg/clipboard-copy-16';
|
||||
successIcon = 'flight-icons/svg/clipboard-checked-16';
|
||||
actionText = this.args.buttonText;
|
||||
successText = this.args.acknowledgeText;
|
||||
|
||||
@tracked copied = false;
|
||||
|
||||
clipboard = null;
|
||||
|
||||
confirmCopy() {
|
||||
this.copied = true;
|
||||
later(() => (this.copied = false), 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for ClipboardJS support.
|
||||
* @return {boolean}
|
||||
*/
|
||||
get isClipboardLibrarySupported() {
|
||||
return ClipboardJS.isSupported();
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Initialize ClipboardJS library and register for it's events.
|
||||
*/
|
||||
@action
|
||||
register() {
|
||||
this.tearDown();
|
||||
/* istanbul ignore next */
|
||||
this.clipboard = new ClipboardJS(`#${this.copyableButtonId}`, {
|
||||
text: () => this.args.text,
|
||||
});
|
||||
/* istanbul ignore next */
|
||||
this.clipboard.on('success', (clipboardEvent) => {
|
||||
clipboardEvent.clearSelection();
|
||||
this.confirmCopy();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy ClipboardJS library instance and cancel icon timer.
|
||||
*/
|
||||
@action
|
||||
tearDown() {
|
||||
this.clipboard?.destroy();
|
||||
this.clipboard = null;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
@disabled={{@model.canSave}}
|
||||
{{on 'click' (route-action 'delete' @model)}}
|
||||
{{on 'click' @delete}}
|
||||
>
|
||||
{{t 'resources.credential-store.actions.delete'}}
|
||||
</dropdown.button>
|
||||
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='credential-store' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.credential-store.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -10,58 +10,48 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
{{#unless @model.isNew}}
|
||||
<form.input
|
||||
@value={{@model.issuer}}
|
||||
@label={{t 'form.issuer.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<form.input
|
||||
@value={{@model.subject}}
|
||||
@label={{t 'form.subject.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<form.input
|
||||
@value={{@model.email}}
|
||||
@label={{t 'form.email.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<form.input
|
||||
@value={{@model.full_name}}
|
||||
@label={{t 'form.full_name.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
|
||||
<InfoField @value={{@model.issuer}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.issuer.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<InfoField @value={{@model.subject}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.subject.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<InfoField @value={{@model.email}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.email.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<InfoField @value={{@model.full_name}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.full_name.label'}}</F.Label>
|
||||
</InfoField>
|
||||
{{/unless}}
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
@@ -83,41 +73,41 @@
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
{{#if @model.isNew}}
|
||||
<form.input
|
||||
@name='issuer'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='issuer'
|
||||
@value={{@model.issuer}}
|
||||
@label={{t 'form.issuer.label'}}
|
||||
@error={{@model.errors.issuer}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.issuer}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'issuer')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.issuer.label'}}</F.Label>
|
||||
{{#if @model.errors.issuer}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.issuer as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='subject'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='subject'
|
||||
@value={{@model.subject}}
|
||||
@label={{t 'form.subject.label'}}
|
||||
@error={{@model.errors.subject}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.subject}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'subject')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.subject.label'}}</F.Label>
|
||||
{{#if @model.errors.subject}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.subject as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -10,37 +10,35 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -55,43 +53,45 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@name='login_name'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='login_name'
|
||||
@value={{@model.login_name}}
|
||||
@label={{t 'form.login_name.label'}}
|
||||
@error={{@model.errors.login_name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.login_name}}
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'login_name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.login_name.label'}}</F.Label>
|
||||
{{#if @model.errors.login_name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.login_name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if @model.isNew}}
|
||||
<form.input
|
||||
@name='password'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='password'
|
||||
@type='password'
|
||||
@value={{this.password}}
|
||||
@label={{t 'form.password.label'}}
|
||||
@error={{@model.errors.password}}
|
||||
readonly={{false}}
|
||||
@value={{@model.password}}
|
||||
@isInvalid={{@model.errors.password}}
|
||||
disabled={{form.disabled}}
|
||||
autocomplete='new-password'
|
||||
as |field|
|
||||
{{on 'input' (set-from-event @model 'password')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.password.label'}}</F.Label>
|
||||
{{#if @model.errors.password}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.password as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -12,37 +12,35 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} disabled={{form.disabled}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -57,24 +55,25 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@name='issuer'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.issuer}}
|
||||
@label={{t 'form.issuer.label'}}
|
||||
@helperText={{t 'form.issuer.help'}}
|
||||
@error={{@model.errors.issuer}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.issuer}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
name='issuer'
|
||||
{{on 'input' (set-from-event @model 'issuer')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.issuer.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.issuer.help'}}</F.HelperText>
|
||||
{{#if @model.errors.issuer}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.issuer as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Checkbox::Field
|
||||
name='disable_discovered_config_validation'
|
||||
@@ -95,164 +94,86 @@
|
||||
</F.HelperText>
|
||||
</Hds::Form::Checkbox::Field>
|
||||
|
||||
<form.input
|
||||
@name='client_id'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='client_id'
|
||||
@value={{@model.client_id}}
|
||||
@label={{t 'form.client_id.label'}}
|
||||
@helperText={{t 'form.client_id.help'}}
|
||||
@error={{@model.errors.client_id}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.client_id}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'client_id')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.client_id.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.client_id.help'}}</F.HelperText>
|
||||
{{#if @model.errors.client_id}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.client_id as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='client_secret'
|
||||
@type='password'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='client_secret'
|
||||
@value={{@model.client_secret}}
|
||||
@label={{t 'form.client_secret.label'}}
|
||||
@helperText={{t 'form.client_secret.help'}}
|
||||
@error={{@model.errors.client_secret}}
|
||||
readonly={{false}}
|
||||
@isInvalid={{@model.errors.client_secret}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
@hasVisibilityToggle={{false}}
|
||||
as |field|
|
||||
@type='password'
|
||||
{{on 'input' (set-from-event @model 'client_secret')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.client_secret.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.client_secret.help'}}</F.HelperText>
|
||||
{{#if @model.errors.client_secret}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.client_secret as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#unless @model.isNew}}
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.client_secret_hmac}}
|
||||
@label={{t 'form.client_secret_hmac.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.client_secret_hmac.label'}}</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/unless}}
|
||||
|
||||
{{! Signing Algorithms }}
|
||||
<Rose::Form::Fieldset>
|
||||
<:title>{{t 'form.signing_algorithms.label'}}</:title>
|
||||
<:description>{{t 'form.signing_algorithms.help'}}</:description>
|
||||
<:body>
|
||||
<Form::Field::ListWrapper @layout='horizontal' @disabled={{form.disabled}}>
|
||||
<:fieldset as |F|>
|
||||
<F.Legend>
|
||||
{{t 'form.signing_algorithms.label'}}
|
||||
</F.Legend>
|
||||
<F.HelperText>
|
||||
{{t 'form.signing_algorithms.help'}}
|
||||
</F.HelperText>
|
||||
|
||||
{{#if @model.errors.signing_algorithms}}
|
||||
<Rose::Form::Errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.signing_algorithms as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</Rose::Form::Errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
<Rose::Table @style='condensed' as |table|>
|
||||
<table.header as |header|>
|
||||
<header.row @hidden={{true}} as |row|>
|
||||
<row.headerCell>{{t 'titles.value'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'titles.actions'}}</row.headerCell>
|
||||
</header.row>
|
||||
</table.header>
|
||||
<table.body as |body|>
|
||||
{{#each @model.signing_algorithms as |algorithm i|}}
|
||||
<body.row as |row|>
|
||||
<row.cell>
|
||||
</:fieldset>
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{algorithm.value}}
|
||||
@isInvalid={{@model.errors.signing_algorithms}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event algorithm 'value')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label class='sr-only'>{{t
|
||||
'form.algorithm.label'
|
||||
}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.signingAlgorithms as |algorithmOption|}}
|
||||
<option
|
||||
value={{algorithmOption}}
|
||||
selected={{eq algorithmOption algorithm.value}}
|
||||
>{{algorithmOption}}</option>
|
||||
{{/each}}
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
@style='warning'
|
||||
@iconOnly='flight-icons/svg/trash-16'
|
||||
title={{t 'actions.remove'}}
|
||||
@disabled={{if
|
||||
@model.isNew
|
||||
false
|
||||
(if form.isEditable false true)
|
||||
}}
|
||||
{{on 'click' (fn @removeItemByIndex 'signing_algorithms' i)}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</Rose::Button>
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
|
||||
<body.row as |row|>
|
||||
<row.cell>
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@value={{this.newSigningAlgorithm}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'change' (set-from-event this 'newSigningAlgorithm')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label class='sr-only'>{{t
|
||||
'resources.auth-method.titles.new-signing-algorithm'
|
||||
}}</F.Label>
|
||||
<F.Options>
|
||||
{{#each this.signingAlgorithms as |algorithmOption|}}
|
||||
<option
|
||||
value={{algorithmOption}}
|
||||
selected={{eq algorithmOption this.newSigningAlgorithm}}
|
||||
>{{algorithmOption}}</option>
|
||||
{{/each}}
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
</row.cell>
|
||||
<row.cell @shrink={{true}}>
|
||||
<Rose::Button
|
||||
@style='secondary'
|
||||
title={{t 'actions.add'}}
|
||||
@disabled={{if
|
||||
@model.isNew
|
||||
false
|
||||
(if form.isEditable false true)
|
||||
}}
|
||||
{{on
|
||||
'click'
|
||||
(fn
|
||||
@addStringItem 'signing_algorithms' this.newSigningAlgorithm
|
||||
)
|
||||
}}
|
||||
>
|
||||
{{t 'actions.add'}}
|
||||
</Rose::Button>
|
||||
</row.cell>
|
||||
</body.row>
|
||||
</table.body>
|
||||
</Rose::Table>
|
||||
</:body>
|
||||
</Rose::Form::Fieldset>
|
||||
<:field as |F|>
|
||||
<F.Select
|
||||
@name='signing_algorithms'
|
||||
@model={{@model}}
|
||||
@selectOptions={{this.signingAlgorithms}}
|
||||
@width='100%'
|
||||
/>
|
||||
</:field>
|
||||
</Form::Field::ListWrapper>
|
||||
|
||||
{{! Allowed Audiences }}
|
||||
<Form::Field::ListWrapper
|
||||
@@ -488,45 +409,43 @@
|
||||
|
||||
</Form::Field::ListWrapper>
|
||||
|
||||
<form.input
|
||||
@name='max_age'
|
||||
@type='number'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='max_age'
|
||||
@value={{@model.max_age}}
|
||||
@label={{t 'form.max_age.label'}}
|
||||
@helperText={{t 'form.max_age.help'}}
|
||||
@error={{@model.errors.max_age}}
|
||||
readonly={{false}}
|
||||
step='1'
|
||||
min='0'
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.max_age}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'max_age')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.max_age.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.max_age.help'}}</F.HelperText>
|
||||
{{#if @model.errors.max_age}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.max_age as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='api_url_prefix'
|
||||
@type='test'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='api_url_prefix'
|
||||
@value={{@model.api_url_prefix}}
|
||||
@label={{t 'form.api_url_prefix.label'}}
|
||||
@helperText={{t 'form.api_url_prefix.help'}}
|
||||
@error={{@model.errors.api_url_prefix}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.api_url_prefix}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'api_url_prefix')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.api_url_prefix.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.api_url_prefix.help'}}</F.HelperText>
|
||||
{{#if @model.errors.api_url_prefix}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.api_url_prefix as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Fieldset @isOptional={{true}} as |F|>
|
||||
<F.Legend>{{t 'form.prompts.label'}}</F.Legend>
|
||||
@@ -581,13 +500,14 @@
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
{{#unless @model.isNew}}
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.callback_url}}
|
||||
@label={{t 'form.callback_url.label'}}
|
||||
@helperText={{t 'form.callback_url.help'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.callback_url.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.callback_url.help'}}</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/unless}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -10,49 +10,40 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} disabled={{form.disabled}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.description.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.description.help'}}</F.HelperText>
|
||||
{{#if @model.errors.description}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.description as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -108,6 +108,78 @@
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Select::Field
|
||||
@isOptional={{true}}
|
||||
@width='100%'
|
||||
name='credential_type'
|
||||
disabled={{or form.disabled (not @model.isNew)}}
|
||||
{{on 'input' this.selectCredentialType}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t 'resources.credential-library.form.credential_type.label'}}
|
||||
</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-library.form.credential_type.help'}}
|
||||
</F.HelperText>
|
||||
<F.Options>
|
||||
<option value='' />
|
||||
|
||||
{{#each this.credentialTypes as |type|}}
|
||||
<option value={{type}} selected={{eq type @model.credential_type}}>
|
||||
{{t (concat 'resources.credential-library.titles.' type)}}
|
||||
</option>
|
||||
{{/each}}
|
||||
</F.Options>
|
||||
{{#if @model.errors.credential_type}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.credential_type as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::Select::Field>
|
||||
|
||||
{{#if @model.credential_type}}
|
||||
<Form::Field::ListWrapper
|
||||
@layout='horizontal'
|
||||
@isOptional={{true}}
|
||||
@disabled={{form.disabled}}
|
||||
>
|
||||
<:fieldset as |F|>
|
||||
<F.Legend>
|
||||
{{t
|
||||
'resources.credential-library.form.credential_mapping_overrides.label'
|
||||
}}
|
||||
</F.Legend>
|
||||
<F.HelperText>
|
||||
{{t
|
||||
'resources.credential-library.form.credential_mapping_overrides.help'
|
||||
}}
|
||||
</F.HelperText>
|
||||
|
||||
{{#if @model.errors.credential_mapping_overrides}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.credential_mapping_overrides as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</:fieldset>
|
||||
|
||||
<:field as |F|>
|
||||
<F.SelectText
|
||||
@name='credential_mapping_overrides'
|
||||
@selectOptions={{this.mappingOverrides}}
|
||||
@model={{@model}}
|
||||
@disabled={{form.disabled}}
|
||||
@removeDuplicates={{true}}
|
||||
@width='400px'
|
||||
/>
|
||||
</:field>
|
||||
</Form::Field::ListWrapper>
|
||||
{{/if}}
|
||||
|
||||
<Hds::Form::Radio::Group
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'http_method')}}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
options,
|
||||
TYPES_CREDENTIAL_LIBRARY,
|
||||
} from 'api/models/credential-library';
|
||||
|
||||
import { action } from '@ember/object';
|
||||
export default class FormCredentialLibraryVaultGenericComponent extends Component {
|
||||
// =properties
|
||||
/**
|
||||
@@ -16,6 +16,7 @@ export default class FormCredentialLibraryVaultGenericComponent extends Componen
|
||||
*/
|
||||
httpMethodOptions = options.http_method;
|
||||
|
||||
credentialTypes = options.credential_types;
|
||||
/**
|
||||
*
|
||||
* @type {Array.<string>}
|
||||
@@ -29,4 +30,17 @@ export default class FormCredentialLibraryVaultGenericComponent extends Componen
|
||||
get isHttpRequestBodyAllowed() {
|
||||
return this.args.model.http_method?.match(/post/i);
|
||||
}
|
||||
|
||||
get mappingOverrides() {
|
||||
return options.mapping_overrides[this.args.model.credential_type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the previously selected key value pair when toggling between credential types on a new form
|
||||
*/
|
||||
@action
|
||||
selectCredentialType({ target: { value } }) {
|
||||
this.args.model.credential_mapping_overrides = {};
|
||||
this.args.model.credential_type = value;
|
||||
}
|
||||
}
|
||||
@@ -10,30 +10,33 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -11,30 +11,33 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -76,6 +79,7 @@
|
||||
<InfoField
|
||||
@value={{t (concat 'resources.credential-store.types.' @model.type)}}
|
||||
@icon='vault'
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
@@ -85,119 +89,135 @@
|
||||
</InfoField>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<form.input
|
||||
@name='address'
|
||||
@type='text'
|
||||
|
||||
<Hds::Form::TextInput::Field
|
||||
name='address'
|
||||
@value={{@model.address}}
|
||||
@label={{t 'resources.credential-store.form.address.label'}}
|
||||
@error={{@model.errors.address}}
|
||||
@helperText={{t 'resources.credential-store.form.address.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.address}}
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'address')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential-store.form.address.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-store.form.address.help'}}
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.address}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.address as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (feature-flag 'vault-worker-filter')}}
|
||||
<form.input
|
||||
@name='worker_filter'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='worker_filter'
|
||||
@value={{@model.worker_filter}}
|
||||
@label={{t 'resources.credential-store.form.worker_filter.label'}}
|
||||
@error={{@model.errors.worker_filter}}
|
||||
@helperText={{t 'resources.credential-store.form.worker_filter.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'worker-filters'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.worker_filter}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'worker_filter')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t 'resources.credential-store.form.worker_filter.label'}}
|
||||
</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-store.form.worker_filter.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'worker-filters'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.worker_filter}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.worker_filter as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#if (or @model.isNew form.isEditable)}}
|
||||
<form.input
|
||||
@name='token'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='token'
|
||||
@value={{@model.token}}
|
||||
@label={{t 'resources.credential-store.form.token.label'}}
|
||||
@error={{@model.errors.token}}
|
||||
@helperText={{t 'resources.credential-store.form.token.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.token}}
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'token')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential-store.form.token.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-store.form.token.help'}}
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.token}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.token as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#unless @model.isNew}}
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.token_hmac}}
|
||||
@label={{t 'resources.credential-store.form.token_hmac.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t 'resources.credential-store.form.token_hmac.label'}}
|
||||
</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/unless}}
|
||||
|
||||
<form.input
|
||||
@name='namespace'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='namespace'
|
||||
@value={{@model.namespace}}
|
||||
@label={{t 'resources.credential-store.form.namespace.label'}}
|
||||
@error={{@model.errors.namespace}}
|
||||
@helperText={{t 'resources.credential-store.form.namespace.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.namespace}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'namespace')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential-store.form.namespace.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-store.form.namespace.help'}}
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.namespace}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.namespace as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='tls_server_name'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='tls_server_name'
|
||||
@value={{@model.tls_server_name}}
|
||||
@label={{t 'resources.credential-store.form.tls_server_name.label'}}
|
||||
@error={{@model.errors.tls_server_name}}
|
||||
@helperText={{t 'resources.credential-store.form.tls_server_name.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.tls_server_name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'tls_server_name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t 'resources.credential-store.form.tls_server_name.label'}}
|
||||
</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.credential-store.form.tls_server_name.help'}}
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.tls_server_name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.tls_server_name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Checkbox::Field
|
||||
name='tls_skip_verify'
|
||||
@@ -225,10 +245,10 @@
|
||||
</Hds::Form::Checkbox::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='client_certificate'
|
||||
@value={{@model.client_certificate}}
|
||||
@isInvalid={{@model.errors.client_certificate}}
|
||||
@isOptional={{true}}
|
||||
name='client_certificate'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -248,10 +268,10 @@
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='client_certificate_key'
|
||||
@value={{@model.client_certificate_key}}
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.client_certificate_key}}
|
||||
name='client_certificate_key'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -271,21 +291,24 @@
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
{{#unless @model.isNew}}
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.client_certificate_key_hmac}}
|
||||
@label={{t
|
||||
'resources.credential-store.form.client_certificate_key_hmac.label'
|
||||
}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t
|
||||
'resources.credential-store.form.client_certificate_key_hmac.label'
|
||||
}}
|
||||
</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/unless}}
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='ca_cert'
|
||||
@value={{@model.ca_cert}}
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.ca_cert}}
|
||||
@name='ca_cert'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -11,28 +11,33 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -48,42 +53,38 @@
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
{{#if @model.isNew}}
|
||||
<form.fieldset>
|
||||
<:body>
|
||||
<Hds::Form::RadioCard::Group as |G|>
|
||||
<G.Legend>{{t 'form.type.label'}}</G.Legend>
|
||||
{{#each @types as |credentialType|}}
|
||||
<G.RadioCard
|
||||
@name={{credentialType}}
|
||||
@value={{credentialType}}
|
||||
@checked={{eq credentialType @model.type}}
|
||||
@maxWidth='20rem'
|
||||
{{on 'input' (fn @changeType credentialType)}}
|
||||
as |R|
|
||||
>
|
||||
<R.Label>{{t
|
||||
(concat 'resources.credential.types.' credentialType)
|
||||
}}</R.Label>
|
||||
<R.Description>{{t
|
||||
(concat 'resources.credential.help.' credentialType)
|
||||
}}</R.Description>
|
||||
</G.RadioCard>
|
||||
{{/each}}
|
||||
</Hds::Form::RadioCard::Group>
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
<Hds::Form::RadioCard::Group as |G|>
|
||||
<G.Legend>{{t 'form.type.label'}}</G.Legend>
|
||||
{{#each @types as |credentialType|}}
|
||||
<G.RadioCard
|
||||
@name={{credentialType}}
|
||||
@value={{credentialType}}
|
||||
@checked={{eq credentialType @model.type}}
|
||||
@maxWidth='20rem'
|
||||
{{on 'input' (fn @changeType credentialType)}}
|
||||
as |R|
|
||||
>
|
||||
<R.Label>{{t (concat 'resources.credential.types.' credentialType)}}
|
||||
</R.Label>
|
||||
<R.Description>{{t
|
||||
(concat 'resources.credential.help.' credentialType)
|
||||
}}
|
||||
</R.Description>
|
||||
</G.RadioCard>
|
||||
{{/each}}
|
||||
</Hds::Form::RadioCard::Group>
|
||||
|
||||
<form.fieldset>
|
||||
<:title>{{t 'resources.credential.form.json.label'}}</:title>
|
||||
<:description>{{t 'resources.credential.form.json.help'}}</:description>
|
||||
<:body>
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<F.Legend>{{t 'resources.credential.form.json.label'}}</F.Legend>
|
||||
<F.HelperText>{{t 'resources.credential.form.json.help'}}</F.HelperText>
|
||||
<F.Control>
|
||||
<Form::Field::JsonSecret
|
||||
@value={{@model.json_object}}
|
||||
@onInput={{fn (mut @model.json_object)}}
|
||||
@showEditButton={{false}}
|
||||
/>
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
</F.Control>
|
||||
</Hds::Form::Fieldset>
|
||||
{{else}}
|
||||
<InfoField
|
||||
@value={{t (concat 'resources.credential.types.' @model.type)}}
|
||||
@@ -94,18 +95,18 @@
|
||||
</F.HelperText>
|
||||
</InfoField>
|
||||
|
||||
<form.fieldset>
|
||||
<:title>{{t 'resources.credential.form.json.label'}}</:title>
|
||||
<:description>{{t 'resources.credential.form.json.help'}}</:description>
|
||||
<:body>
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<F.Legend>{{t 'resources.credential.form.json.label'}}</F.Legend>
|
||||
<F.HelperText>{{t 'resources.credential.form.json.help'}}</F.HelperText>
|
||||
<F.Control>
|
||||
<Form::Field::JsonSecret
|
||||
@disabled={{form.disabled}}
|
||||
@value={{@model.json_object}}
|
||||
@onInput={{fn (mut @model.json_object)}}
|
||||
@showEditButton={{true}}
|
||||
/>
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
</F.Control>
|
||||
</Hds::Form::Fieldset>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -11,28 +11,33 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -71,6 +76,7 @@
|
||||
{{else}}
|
||||
<InfoField
|
||||
@value={{t (concat 'resources.credential.types.' @model.type)}}
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
@@ -79,29 +85,33 @@
|
||||
</InfoField>
|
||||
{{/if}}
|
||||
|
||||
<form.input
|
||||
@name='username'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='username'
|
||||
@value={{@model.username}}
|
||||
@label={{t 'resources.credential.form.username.label'}}
|
||||
@helperText={{t 'resources.credential.form.username.help'}}
|
||||
@error={{@model.errors.username}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.username}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'username')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential.form.username.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'resources.credential.form.username.help'}}</F.HelperText>
|
||||
{{#if @model.errors.username}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.username as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-username>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (or @model.isNew form.isEditable)}}
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{false}}
|
||||
name='private_key'
|
||||
@value={{@model.private_key}}
|
||||
@isInvalid={{@model.errors.private_key}}
|
||||
name='private_key'
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -112,30 +122,36 @@
|
||||
{{#if @model.errors.private_key}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.private_key as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
<E.Message data-test-error-message-private-key>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
<form.input
|
||||
|
||||
<Hds::Form::TextInput::Field
|
||||
name='private_key_passphrase'
|
||||
@type='password'
|
||||
@name='private_key_passphrase'
|
||||
@value={{@model.private_key_passphrase}}
|
||||
@label={{t 'resources.credential.form.private_key_passphrase.label'}}
|
||||
@helperText={{t 'resources.credential.form.private_key_passphrase.help'}}
|
||||
@error={{@model.errors.private_key_passphrase}}
|
||||
@hasVisibilityToggle={{false}}
|
||||
@isInvalid={{@model.errors.private_key_passphrase}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
autocomplete='new-password'
|
||||
as |field|
|
||||
{{on 'input' (set-from-event @model 'private_key_passphrase')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>
|
||||
{{t 'resources.credential.form.private_key_passphrase.label'}}
|
||||
</F.Label>
|
||||
{{#if @model.errors.private_key_passphrase}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.private_key_passphrase as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -11,27 +11,33 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
as |field|
|
||||
>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
<Hds::Form::Textarea::Field
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<E.Message data-test-error-message-name>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -70,6 +76,7 @@
|
||||
{{else}}
|
||||
<InfoField
|
||||
@value={{t (concat 'resources.credential.types.' @model.type)}}
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
@@ -78,42 +85,50 @@
|
||||
</InfoField>
|
||||
{{/if}}
|
||||
|
||||
<form.input
|
||||
@name='username'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='username'
|
||||
@value={{@model.username}}
|
||||
@label={{t 'resources.credential.form.username.label'}}
|
||||
@helperText={{t 'resources.credential.form.username.help'}}
|
||||
@error={{@model.errors.username}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.username}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'username')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential.form.username.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'resources.credential.form.username.help'}}</F.HelperText>
|
||||
{{#if @model.errors.username}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.username as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (or @model.isNew form.isEditable)}}
|
||||
<form.input
|
||||
@name='password'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='password'
|
||||
@type='password'
|
||||
@value={{@model.password}}
|
||||
@label={{t 'resources.credential.form.password.label'}}
|
||||
@helperText={{t 'resources.credential.form.password.help'}}
|
||||
@error={{@model.errors.password}}
|
||||
@isInvalid={{@model.errors.password}}
|
||||
disabled={{form.disabled}}
|
||||
autocomplete='new-password'
|
||||
as |field|
|
||||
{{on 'input' (set-from-event @model 'password')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.credential.form.password.label'}}</F.Label>
|
||||
<F.HelperText>{{t
|
||||
'resources.credential.form.password.help'
|
||||
}}</F.HelperText>
|
||||
{{#if @model.errors.password}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.password as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-password>
|
||||
{{error.message}}
|
||||
</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
Textarea=(component
|
||||
'form/field/list-wrapper/textarea' disabled=@disabled
|
||||
)
|
||||
Select=(component 'form/field/list-wrapper/select' disabled=@disabled)
|
||||
SelectText=(component
|
||||
'form/field/list-wrapper/select-text' disabled=@disabled
|
||||
)
|
||||
)
|
||||
to='field'
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
}}
|
||||
{{#let (unique-id) (unique-id) as |keyHeaderID valueHeaderID|}}
|
||||
<Hds::Table class='list-wrapper-field' name={{@name}}>
|
||||
<:head as |H|>
|
||||
<H.Tr>
|
||||
<H.Th id={{keyHeaderID}}>{{t 'form.key.label'}}</H.Th>
|
||||
<H.Th id={{valueHeaderID}}>{{t 'form.value.label'}}</H.Th>
|
||||
<H.Th>
|
||||
{{t 'titles.actions'}}
|
||||
|
||||
</H.Th>
|
||||
</H.Tr>
|
||||
</:head>
|
||||
<:body as |B|>
|
||||
{{#each-in this.options as |select val|}}
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<Hds::Form::Select::Base
|
||||
@value={{select}}
|
||||
disabled={{@disabled}}
|
||||
@width={{@width}}
|
||||
aria-labelledby={{keyHeaderID}}
|
||||
{{on 'change' (fn this.selectChange select val)}}
|
||||
as |F|
|
||||
>
|
||||
<F.Options>
|
||||
{{#each-in @selectOptions as |key value|}}
|
||||
<option value={{key}} selected={{eq select key}}>
|
||||
{{value}}
|
||||
</option>
|
||||
{{/each-in}}
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Base>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{val}}
|
||||
@type='text'
|
||||
@width={{@width}}
|
||||
disabled={{@disabled}}
|
||||
aria-labelledby={{valueHeaderID}}
|
||||
{{on 'change' (fn this.updateInput select)}}
|
||||
/>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
{{#if this.removeOptionByKey}}
|
||||
<Hds::Button
|
||||
data-test-remove-button={{select}}
|
||||
@text={{t 'actions.remove'}}
|
||||
@color='critical'
|
||||
@icon='trash'
|
||||
@isIconOnly={{true}}
|
||||
disabled={{@disabled}}
|
||||
{{on 'click' (fn this.removeOptionByKey select)}}
|
||||
/>
|
||||
{{/if}}
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
{{/each-in}}
|
||||
|
||||
{{#if this.showNewRow}}
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<Hds::Form::Select::Base
|
||||
@value={{this.newOptionKey}}
|
||||
disabled={{@disabled}}
|
||||
aria-labelledby={{keyHeaderID}}
|
||||
@width={{@width}}
|
||||
{{on 'change' (set-from-event this 'newOptionKey')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Options>
|
||||
|
||||
<option hidden selected value=''>
|
||||
{{t 'titles.choose-an-option'}}
|
||||
</option>
|
||||
{{#each-in this.selectOptions as |key value|}}
|
||||
<option value={{key}} selected={{eq key this.newOptionKey}}>
|
||||
{{value}}
|
||||
</option>
|
||||
{{/each-in}}
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Base>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{this.newOptionValue}}
|
||||
@type='text'
|
||||
@width={{@width}}
|
||||
disabled={{@disabled}}
|
||||
aria-labelledby={{valueHeaderID}}
|
||||
{{on 'input' (set-from-event this 'newOptionValue')}}
|
||||
/>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
<Hds::Button
|
||||
data-test-select-text-add-btn
|
||||
@text={{t 'actions.add'}}
|
||||
@color='secondary'
|
||||
type='button'
|
||||
disabled={{or @disabled (not this.newOptionKey)}}
|
||||
{{on 'click' this.addOption}}
|
||||
/>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
{{/if}}
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
{{/let}}
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
|
||||
export default class MappingListComponent extends Component {
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
@tracked newOptionKey = '';
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
@tracked newOptionValue = '';
|
||||
|
||||
/**
|
||||
* Returns an object of key/value pair that the user enters
|
||||
* @type {object}
|
||||
*/
|
||||
get options() {
|
||||
return this.args?.options || this.args?.model?.[this.args.name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if we need to show an empty row to the users to enter more key/value pairs based on removeDuplicates arg,
|
||||
* by default it is true
|
||||
* @type {object}
|
||||
*/
|
||||
get showNewRow() {
|
||||
if (this.args.removeDuplicates) {
|
||||
return (
|
||||
Object.keys(this.options || {}).length !==
|
||||
Object.keys(this.args.selectOptions || {}).length
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents users from selecting duplicate keys from the select list if there's the arg is set to true
|
||||
* @type {object}
|
||||
*/
|
||||
get selectOptions() {
|
||||
const previouslySelectedKeys = Object.keys(this.options || {});
|
||||
if (this.args.removeDuplicates && previouslySelectedKeys.length) {
|
||||
const newObj = { ...this.args.selectOptions };
|
||||
for (const key of Object.keys(newObj)) {
|
||||
if (previouslySelectedKeys.includes(key)) {
|
||||
delete newObj[key];
|
||||
}
|
||||
}
|
||||
return newObj;
|
||||
} else {
|
||||
return this.args.selectOptions;
|
||||
}
|
||||
}
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Handles when then user makes changes to the select list
|
||||
* @param oldkey {string}
|
||||
* @param oldVal {string}
|
||||
*/
|
||||
@action
|
||||
selectChange(oldkey, oldVal, { target: { value: newKey } }) {
|
||||
const field = this.args.name;
|
||||
const newObj = { ...this.args.model[field], [newKey]: oldVal };
|
||||
delete newObj[oldkey];
|
||||
set(this.args.model, field, newObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles input changes
|
||||
* @param key {string}
|
||||
*/
|
||||
@action
|
||||
updateInput(key, { target: { value: newValue } }) {
|
||||
const field = this.args.name;
|
||||
this.args.model[field] = {
|
||||
...this.args.model[field],
|
||||
[key]: newValue,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If a new key value is entered and an addOption method was specified,
|
||||
* calls addOption with the new key and value. Resets key and value.
|
||||
* Otherwise use the model argument to create the array and update the model
|
||||
*/
|
||||
|
||||
@action
|
||||
addOption() {
|
||||
if (this.args.addOption) {
|
||||
if (this.newOptionKey) {
|
||||
this.args.addOption({
|
||||
key: this.newOptionKey,
|
||||
value: this.newOptionValue,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const field = this.args.name;
|
||||
this.args.model[field] = {
|
||||
...this.args.model[field],
|
||||
[this.newOptionKey]: this.newOptionValue,
|
||||
};
|
||||
}
|
||||
|
||||
this.newOptionKey = '';
|
||||
this.newOptionValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* If removeOptionByIndex method was passed, use that.
|
||||
* Otherwise, use the model to remove an option by key
|
||||
* @param index {number}
|
||||
*/
|
||||
@action
|
||||
removeOptionByKey(selectedKey) {
|
||||
if (this.args.removeOptionByKey) {
|
||||
this.args.removeOptionByKey(selectedKey);
|
||||
} else {
|
||||
const field = this.args.name;
|
||||
const newObj = { ...this.args.model[field] };
|
||||
delete newObj[selectedKey];
|
||||
set(this.args.model, field, newObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
}}
|
||||
|
||||
<Hds::Table class='list-wrapper-field' name={{@name}}>
|
||||
|
||||
<:body as |B|>
|
||||
|
||||
{{#each this.options as |select index|}}
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<Hds::Form::Select::Base
|
||||
@value={{select.value}}
|
||||
@width={{@width}}
|
||||
disabled={{@disabled}}
|
||||
aria-label={{t 'titles.value'}}
|
||||
{{on 'change' (set-from-event select 'value')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Options>
|
||||
{{#each @selectOptions as |selectOption|}}
|
||||
<option
|
||||
value={{selectOption}}
|
||||
selected={{eq select.value selectOption}}
|
||||
>
|
||||
{{selectOption}}
|
||||
</option>
|
||||
{{/each}}
|
||||
</F.Options>
|
||||
</Hds::Form::Select::Base>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
{{#if this.removeOptionByIndex}}
|
||||
<Hds::Button
|
||||
data-test-remove-option-button={{select.value}}
|
||||
@text={{t 'actions.remove'}}
|
||||
@color='critical'
|
||||
@icon='trash'
|
||||
@isIconOnly={{true}}
|
||||
disabled={{@disabled}}
|
||||
{{on 'click' (fn this.removeOptionByIndex index)}}
|
||||
/>
|
||||
{{/if}}
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
{{/each}}
|
||||
|
||||
<B.Tr>
|
||||
<B.Td>
|
||||
<Hds::Form::Select::Base
|
||||
@value={{this.newOptionValue}}
|
||||
@width={{@width}}
|
||||
disabled={{@disabled}}
|
||||
aria-label={{t 'titles.value'}}
|
||||
{{on 'change' (set-from-event this 'newOptionValue')}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
<F.Options>
|
||||
<option disabled={{@disabled}} hidden selected value=''>
|
||||
{{t 'titles.choose-an-option'}}
|
||||
</option>
|
||||
{{#each @selectOptions as |selectOption|}}
|
||||
<option
|
||||
value={{selectOption}}
|
||||
selected={{eq selectOption this.newOptionValue}}
|
||||
>
|
||||
{{selectOption}}
|
||||
</option>
|
||||
{{/each}}
|
||||
</F.Options>
|
||||
|
||||
</Hds::Form::Select::Base>
|
||||
</B.Td>
|
||||
|
||||
<B.Td>
|
||||
<Hds::Button
|
||||
data-test-add-option-button
|
||||
@text={{t 'actions.add'}}
|
||||
@color='secondary'
|
||||
type='button'
|
||||
disabled={{or @disabled (not this.newOptionValue)}}
|
||||
{{on 'click' this.addOption}}
|
||||
/>
|
||||
</B.Td>
|
||||
</B.Tr>
|
||||
</:body>
|
||||
</Hds::Table>
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
|
||||
export default class MappingListSelectComponent extends Component {
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
@tracked newOptionValue = '';
|
||||
|
||||
get options() {
|
||||
return this.args.options || this.args.model[this.args.name];
|
||||
}
|
||||
|
||||
/**
|
||||
* If a new input is entered and an addOption method was specified,
|
||||
* calls addOption with the new input. Resets previous value.
|
||||
* Otherwise use the model argument to create the array and update the model
|
||||
*/
|
||||
|
||||
@action
|
||||
addOption() {
|
||||
if (this.args.addOption && this.newOptionValue) {
|
||||
this.args.addOption({
|
||||
value: this.newOptionValue,
|
||||
});
|
||||
} else {
|
||||
const field = this.args.name;
|
||||
const existingArray = this.args.model[field] ?? [];
|
||||
const newArray = [...existingArray, { value: this.newOptionValue }];
|
||||
set(this.args.model, field, newArray);
|
||||
}
|
||||
|
||||
this.newOptionValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* If removeOptionByIndex method was passed, use that.
|
||||
* Otherwise, use the model to remove an option by index. We recreate a new array after
|
||||
* splicing out the item so that ember is aware that the array has been modified.
|
||||
* @param index {number}
|
||||
*/
|
||||
@action
|
||||
removeOptionByIndex(index) {
|
||||
if (this.args.removeOptionByIndex) {
|
||||
this.args.removeOptionByIndex(index);
|
||||
} else {
|
||||
const field = this.args.name;
|
||||
const newArray = this.args.model[field].filter((_, i) => i !== index);
|
||||
set(this.args.model, field, newArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,30 +11,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -10,30 +10,31 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -94,7 +95,7 @@
|
||||
<InfoField
|
||||
@value={{t 'resources.host-catalog.types.aws'}}
|
||||
@icon='aws-color'
|
||||
disabled={{form.disabled}}
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'titles.provider'}}</F.Label>
|
||||
@@ -103,38 +104,53 @@
|
||||
</InfoField>
|
||||
{{/if}}
|
||||
|
||||
<form.input
|
||||
@name='region'
|
||||
@type='region'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='region'
|
||||
@value={{@model.region}}
|
||||
@label={{t 'resources.host-catalog.form.aws_region.label'}}
|
||||
@helperText={{t 'resources.host-catalog.form.aws_region.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.aws.region'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'region')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.host-catalog.form.aws_region.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.host-catalog.form.aws_region.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.aws.region'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='access_key_id'
|
||||
@type='access_key_id'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='access_key_id'
|
||||
@value={{@model.access_key_id}}
|
||||
@label={{t 'form.access_key_id.label'}}
|
||||
@helperText={{t 'form.access_key_id.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.aws'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'access_key_id')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.access_key_id.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.access_key_id.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.aws'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='secret_access_key'
|
||||
@type='secret_access_key'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='secret_access_key'
|
||||
@value={{@model.secret_access_key}}
|
||||
@label={{t 'form.secret_access_key.label'}}
|
||||
@helperText={{t 'form.secret_access_key.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.aws'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'secret_access_key')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.secret_access_key.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.secret_access_key.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.aws'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Checkbox::Field
|
||||
name='disable_credential_rotation'
|
||||
|
||||
@@ -10,30 +10,31 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -94,7 +95,7 @@
|
||||
<InfoField
|
||||
@value={{t 'resources.host-catalog.types.azure'}}
|
||||
@icon='azure-color'
|
||||
disabled={{form.disabled}}
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'titles.provider'}}</F.Label>
|
||||
@@ -103,49 +104,69 @@
|
||||
</InfoField>
|
||||
{{/if}}
|
||||
|
||||
<form.input
|
||||
@name='tenant_id'
|
||||
@type='tenant_id'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='tenant_id'
|
||||
@value={{@model.tenant_id}}
|
||||
@label={{t 'form.tenant_id.label'}}
|
||||
@helperText={{t 'form.tenant_id.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.azure'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'tenant_id')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.tenant_id.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.tenant_id.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.azure'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='subscription_id'
|
||||
@type='subscription_id'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='subscription_id'
|
||||
@value={{@model.subscription_id}}
|
||||
@label={{t 'form.subscription_id.label'}}
|
||||
@helperText={{t 'form.subscription_id.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.azure'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'subscription_id')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.subscription_id.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.subscription_id.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.azure'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='client_id'
|
||||
@type='client_id'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='client_id'
|
||||
@value={{@model.client_id}}
|
||||
@label={{t 'resources.host-catalog.form.azure_client_id.label'}}
|
||||
@helperText={{t 'resources.host-catalog.form.azure_client_id.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.azure'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'client_id')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.host-catalog.form.azure_client_id.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.host-catalog.form.azure_client_id.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.azure'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='secret_value'
|
||||
@type='secret_value'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='secret_value'
|
||||
@value={{@model.secret_value}}
|
||||
@label={{t 'form.secret.label'}}
|
||||
@helperText={{t 'form.secret.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'host-catalog.azure'}}
|
||||
readonly={{false}}
|
||||
/>
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'secret_value')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.secret.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.secret.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-catalog.azure'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Checkbox::Field
|
||||
name='disable_credential_rotation'
|
||||
|
||||
@@ -10,31 +10,31 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -12,30 +12,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -50,12 +51,9 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} disabled={{form.disabled}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<InfoField
|
||||
@value={{t 'descriptions.provider'}}
|
||||
@@ -125,27 +123,30 @@
|
||||
</:field>
|
||||
</Form::Field::ListWrapper>
|
||||
|
||||
<form.input
|
||||
@name='sync_interval_seconds'
|
||||
@type='number'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='sync_interval_seconds'
|
||||
@value={{@model.sync_interval_seconds}}
|
||||
@label={{t 'form.sync-interval.label'}}
|
||||
@error={{@model.errors.sync_interval_seconds}}
|
||||
@helperText={{t 'form.sync-interval.help'}}
|
||||
@link={{doc-url 'host-set.sync-interval-seconds'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
min='0'
|
||||
step='1'
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.sync_interval_seconds}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'sync_interval_seconds')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.name.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-set.sync-interval-seconds'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.sync_interval_seconds}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.sync_interval_seconds as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
@enableEditText={{t 'actions.edit-form'}}
|
||||
|
||||
@@ -12,30 +12,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -50,17 +51,14 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<InfoField
|
||||
@value={{t 'descriptions.provider'}}
|
||||
@icon='azure-color'
|
||||
disabled={{form.disabled}}
|
||||
readonly={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'titles.provider'}}</F.Label>
|
||||
@@ -101,10 +99,10 @@
|
||||
</Form::Field::ListWrapper>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='filter'
|
||||
@value={{@model.filter_string}}
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.filter_string}}
|
||||
name='filter'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -121,27 +119,29 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@name='sync_interval_seconds'
|
||||
@type='number'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='sync_interval_seconds'
|
||||
@value={{@model.sync_interval_seconds}}
|
||||
@label={{t 'form.sync-interval.label'}}
|
||||
@error={{@model.errors.sync_interval_seconds}}
|
||||
@helperText={{t 'form.sync-interval.help'}}
|
||||
@link={{doc-url 'host-set.sync-interval-seconds'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
min='0'
|
||||
step='1'
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.sync_interval_seconds}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'sync_interval_seconds')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'form.name.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'host-set.sync-interval-seconds'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.sync_interval_seconds}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.sync_interval_seconds as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
|
||||
@@ -11,30 +11,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.name}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isOptional={{true}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -11,37 +11,35 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<Hds::Form::TextInput::Field @value={{@model.type}} disabled={{true}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -56,24 +54,26 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@name='address'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='address'
|
||||
@value={{@model.address}}
|
||||
@label={{t 'form.address.label'}}
|
||||
@error={{@model.errors.address}}
|
||||
@helperText={{t 'form.address.help'}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.address}}
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'address')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.address.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.address.help'}}</F.HelperText>
|
||||
{{#if @model.errors.address}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.address as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
@enableEditText={{t 'actions.edit-form'}}
|
||||
|
||||
@@ -10,31 +10,29 @@
|
||||
@showEditToggle={{if @model.isNew false true}}
|
||||
as |form|
|
||||
>
|
||||
<form.input
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.type}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</InfoField>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.error.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
@@ -55,23 +53,25 @@
|
||||
{{/if}}
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<form.input
|
||||
@name='filter'
|
||||
@type='text'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='filter'
|
||||
@value={{@model.filter_string}}
|
||||
@label={{t 'form.filter.label'}}
|
||||
@error={{@model.errors.filter_string}}
|
||||
@helperText={{t 'form.filter.help'}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.filter_string}}
|
||||
@isRequired={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'filter_string')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.filter.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.filter.help'}}</F.HelperText>
|
||||
{{#if @model.errors.filter_string}}
|
||||
<field.errors as |errors|>
|
||||
{{#each @model.errors.filter_string as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
|
||||
@@ -10,7 +10,7 @@ const RETENTION_POLICY = {
|
||||
custom: 1,
|
||||
do_not_protect: 0,
|
||||
soc: 2555,
|
||||
hippa: 2190,
|
||||
hipaa: 2190,
|
||||
};
|
||||
|
||||
const DELETION_POLICY = { do_not_delete: 0, custom: 1 };
|
||||
|
||||
@@ -11,30 +11,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@isOptional={{true}}
|
||||
name='description'
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
|
||||
@@ -12,45 +12,75 @@
|
||||
<h3>{{t 'resources.worker.form.steps.1.title'}}</h3>
|
||||
<div class='worker-create-section'>
|
||||
{{#if (feature-flag 'byow-pki-hcp-cluster-id')}}
|
||||
<form.input
|
||||
@name='cluster_id'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='cluster_id'
|
||||
@value={{this.clusterID}}
|
||||
@label={{t 'resources.worker.form.cluster_id.label'}}
|
||||
@helperText={{t 'resources.worker.form.cluster_id.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'worker.manage-workers'}}
|
||||
@isOptional={{true}}
|
||||
placeholder='69b6ddb3-ffec-42ab-a994-f43a6519470a'
|
||||
/>
|
||||
{{on 'input' (set-from-event this 'clusterID')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.worker.form.cluster_id.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.worker.form.cluster_id.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'worker.manage-workers'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
<form.input
|
||||
@name='ip_address'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='ip_address'
|
||||
@value={{this.ipAddress}}
|
||||
@label={{t 'resources.worker.form.ip_address.label'}}
|
||||
@helperText={{t 'resources.worker.form.ip_address.help'}}
|
||||
@linkText={{t 'actions.learn-more'}}
|
||||
@link={{doc-url 'worker'}}
|
||||
@isOptional={{true}}
|
||||
placeholder='worker1.example.com'
|
||||
/>
|
||||
{{on 'input' (set-from-event this 'ipAddress')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.worker.form.ip_address.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.worker.form.ip_address.help'}}
|
||||
<Hds::Link::Inline @href={{doc-url 'worker'}}>
|
||||
{{t 'actions.learn-more'}}
|
||||
</Hds::Link::Inline>
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.input
|
||||
@name='config_file_path'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='config_file_path'
|
||||
@value={{this.configFilePath}}
|
||||
@label={{t 'resources.worker.form.config_file_path.label'}}
|
||||
@helperText={{t 'resources.worker.form.config_file_path.help'}}
|
||||
@isOptional={{true}}
|
||||
placeholder='/home/ubuntu/boundary'
|
||||
/>
|
||||
{{on 'input' (set-from-event this 'configFilePath')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.worker.form.config_file_path.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.worker.form.config_file_path.help'}}
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
{{#if (not (feature-flag 'byow-pki-hcp-cluster-id'))}}
|
||||
<form.input
|
||||
@name='initial_upstreams'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='initial_upstreams'
|
||||
@value={{this.initialUpstreams}}
|
||||
@label={{t 'resources.worker.form.initial_upstreams.label'}}
|
||||
@helperText={{t 'resources.worker.form.initial_upstreams.help'}}
|
||||
@isOptional={{true}}
|
||||
placeholder='10.0.0.1, 10.0.0.2, 10.0.0.3'
|
||||
/>
|
||||
{{on 'input' (set-from-event this 'initialUpstreams')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'resources.worker.form.initial_upstreams.label'}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.worker.form.initial_upstreams.help'}}
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
<Form::Field::ListWrapper @layout='horizontal' @disabled={{form.disabled}}>
|
||||
<Form::Field::ListWrapper
|
||||
@layout='horizontal'
|
||||
@disabled={{form.disabled}}
|
||||
@isOptional={{true}}
|
||||
>
|
||||
<:fieldset as |F|>
|
||||
<F.Legend>{{t 'resources.worker.form.worker_tags.label'}}</F.Legend>
|
||||
<F.HelperText>
|
||||
@@ -70,7 +100,7 @@
|
||||
</Form::Field::ListWrapper>
|
||||
|
||||
{{#if (feature-flag 'ssh-session-recording')}}
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<Hds::Form::Fieldset @isOptional={{true}} as |F|>
|
||||
<F.Legend>{{t
|
||||
'resources.worker.form.local_session_recording_storage.label'
|
||||
}}</F.Legend>
|
||||
@@ -94,80 +124,108 @@
|
||||
</F.Control>
|
||||
{{#if this.enableRecordingStoragePath}}
|
||||
<F.Control>
|
||||
<form.input
|
||||
@name='recording_storage_path'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='recording_storage_path'
|
||||
@value={{this.recording_storage_path}}
|
||||
@label={{t 'resources.worker.form.recording_storage_path.label'}}
|
||||
@helperText={{t
|
||||
'resources.worker.form.recording_storage_path.help'
|
||||
}}
|
||||
placeholder='/tmp/worker1'
|
||||
/>
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t
|
||||
'resources.worker.form.recording_storage_path.label'
|
||||
}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t 'resources.worker.form.recording_storage_path.help'}}
|
||||
</F.HelperText>
|
||||
</Hds::Form::TextInput::Field>
|
||||
</F.Control>
|
||||
{{/if}}
|
||||
</Hds::Form::Fieldset>
|
||||
{{/if}}
|
||||
|
||||
<Rose::CodeEditor @codeValue={{this.createConfigText}} as |c|>
|
||||
<c.toolbar>
|
||||
<:action>
|
||||
<span>{{t 'resources.worker.form.steps.1.create_directory'}}</span>
|
||||
</:action>
|
||||
</c.toolbar>
|
||||
<c.fieldEditor class='rose-autosize' @options={{this.shellCodeEditor}} />
|
||||
</Rose::CodeEditor>
|
||||
<p>
|
||||
{{t 'resources.worker.form.steps.1.create_directory'}}
|
||||
</p>
|
||||
|
||||
<Rose::CodeEditor @codeValue={{this.workerConfigText}} as |c|>
|
||||
<c.toolbar>
|
||||
<:action>
|
||||
<span>{{t 'resources.worker.form.steps.1.create_config'}}</span>
|
||||
</:action>
|
||||
</c.toolbar>
|
||||
<c.fieldEditor class='rose-autosize' @options={{this.hclCodeEditor}} />
|
||||
</Rose::CodeEditor>
|
||||
<p>{{t 'resources.worker.form.steps.1.save_config'}}</p>
|
||||
<Hds::CodeBlock
|
||||
@language='bash'
|
||||
@value={{this.createConfigText}}
|
||||
@hasCopyButton={{true}}
|
||||
@hasLineNumbers={{false}}
|
||||
/>
|
||||
|
||||
<p>
|
||||
{{t 'resources.worker.form.steps.1.create_config'}}
|
||||
</p>
|
||||
|
||||
<Hds::CodeBlock
|
||||
@language='hcl'
|
||||
@value={{this.workerConfigText}}
|
||||
@hasCopyButton={{true}}
|
||||
@hasLineNumbers={{false}}
|
||||
/>
|
||||
|
||||
<p>
|
||||
{{t 'resources.worker.form.steps.1.save_config' htmlSafe=true}}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>{{t 'resources.worker.form.steps.2.title'}}</h3>
|
||||
<div class='worker-create-section'>
|
||||
<Rose::CodeEditor @codeValue={{this.installBoundaryText}} as |c|>
|
||||
<c.toolbar>
|
||||
<:action>
|
||||
<span>{{t 'resources.worker.form.steps.2.run_command'}}</span>
|
||||
</:action>
|
||||
</c.toolbar>
|
||||
<c.fieldEditor class='rose-autosize' @options={{this.shellCodeEditor}} />
|
||||
</Rose::CodeEditor>
|
||||
<span>{{t 'resources.worker.form.steps.2.copy_registration_request'}}</span>
|
||||
<code>{{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.label'
|
||||
}}
|
||||
</code>
|
||||
|
||||
<p>
|
||||
{{t 'resources.worker.form.steps.2.run_command'}}
|
||||
</p>
|
||||
|
||||
<Hds::CodeBlock
|
||||
@language='bash'
|
||||
@value={{this.installBoundaryText}}
|
||||
@hasCopyButton={{true}}
|
||||
@hasLineNumbers={{false}}
|
||||
/>
|
||||
|
||||
<p>
|
||||
{{t 'resources.worker.form.steps.2.copy_registration_request'}}
|
||||
<code>{{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.label'
|
||||
}}</code>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3>{{t 'resources.worker.form.steps.3.title'}}</h3>
|
||||
<div class='worker-create-section'>
|
||||
<div class='worker-auth-token'>
|
||||
<form.input
|
||||
@name='worker_auth_registration_request'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='worker_auth_registration_request'
|
||||
@value={{this.generatedWorkerAuthToken}}
|
||||
@disabled={{@model.cannotSave}}
|
||||
@label={{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.label'
|
||||
}}
|
||||
@helperText={{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.help'
|
||||
}}
|
||||
/>
|
||||
@isRequired={{true}}
|
||||
@isInvalid={{@model.errors.worker_generated_auth_token}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event this 'generatedWorkerAuthToken')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.label'
|
||||
}}</F.Label>
|
||||
<F.HelperText>
|
||||
{{t
|
||||
'resources.worker.form.steps.3.worker_auth_registration_request.help'
|
||||
}}
|
||||
</F.HelperText>
|
||||
{{#if @model.errors.worker_generated_auth_token}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.worker_generated_auth_token as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{#if (can 'save worker' @model)}}
|
||||
<Rose::Button
|
||||
@onSubmit={{true}}
|
||||
@style='primary'
|
||||
<Hds::Button
|
||||
@text={{t 'resources.worker.actions.register'}}
|
||||
type='submit'
|
||||
disabled={{@model.cannotSave}}
|
||||
class='nowrap'
|
||||
@disabled={{@model.cannotSave}}
|
||||
>
|
||||
{{t 'resources.worker.actions.register'}}
|
||||
</Rose::Button>
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,39 +11,31 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
@name='type'
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
@helperText={{t 'form.worker_type.help'}}
|
||||
@disabled={{true}}
|
||||
readonly={{true}}
|
||||
/>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
<Hds::Form::TextInput::Field
|
||||
name='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
@error={{@model.errors.name}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.name}}
|
||||
@isOptional={{true}}
|
||||
disabled={{form.disabled}}
|
||||
{{on 'input' (set-from-event @model 'name')}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.name}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.name as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message data-test-error-message-name>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.input>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
name='description'
|
||||
@isOptional={{true}}
|
||||
@value={{@model.description}}
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
disabled={{form.disabled}}
|
||||
as |F|
|
||||
>
|
||||
@@ -82,42 +74,34 @@
|
||||
</F.Control>
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
<form.input
|
||||
@name='address'
|
||||
@type='url'
|
||||
@value={{@model.address}}
|
||||
@label={{t 'form.address.label'}}
|
||||
@helperText={{t 'form.worker_address.help'}}
|
||||
@disabled={{true}}
|
||||
readonly={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.address}} disabled={{form.disabled}} as |F|>
|
||||
<F.Label>{{t 'form.address.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.worker_address.help'}}</F.HelperText>
|
||||
</InfoField>
|
||||
|
||||
{{#let
|
||||
(relative-datetime-live @model.last_status_time)
|
||||
(format-date @model.last_status_time format='yymmddt')
|
||||
as |relativeDate customFormat|
|
||||
}}
|
||||
<form.input
|
||||
@name='last seen'
|
||||
@type='datetime'
|
||||
<InfoField
|
||||
@value={{if
|
||||
@model.last_status_time
|
||||
(concat relativeDate ', ' customFormat)
|
||||
}}
|
||||
@label={{t 'form.worker_last_seen.label'}}
|
||||
@helperText={{t 'form.worker_last_seen.help'}}
|
||||
@disabled={{true}}
|
||||
readonly={{true}}
|
||||
/>
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.worker_last_seen.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.worker_last_seen.help'}}</F.HelperText>
|
||||
</InfoField>
|
||||
|
||||
{{/let}}
|
||||
|
||||
<form.input
|
||||
@name='release version'
|
||||
@value={{@model.release_version}}
|
||||
@label={{t 'form.worker_release_version.label'}}
|
||||
@helperText={{t 'form.worker_release_version.help'}}
|
||||
@disabled={{true}}
|
||||
readonly={{true}}
|
||||
/>
|
||||
<InfoField @value={{@model.release_version}} readonly={{true}} as |F|>
|
||||
<F.Label>{{t 'form.worker_release_version.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.worker_release_version.help'}}</F.HelperText>
|
||||
</InfoField>
|
||||
|
||||
{{#if (can 'save worker' @model)}}
|
||||
<form.actions
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
@disabled={{@model.canSave}}
|
||||
{{on 'click' (route-action 'delete' @model)}}
|
||||
{{on 'click' @delete}}
|
||||
>
|
||||
{{t 'resources.group.actions.delete'}}
|
||||
</dropdown.button>
|
||||
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='group' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.group.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='host-catalog' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.host-catalog.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
+1
-7
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='host-set' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.host-set.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
+1
-7
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='host' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.host.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='host' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.host.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='role' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.role.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='target' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.target.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -8,10 +8,4 @@
|
||||
<DocLink @doc='user' @iconSize='large' />
|
||||
</h2>
|
||||
<p>{{t 'resources.user.description'}}</p>
|
||||
<Copyable
|
||||
@text={{@model.id}}
|
||||
@buttonText={{t 'actions.copy-to-clipboard'}}
|
||||
@acknowledgeText={{t 'states.copied'}}
|
||||
>
|
||||
<code>{{@model.id}}</code>
|
||||
</Copyable>
|
||||
<Hds::Copy::Snippet @textToCopy={{@model.id}} @color='secondary' />
|
||||
@@ -5,9 +5,45 @@
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class AccountChangePasswordController extends Controller {
|
||||
// =services
|
||||
|
||||
@service session;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Changes the password on the account and then redirects to the index route.
|
||||
* @param {AccountModel} account
|
||||
* @param {string} currentPassword
|
||||
* @param {string} newPassword
|
||||
*/
|
||||
@action
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.save-success')
|
||||
async changePassword(account, currentPassword, newPassword) {
|
||||
await account.changePassword(currentPassword, newPassword);
|
||||
// Transition to index after success. We ignore errors in the transition,
|
||||
// since the index route is responsible for additional
|
||||
// redirects depending on the authentication context. These additional
|
||||
// redirects may abort this initial transition, resulting in a
|
||||
// TransitionAborted error, which we do not want to show to the user.
|
||||
try {
|
||||
await this.router.replaceWith('index');
|
||||
} catch (e) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On cancel, redirects to index route for further processing.
|
||||
*/
|
||||
@action
|
||||
cancel() {
|
||||
this.router.replaceWith('index');
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,73 @@
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default class ApplicationController extends Controller {
|
||||
// =services
|
||||
|
||||
@service session;
|
||||
@service flashMessages;
|
||||
@service features;
|
||||
@service featureEdition;
|
||||
@service flashMessages;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Delegates invalidation to the session service.
|
||||
*/
|
||||
@action
|
||||
invalidateSession() {
|
||||
this.session.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the specified color theme to the root ember element.
|
||||
* @param {string} theme - "light", "dark", or nullish (system default)
|
||||
*/
|
||||
@action
|
||||
toggleTheme(theme) {
|
||||
const rootElementSelector = getOwner(this).rootElement;
|
||||
const rootEl = getOwner(this)
|
||||
.lookup('service:-document')
|
||||
.querySelector(rootElementSelector);
|
||||
this.session.set('data.theme', theme);
|
||||
switch (theme) {
|
||||
case 'light':
|
||||
rootEl.classList.add('rose-theme-light');
|
||||
rootEl.classList.remove('rose-theme-dark');
|
||||
break;
|
||||
case 'dark':
|
||||
rootEl.classList.add('rose-theme-dark');
|
||||
rootEl.classList.remove('rose-theme-light');
|
||||
break;
|
||||
default:
|
||||
rootEl.classList.remove('rose-theme-dark');
|
||||
rootEl.classList.remove('rose-theme-light');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to specified edition.
|
||||
* Options are oss, enterprise, and hcp.
|
||||
* @param {string} edition
|
||||
*/
|
||||
@action
|
||||
toggleEdition(edition) {
|
||||
this.featureEdition.setEdition(edition);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} feature
|
||||
*/
|
||||
@action
|
||||
toggleFeature(feature) {
|
||||
if (this.features.isEnabled(feature)) {
|
||||
this.features.disable(feature);
|
||||
} else {
|
||||
this.features.enable(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAliasesAliasIndexController extends Controller {
|
||||
@controller('scopes/scope/aliases/index') aliases;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAliasesIndexController extends Controller {
|
||||
// =services
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAliasesNewController extends Controller {
|
||||
@controller('scopes/scope/aliases/index') aliases;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodAccountsAccountIndexController extends Controller {
|
||||
@controller('scopes/scope/auth-methods/auth-method/accounts/index') accounts;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodAccountsAccountSetPasswordController extends Controller {
|
||||
// =controllers
|
||||
|
||||
@controller('scopes/scope/auth-methods/auth-method/accounts/index') accounts;
|
||||
|
||||
// =services
|
||||
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Set password for the specified account.
|
||||
* @param {AccountModel} account
|
||||
* @param {string} password
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.save-success')
|
||||
async setPassword(account, password) {
|
||||
await account.setPassword(password);
|
||||
await this.router.replaceWith(
|
||||
'scopes.scope.auth-methods.auth-method.accounts.account.set-password',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodAccountsIndexController extends Controller {
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Rollback changes on an account.
|
||||
* @param {AccountModel} account
|
||||
*/
|
||||
@action
|
||||
async cancel(account) {
|
||||
const { isNew } = account;
|
||||
account.rollbackAttributes();
|
||||
if (isNew) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.accounts',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an account in current scope.
|
||||
* @param {AccountModel} account
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess(({ isNew }) =>
|
||||
isNew ? 'notifications.create-success' : 'notifications.save-success',
|
||||
)
|
||||
async save(account, password) {
|
||||
const { isNew } = account;
|
||||
const adapterOptions = {};
|
||||
if (isNew) {
|
||||
adapterOptions.password = password;
|
||||
}
|
||||
await account.save({ adapterOptions });
|
||||
if (this.can.can('read model', account)) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.accounts.account',
|
||||
account,
|
||||
);
|
||||
} else {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.accounts',
|
||||
);
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an account in current scope and redirect to index
|
||||
* @param {AccountModel} account
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(account) {
|
||||
await account.destroyRecord();
|
||||
await this.router.replaceWith(
|
||||
'scopes.scope.auth-methods.auth-method.accounts',
|
||||
);
|
||||
await this.router.refresh();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodAccountsNewController extends Controller {
|
||||
@controller('scopes/scope/auth-methods/auth-method/accounts/index') accounts;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsIndexController extends Controller {
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Rollback changes on a managed group.
|
||||
* @param {ManagedGroupModel} managedGroup
|
||||
*/
|
||||
@action
|
||||
async cancel(managedGroup) {
|
||||
const { isNew } = managedGroup;
|
||||
managedGroup.rollbackAttributes();
|
||||
if (isNew) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.managed-groups',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a managed group in current scope.
|
||||
* @param {ManagedGroupModel} managedGroup
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess(({ isNew }) =>
|
||||
isNew ? 'notifications.create-success' : 'notifications.save-success',
|
||||
)
|
||||
async save(managedGroup) {
|
||||
await managedGroup.save();
|
||||
if (this.can.can('read model', managedGroup)) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.managed-groups.managed-group',
|
||||
managedGroup,
|
||||
);
|
||||
} else {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.auth-methods.auth-method.managed-groups',
|
||||
);
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a managed group in current scope and redirect to index
|
||||
* @param {ManagedGroupModel} managed group
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(managedGroup) {
|
||||
await managedGroup.destroyRecord();
|
||||
await this.router.replaceWith(
|
||||
'scopes.scope.auth-methods.auth-method.managed-groups',
|
||||
);
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of string array fields in order to force the instance
|
||||
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||
* to the original expected array.
|
||||
*
|
||||
* The deep copy implemented here is required to ensure that both the
|
||||
* array itself and its members are all new.
|
||||
*
|
||||
* @param {managedGroupModel} managedGroup
|
||||
*/
|
||||
@action
|
||||
edit(managedGroup) {
|
||||
if (managedGroup.group_names) {
|
||||
managedGroup.group_names = structuredClone(managedGroup.group_names);
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsManagedGroupIndexController extends Controller {
|
||||
@controller('scopes/scope/auth-methods/index') authMethods;
|
||||
@controller('scopes/scope/auth-methods/auth-method/managed-groups/index')
|
||||
managedGroups;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsManagedGroupMembersController extends Controller {
|
||||
@controller('scopes/scope/auth-methods/auth-method/managed-groups/index')
|
||||
managedGroups;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsNewController extends Controller {
|
||||
@controller('scopes/scope/auth-methods/index') authMethods;
|
||||
@controller('scopes/scope/auth-methods/auth-method/managed-groups/index')
|
||||
managedGroups;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default class ScopesScopeAuthMethodsIndexController extends Controller {
|
||||
// =attributes
|
||||
@@ -15,4 +16,35 @@ export default class ScopesScopeAuthMethodsIndexController extends Controller {
|
||||
get hasPrimaryAuthMethod() {
|
||||
return Boolean(this.scopeModel.primary_auth_method_id);
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Removes an item from array `property` at `index` on the
|
||||
* passed `authMethod`. This is used to manage entries in fragment array
|
||||
* fields such as `signing_algorithms`.
|
||||
* @param {AuthMethodModel} authMethod
|
||||
* @param {string} property
|
||||
* @param {number} index
|
||||
*/
|
||||
@action
|
||||
async removeItemByIndex(authMethod, property, index) {
|
||||
const array = authMethod.get(property).filter((item, i) => i !== index);
|
||||
authMethod.set(property, array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a string item to array `property` on the passed `authMethod`.
|
||||
* This is used to manage entries in fragment OIDC string array fields such
|
||||
* as `signing_algorithms`.
|
||||
* @param {AuthMethodModel} authMethod
|
||||
* @param {string} property
|
||||
* @param {string} value
|
||||
*/
|
||||
@action
|
||||
async addStringItem(authMethod, property, value) {
|
||||
const existingArray = authMethod[property] ?? [];
|
||||
const array = [...existingArray, { value }];
|
||||
authMethod.set(property, array);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrariesCredentialLibraryIndexController extends Controller {
|
||||
@controller(
|
||||
'scopes/scope/credential-stores/credential-store/credential-libraries/index',
|
||||
)
|
||||
credentialLibraries;
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrariesIndexController extends Controller {
|
||||
@controller('scopes/scope/credential-stores/index') credentialStores;
|
||||
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Rollback changes on a credential library.
|
||||
* @param {CredentialLibraryModel} credentialLibrary
|
||||
*/
|
||||
@action
|
||||
async cancel(credentialLibrary) {
|
||||
const { isNew } = credentialLibrary;
|
||||
credentialLibrary.rollbackAttributes();
|
||||
if (isNew)
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle save of a credential library
|
||||
* @param {CredentialLibraryModel} credentialLibrary
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess(({ isNew }) =>
|
||||
isNew ? 'notifications.create-success' : 'notifications.save-success',
|
||||
)
|
||||
async save(credentialLibrary) {
|
||||
await credentialLibrary.save();
|
||||
if (this.can.can('read model', credentialLibrary)) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries.credential-library',
|
||||
credentialLibrary,
|
||||
);
|
||||
} else {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries',
|
||||
);
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle delete of a credential library
|
||||
* @param {CredentialLibraryModel} credentialLibrary
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(credentialLibrary) {
|
||||
await credentialLibrary.destroyRecord();
|
||||
await this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credential-libraries',
|
||||
);
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of array fields in order to force the instance
|
||||
* into a dirty state. This ensures that `model.rollbackAttributes()` reverts
|
||||
* to the original expected array.
|
||||
*
|
||||
* The deep copy implemented here is required to ensure that both the
|
||||
* array itself and its members are all new.
|
||||
*
|
||||
* @param {credentialLibraryModel} credentialLibrary
|
||||
*/
|
||||
@action
|
||||
edit(credentialLibrary) {
|
||||
const { critical_options, extensions } = credentialLibrary;
|
||||
credentialLibrary.critical_options = structuredClone(critical_options);
|
||||
credentialLibrary.extensions = structuredClone(extensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update type of credential library
|
||||
* @param {string} type
|
||||
*/
|
||||
@action
|
||||
async changeType(type) {
|
||||
await this.router.replaceWith({ queryParams: { type } });
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -3,10 +3,13 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrariesNewController extends Controller {
|
||||
// =services
|
||||
@controller(
|
||||
'scopes/scope/credential-stores/credential-store/credential-libraries/index',
|
||||
)
|
||||
credentialLibraries;
|
||||
|
||||
// =attributes
|
||||
queryParams = ['type'];
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialsCredentialIndexController extends Controller {
|
||||
@controller(
|
||||
'scopes/scope/credential-stores/credential-store/credentials/index',
|
||||
)
|
||||
credentials;
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialsIndexController extends Controller {
|
||||
@controller('scopes/scope/credential-stores/index') credentialStores;
|
||||
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Rollback changes on a credential.
|
||||
* @param {CredentialModel} credential
|
||||
*/
|
||||
@action
|
||||
async cancel(credential) {
|
||||
const { isNew } = credential;
|
||||
credential.rollbackAttributes();
|
||||
if (isNew)
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credentials',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle save of a credential
|
||||
* @param {CredentialModel} credential
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess(({ isNew }) =>
|
||||
isNew ? 'notifications.create-success' : 'notifications.save-success',
|
||||
)
|
||||
async save(credential) {
|
||||
await credential.save();
|
||||
if (this.can.can('read credential', credential)) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credentials.credential',
|
||||
credential,
|
||||
);
|
||||
} else {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store.credentials',
|
||||
);
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
/**
|
||||
* Handle delete of a credential
|
||||
* @param {Credential} credential
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(credential) {
|
||||
await credential.destroyRecord();
|
||||
await this.router.replaceWith(
|
||||
'scopes.scope.credential-stores.credential-store.credentials',
|
||||
);
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update type of credential
|
||||
* @param {string} type
|
||||
*/
|
||||
@action
|
||||
async changeType(type) {
|
||||
await this.router.replaceWith({ queryParams: { type } });
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -3,10 +3,13 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreCredentialsNewController extends Controller {
|
||||
// =services
|
||||
@controller(
|
||||
'scopes/scope/credential-stores/credential-store/credentials/index',
|
||||
)
|
||||
credentials;
|
||||
|
||||
// =attributes
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresCredentialStoreIndexController extends Controller {
|
||||
@controller('scopes/scope/credential-stores/index') credentialStores;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeCredentialStoresIndexController extends Controller {
|
||||
// =services
|
||||
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Handle save
|
||||
* @param {CredentialStoreModel} credentialStore
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess('notifications.save-success')
|
||||
async save(credentialStore) {
|
||||
await credentialStore.save();
|
||||
if (this.can.can('read model', credentialStore)) {
|
||||
await this.router.transitionTo(
|
||||
'scopes.scope.credential-stores.credential-store',
|
||||
credentialStore,
|
||||
);
|
||||
} else {
|
||||
await this.router.transitionTo('scopes.scope.credential-stores');
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback changes on credential stores.
|
||||
* @param {CredentialStoreModel} credentialStore
|
||||
*/
|
||||
@action
|
||||
async cancel(credentialStore) {
|
||||
const { isNew } = credentialStore;
|
||||
credentialStore.rollbackAttributes();
|
||||
if (isNew) {
|
||||
await this.router.transitionTo('scopes.scope.credential-stores');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the credential store and redirects to index
|
||||
* @param {CredentialStoreModel} credentialStore
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(credentialStore) {
|
||||
await credentialStore.destroyRecord();
|
||||
await this.router.replaceWith('scopes.scope.credential-stores');
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update type of credential store
|
||||
* @param {string} type
|
||||
*/
|
||||
@action
|
||||
async changeType(type) {
|
||||
await this.router.replaceWith({ queryParams: { type } });
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeCredentialStoresNewController extends Controller {
|
||||
// =services
|
||||
@controller('scopes/scope/credential-stores/index') credentialStores;
|
||||
|
||||
// =attributes
|
||||
queryParams = ['type'];
|
||||
|
||||
@@ -4,10 +4,16 @@
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeGroupsGroupAddMembersController extends Controller {
|
||||
// =services
|
||||
|
||||
@service router;
|
||||
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
@@ -26,4 +32,29 @@ export default class ScopesScopeGroupsGroupAddMembersController extends Controll
|
||||
const sorted = [global, ...orgsAndProjects].flat();
|
||||
return sorted;
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Adds members to the group and saves, replaces with the members index
|
||||
* route, and notifies the user of success or error.
|
||||
* @param {GroupModel} group
|
||||
* @param {[string]} userIDs
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.add-success')
|
||||
async addMembers(group, userIDs) {
|
||||
await group.addMembers(userIDs);
|
||||
await this.router.replaceWith('scopes.scope.groups.group.members');
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to group members as if nothing ever happened.
|
||||
*/
|
||||
@action
|
||||
async cancel() {
|
||||
await this.router.replaceWith('scopes.scope.groups.group.members');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeGroupsGroupIndexController extends Controller {
|
||||
@controller('scopes/scope/groups/index') groups;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeGroupsGroupMembersController extends Controller {
|
||||
@controller('scopes/scope/groups/index') groups;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { confirm } from 'core/decorators/confirm';
|
||||
import { notifySuccess, notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeGroupsIndexController extends Controller {
|
||||
// =services
|
||||
@service can;
|
||||
@service router;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Rollback changes on a group.
|
||||
* @param {GroupModel} group
|
||||
*/
|
||||
@action
|
||||
async cancel(group) {
|
||||
const { isNew } = group;
|
||||
group.rollbackAttributes();
|
||||
if (isNew) await this.router.transitionTo('scopes.scope.groups');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a group in current scope.
|
||||
* @param {GroupModel} group
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(({ message }) => message)
|
||||
@notifySuccess(({ isNew }) =>
|
||||
isNew ? 'notifications.create-success' : 'notifications.save-success',
|
||||
)
|
||||
async save(group) {
|
||||
await group.save();
|
||||
if (this.can.can('read model', group)) {
|
||||
await this.router.transitionTo('scopes.scope.groups.group', group);
|
||||
} else {
|
||||
await this.router.transitionTo('scopes.scope.groups');
|
||||
}
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a group in current scope and redirect to index
|
||||
* @param {GroupModel} group
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.delete-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.delete-success')
|
||||
async delete(group) {
|
||||
await group.destroyRecord();
|
||||
await this.router.replaceWith('scopes.scope.groups');
|
||||
await this.router.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a member from the current role and redirect to members index.
|
||||
* @param {GroupModel} group
|
||||
* @param {UserModel} member
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@confirm('questions.remove-confirm')
|
||||
@notifyError(({ message }) => message, { catch: true })
|
||||
@notifySuccess('notifications.remove-success')
|
||||
async removeMember(group, member) {
|
||||
await group.removeMember(member.id);
|
||||
await this.router.refresh();
|
||||
}
|
||||
}
|
||||
Loaded 100 of 274 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user