Compare commits

..
34 Commits
Author SHA1 Message Date
Lisbet Alvarez 002f64d676 update cli version and update changelog (#2165)
* docs: ✏️ update cli version and update changelog
2024-02-28 10:31:34 -08:00
Devon Anderson c09efbae10 chore: 🤖 Migrate form.inut to Hds::TextInput::Field (#2151)
* chore: 🤖 Migrate `form.inut` to `Hds::TextInput::Field`

Migrate `form/create-worker-led` form to use `Hds:Text::InputField`
instead of `form.input`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12477

* refactor: 💡 Added `optional` and `requred` arguments for fields

Added `optional` and `require` arguments for all needed fields.

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12477

* refactor: 💡 fix failing test

fix failing test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12477
2024-02-28 13:02:02 -05:00
Devon Anderson 060f995f94 chore: 🤖 Migrate form.input to Hds::TextInput::Field (#2143)
* chore: 🤖 Migrate `form.input` to `Hds::TextInput::Field`

Migrate `form/credential` forms for for `json`, `ssh_private_key`,
`username_password`, and `form/credential-store` forms for `static` and
`vault` to use `Hds::TextInput::Field` instead of `form.input`.

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 fix broken test

fix broken test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 fix broken test

fix broken test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 added `@hasVisibilityToggle` back and clean up test

Added `@hasVisibilityToggle` back and clean up test by use `data-test-*`
attributes for error messaging

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 set `@hasVisiblityToggle` to default

set `@hasVisiblityToggle` to default

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 field argument clean up

field argument cleanup

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 switch `disabled` argument to `readonly`

switch `disabled` argument to `readonly`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461

* refactor: 💡 clean up attribute order

clean up field attribute order

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12461
2024-02-28 12:21:37 -05:00
Devon Anderson f1c5c99664 chore: 🤖 Migrate form.input to Hds::TextInput::Field (#2147)
* chore: 🤖 Migrate `form.input` to `Hds::TextInput::Field`

Migrate `form/host-set/aws`, `form/host-set/azure` and
`form/host-set/static` forms to use `Hds::TextInputField` instead of
`form.input`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12469

* Update index.hbs

removed `@isOptional` field.

* Update index.hbs

removed `@isOptional` argument

* refactor: 💡 fix lint errors

fix lint

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12469

* refactor: 💡 field argument cleanup

field argument cleanup

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12469

* refactor: 💡 switch `disabled` argument to `readonly`

switch `disabled` argument to `readonly`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12469

* refactor: 💡 order of attributes

change order of attributes

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12469
2024-02-28 10:18:22 -05:00
af5fb8e814 chore(deps): bump es5-ext from 0.10.53 to 0.10.63 (#2162)
Bumps [es5-ext](https://github.com/medikoo/es5-ext) from 0.10.53 to 0.10.63.
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.53...v0.10.63)

---
updated-dependencies:
- dependency-name: es5-ext
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2024-02-27 16:49:29 -05:00
Devon Anderson cf5334556f chore: 🤖 Migrate form.input to Hds::TextInput:Field (#2150)
* chore: 🤖 Migrate `form.input` to `Hds::TextInput:Field`

Migrate  `form/manage-groups/oidc`, `form/user` and `form/worker` forms
to use `Hds::TextInput::Field` instead of `form.input`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12473

* refactor: 💡 argument clean up

argument clean up

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12473

* refactor: 💡 refactor InfoField arguments for `readonly`

Refactor InfoField component's arguments for `readonly` instead of
`disabled`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12473
2024-02-27 14:57:54 -05:00
Dharini Jeeva 5c6c9bb69f fix: 🐛 move config processing to mirage serializer (#2163) 2024-02-27 11:25:51 -08:00
Devon Anderson 26a77edbc7 chore: 🤖 Migrate form.inpu to use Hds::TextInput::Field` (#2145)
* chore: 🤖 Migrate `form.inpu` to use Hds::TextInput::Field`

Migrate `form/group`, `form/host-static`, `form/host-catalog/aws` and
`form/host-catalog/azure` forms to use `Hds::TextInputField instead of
`form.input`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12466

* refactor: 💡 use `data-test` attributes for testing

use `data-test` attributes for testing error messaging.

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12466

* refactor: 💡 field argument cleanup

field argument cleanup

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12466

* refactor: 💡 switch `disabled` argument to `readonly`

switch `disabled` argument to `readonly`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12466
2024-02-27 13:52:50 -05:00
Dharini Jeeva 3fc865d226 Fix credential library mocks (#2161)
* fix: 🐛 vault cred library mocks
2024-02-27 09:41:28 -08:00
Devon Anderson 47d7ceccf7 chore: Migrate form.input to use Hds text input field (#2154)
* chore: 🤖 Migrate `form.input` to use `Hds` form input field

Migrate `form.input` for `clusterurl.hbs` to use
`Hds::Form::TextInput::Field`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12478

* refactor: 💡 removed unused `data-test` attribute

removed unused `data-test` attribute

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12478
2024-02-27 09:31:48 -05:00
Dharini Jeeva 38df28be55 fix: 🐛 change delete to detach Storage policy from a scope (#2160)
* fix: 🐛 change delete to detach Storage policy from a scope
2024-02-26 12:50:38 -08:00
Dharini Jeeva 6d7c86a08c fix: 🐛 spelling (#2159)
✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12813
2024-02-26 11:18:34 -08:00
Michael Li 58a31b880b test(e2e): Add enterprise tests for creating TCP/SSH targets (#2158) 2024-02-26 12:59:34 -05:00
Dharini Jeeva 453ab7911d doc: var name (#2140)
* fix: 🐛 var name
2024-02-23 15:52:08 -08:00
Dharini Jeeva 93c8d481fd Icu 12567 add new field credential mapping overrides (#2156)
* chore: 🤖 add credential type select list
2024-02-23 10:07:52 -08:00
Carlos Alcaide Corvo 956f6fd04d refactor: 💡 Adopt HDS copy snippet Desktop UI (#2146)
* refactor: 💡 Adopt HDS copy snippet Desktop UI

Adopt HDS copy snippet and delete usage of Copyable custom component
2024-02-22 13:56:56 -08:00
dependabot[bot]andZhihe Li 912be13744 chore(deps): bump ip from 1.1.8 to 1.1.9 in /ui/desktop/electron-app (#2155)
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9)

---
updated-dependencies:
- dependency-name: ip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2024-02-22 15:28:18 -05:00
dependabot[bot]andZhihe Li fc1b91c8f9 chore(deps): bump ip from 1.1.5 to 1.1.9 (#2153)
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.5 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.5...v1.1.9)

---
updated-dependencies:
- dependency-name: ip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
2024-02-22 15:10:54 -05:00
Devon Anderson 8e40b01caf refactor: 💡 Quick fix for client_secret attributes (#2157)
`client_secret` attribute needed to be `@type` instead of `type`
2024-02-22 14:52:31 -05:00
Devon Anderson 20181c978f refactor: 💡 Migrate form.input to Hds::TextInput::Field (#2142)
* refactor: 💡 Migrate `form.input` to `Hds::TextInput::Field`

Migrate the use of `form.input` to `Hds::TextInput::Field` for OIDC and
Password auth-method form

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459

* Update index.hbs

move `name` attribute to top of attribute list for readers

* refactor: 💡 fix `step` and `min` arguments

fix `step` and `min` arguments

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459

* refactor: 💡 clean up order of arguments and add `data-test` att

clean up order of arguments and add `data-test` attributes

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459

* refactor: 💡 Add `@isOptional` attribute to all needed fields

Add `@isOptiona` attributes to all needed fields

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459

* Update index.hbs

add `@hasVisibilityToggle`

* refactor: 💡 fix lint

fix lint

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459

* refactor: 💡 quick attribute refactor

quick attribute refactor

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12459
2024-02-22 13:22:18 -05:00
Lisbet Alvarez db78f1ae4d docs: ✏️ update enos readme (#2139)
* docs: ✏️ update enos readme

* docs: ✏️ update cmd

* docs: ✏️ update wording

* docs: ✏️ add link

* docs: ✏️ use diff slack channel
2024-02-20 17:57:21 -08:00
Dharini Jeeva 592bb15022 chore: 🤖 add credential type select list (#2144)
* chore: 🤖 add credential type select list
2024-02-16 15:57:14 -08:00
Carlos Alcaide Corvo f002e14673 [Admin UI] Adopt HDS::Copy::Snippet (#2141)
* refactor: 💡 Adopt HDS copy snippet

Adopt HDS copy snippet and delete usage of Copyable custom component
within Admin UI.
2024-02-16 02:19:43 -08:00
Devon Anderson a1b455e5eb refactor: 💡 Migrate last form.fieldset over to use Hds (#2138)
* refactor: 💡 Migrate last `form.fieldset` over to use Hds

Migrate last `form.fieldset` over to use `Hds::FormFieldset`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-9427

* refactor: 💡 removed `fieldset` from `RadioCard`

Removed unneeded `fieldset` from `RadioCard`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-9427
2024-02-15 09:51:39 -05:00
Dharini Jeeva 786e6130cd feat: 🎸 allow session recording deletion (#2132)
* feat: 🎸 allow session recording deletion
2024-02-13 13:26:23 -08:00
hashicorp-copywrite[bot] 4db8b8e1e7 [COMPLIANCE] Add Copyright and License Headers (#2137)
Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2024-02-12 16:31:46 -05:00
Lisbet Alvarez 4be8d10323 Icu 12557 refresh not working as intended on windows (#2133)
* fix: 🐛 add flag

* refactor: 💡 add true val

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12557
2024-02-09 11:58:41 -08:00
Devon Anderson c79a1fca79 chore: 🤖 Create select field render for the Form::Field::ListWrapper (#2112)
* chore: 🤖 Create `select` field render for the `Form::Field::ListWrapper`
component

Create a `select` field render for the `Form::Field::ListWrapper`
component.

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 Added additional test

Added additional testing around removing and adding an option, and
refactored for better usability

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 Refactored getter to check for option and model arg

Refactore getter to check for options and model args.

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 Use select field with `signing_algorithms`

Use select field with `signing_algorithms`

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 fix test

fix test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 fix failing test

fix failing test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271

* refactor: 💡 fix update auth-method test

fix update auth-method test

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12271
2024-02-09 08:42:15 -05:00
Cameron Perera d2d332b7d1 refactor: 💡 only show scopes with auth methods at authenticate (#2129)
* refactor: 💡 only show scopes with auth methods at authenticate

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* test: 💍 verify scopes with no auth methods are hidden

when authenticating

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* refactor: 💡 update logic for fetching scopes and auth methods

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* refactor: 💡 PR feedback changes

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* refactor: 💡 added unless block back to template

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* refactor: 💡 update admin authenticate route and template

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355

* test: 💍 add test for orgs with no auth methods admin ui

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-2355
2024-02-08 10:01:20 -06:00
022ac0fffe Result of tsccr-helper -log-level=info gha update -latest . (#2126)
Co-authored-by: hashicorp-tsccr[bot] <hashicorp-tsccr[bot]@users.noreply.github.com>
Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
Co-authored-by: Lisbet Alvarez <107949262+lisbet-alvarez@users.noreply.github.com>
2024-02-07 16:42:38 -08:00
Cameron Perera f3622fb92b feat: 🎸 remove Type of Worker from worker details page (#2131)
* feat: 🎸 remove Type of Worker from worker details page

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12409

* refactor: 💡 remove unused translation

✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12409
2024-02-06 14:48:28 -06:00
Zhihe Li f8b5dcd824 fix: 🐛 Add error notification if adding token to daemon fails (#2127)
✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12488
2024-02-05 14:21:13 -05:00
Alex 056008e13e chore: 🤖 replace Rose::CodeEditor with Hds::CodeBlock on new worker page (#2128)
* chore: 🤖 replace `Rose::CodeEditor` with `Hds::CodeBlock` for new workers
2024-02-05 09:50:08 -08:00
Alex ea03d6e488 chore: 🤖 update HDS to 3.5.0 (#2116)
* chore: update to 3.4.1

`@hashicorp/design-system-components` to `3.4.1`
 - `@hashicorp/ember-flight-icons` to `4.0.5`

* chore: update to 3.5.0
2024-01-31 15:49:02 -05:00
151 changed files with 2985 additions and 2106 deletions

No files matched your search

+12 -12
View File
@@ -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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
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@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0
with:
name: admin-ui-hcp
path: ./ui/admin/dist/
+2 -2
View File
@@ -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@e6a47e25652c5dbefe5b65d3b8e8dab0e9364b21 # codeql-bundle-v2.16.0
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@e6a47e25652c5dbefe5b65d3b8e8dab0e9364b21 # codeql-bundle-v2.16.0
+8 -8
View File
@@ -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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
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');
}
@@ -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,
@@ -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
+2
View File
@@ -798,6 +798,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));
@@ -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',
@@ -60,6 +60,7 @@ export default factory.extend({
'read',
'download',
'reapply-storage-policy',
'delete',
],
withNonExistingUserAndTarget: trait({
@@ -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),
);
});
});
@@ -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',
);
+2 -2
View File
@@ -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:
+19 -4
View File
@@ -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:
+1 -1
View File
@@ -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;
}
}
@@ -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' />
@@ -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>
-68
View File
@@ -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;
}
}
@@ -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' />
@@ -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);
}
}
}
+15 -14
View File
@@ -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
+1 -1
View File
@@ -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 };
+15 -14
View File
@@ -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>
+30 -46
View File
@@ -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
@@ -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' />
@@ -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' />
@@ -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,7 +5,6 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { hash } from 'rsvp';
export default class ScopesScopeAuthenticateRoute extends Route {
// =services
@@ -13,6 +12,7 @@ export default class ScopesScopeAuthenticateRoute extends Route {
@service session;
@service router;
@service resourceFilterStore;
// =methods
beforeModel() {
@@ -27,16 +27,7 @@ export default class ScopesScopeAuthenticateRoute extends Route {
*/
async model() {
const { id: scope_id } = this.modelFor('scopes.scope');
// Fetch auth methods for the current scope
const authMethods = await this.resourceFilterStore.queryBy(
'auth-method',
{
authorized_actions: [{ contains: 'authenticate' }],
},
{
scope_id,
},
);
// Preload all authenticatable auth methods into the store
const authMethodsForAllScopes = await this.resourceFilterStore.queryBy(
'auth-method',
@@ -48,22 +39,25 @@ export default class ScopesScopeAuthenticateRoute extends Route {
recursive: true,
},
);
// Fetch org scopes
// and filter out any that have no auth methods
const scopes = this.modelFor('scopes').filter(
({ id: scope_id, isOrg }) =>
isOrg &&
authMethodsForAllScopes.filter((i) => i.scopeID === scope_id).length,
const scopeIDs = new Set(
authMethodsForAllScopes.map((authMethod) => authMethod.scopeID),
);
return hash({
// Fetch org scopes and filter out any that have no auth methods
const scopes = this.modelFor('scopes').filter(({ id: scope_id }) =>
scopeIDs.has(scope_id),
);
// Filter out auth methods that are not for the current scope
const authMethods = authMethodsForAllScopes.filter(
(authMethod) => authMethod.scopeID === scope_id,
);
return {
scope: this.modelFor('scopes.scope'),
scopes,
authMethods,
// for integration testing:
// authMethods: A([{
// id: 'am_1234567890',
// type: 'password'
// }])
});
};
}
}
@@ -6,6 +6,10 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import orderBy from 'lodash/orderBy';
import { loading } from 'ember-loading';
import { confirm } from 'core/decorators/confirm';
import { action } from '@ember/object';
import { notifySuccess, notifyError } from 'core/decorators/notify';
export default class ScopesScopeSessionRecordingsRoute extends Route {
// =services
@@ -68,4 +72,19 @@ export default class ScopesScopeSessionRecordingsRoute extends Route {
};
}
}
/**
* Deletes the session recording
* @param {SessionRecording} recording
*/
@action
@loading
@confirm('resources.session-recording.questions.delete')
@notifyError(({ message }) => message, { catch: true })
@notifySuccess('notifications.delete-success')
async delete(recording) {
await recording.destroyRecord();
await this.router.replaceWith('scopes.scope.session-recordings');
this.router.refresh();
}
}
+9 -53
View File
@@ -174,33 +174,6 @@
}
}
.copyable {
white-space: nowrap;
.copyable-button {
margin: 0;
padding: 0 sizing.rems(xxs);
position: relative;
top: -2px;
}
mark {
animation: fade-background 0.75s linear;
background-color: transparent;
color: inherit;
@keyframes fade-background {
0% {
background-color: var(--action-subtler-1);
}
100% {
background-color: transparent;
}
}
}
}
[class*='session-status-'] {
color: var(--ui-gray-subtler-2);
}
@@ -284,29 +257,7 @@
}
.create-resources-item-controller-copyable {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
border: sizing.rems(xxxxs) solid var(--ui-gray-subtler-2);
border-radius: sizing.rems(xxxs);
color: var(--action);
height: (sizing.rems(xs) * 5);
margin: sizing.rems(xxs) 0 sizing.rems(l) 0;
.copyable {
display: flex;
justify-content: space-between;
padding: sizing.rems(s);
span {
display: flex;
}
}
.copyable-button {
top: 0; // This is to override a negative top declared above
}
}
.image-container > svg {
@@ -337,16 +288,21 @@
margin-bottom: sizing.rems(l);
}
> code {
background-color: var(--ui-gray-subtler-5);
border: sizing.rems(xxxxs) solid var(--ui-gray-subtler-2);
color: var(--failure);
> p code {
background-color: var(--token-color-surface-strong);
border-radius: 5px;
color: var(--token-color-foreground-primary);
padding: sizing.rems(xxxs) sizing.rems(xxs);
}
.worker-auth-token {
align-items: flex-end;
display: flex;
gap: sizing.rems(m);
[class*='hds-form-field--layout'] {
margin-bottom: 0;
}
}
.worker-success {
@@ -10,13 +10,7 @@
<Rose::Notification @style='error' @heading={{t 'auth.titles.flow-error'}}>
{{t 'auth.descriptions.flow-error'}}
<br />
<Copyable
@text={{@model}}
@buttonText={{t 'actions.copy-error-detail-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
{{t 'actions.copy-error-detail-to-clipboard'}}
</Copyable>
<Hds::Copy::Snippet @textToCopy={{@model}} @color='secondary' />
</Rose::Notification>
</Rose::Layout::Centered>
</main>
@@ -54,13 +54,7 @@
'onboarding.success.descriptions.controller'
}}</span>
<div class='create-resources-item-controller-copyable'>
<Copyable
@text={{this.model.clusterUrl}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{this.model.clusterUrl}}</code>
</Copyable>
<Hds::Copy::Snippet @textToCopy={{this.model.clusterUrl}} />
</div>
<Image @name='targets' />
@@ -18,13 +18,7 @@
<page.header>
<h2>{{t 'resources.account.title'}}</h2>
<p>{{t 'resources.account.messages.set-password.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' />
</page.header>
<page.navigation>
@@ -69,13 +69,10 @@
<Hds::Badge @text={{B.data.type}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -154,13 +151,10 @@
<Hds::Badge @text={{B.data.type}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -51,13 +51,10 @@
<B.Td>{{B.data.description}}</B.Td>
<B.Td><Hds::Badge @text={{B.data.type}} /></B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -91,13 +88,10 @@
<B.Td>{{B.data.description}}</B.Td>
<B.Td><Hds::Badge @text={{B.data.type}} /></B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{truncate-list 'actions.more' B.data.group_names 3}}
@@ -61,13 +61,10 @@
<B.Td>{{B.data.full_name}}</B.Td>
<B.Td><Hds::Badge @text={{B.data.type}} /></B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -146,13 +146,10 @@
/>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{#if B.data.isPrimary}}
@@ -61,6 +61,19 @@
{{#if @model.authMethods}}
{{outlet}}
{{/if}}
{{#unless @model.authMethods}}
<Rose::Layout::Centered>
<Rose::Message
@title={{t 'resources.auth-method.messages.none.title'}}
@icon='flight-icons/svg/alert-circle-16'
as |message|
>
<message.description>
{{t 'resources.auth-method.messages.none.description'}}
</message.description>
</Rose::Message>
</Rose::Layout::Centered>
{{/unless}}
</:body>
</Rose::Frame>
</page.body>
@@ -15,13 +15,7 @@
<DocLink @doc='credential-library' @iconSize='large' />
</h2>
<p>{{t 'resources.credential-library.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' />
</page.header>
<page.navigation>
@@ -15,13 +15,7 @@
<DocLink @doc='credential' @iconSize='large' />
</h2>
<p>{{t 'resources.credential.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' />
</page.header>
<page.navigation>
+2 -8
View File
@@ -41,13 +41,7 @@
</h2>
<p>{{t 'resources.project.description'}}</p>
{{/if}}
<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' />
</page.header>
{{#if (can 'read model' @model)}}
@@ -178,7 +172,7 @@
/>
<dd.Separator />
<dd.Interactive
@text={{t 'resources.policy.actions.delete'}}
@text={{t 'resources.policy.actions.detach'}}
@color='critical'
{{on
'click'
@@ -54,13 +54,10 @@
</span>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
<ScopeBadge @scope={{B.data.scopeModel}} />
@@ -52,13 +52,10 @@
<p>{{B.data.description}}</p>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -52,13 +52,10 @@
<HostCatalogTypeBadge @model={{B.data}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<Hds::Text::Code>{{B.data.id}}</Hds::Text::Code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
<Hds::Text::Code>{{B.data.address}}</Hds::Text::Code>
@@ -54,13 +54,10 @@
<p>{{B.data.description}}</p>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -21,13 +21,7 @@
<DocLink @doc='role' @iconSize='large' />
</h2>
<p>{{t 'resources.role.grant.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' />
</page.header>
<page.actions>
@@ -21,13 +21,7 @@
<DocLink @doc='role' @iconSize='large' />
</h2>
<p>{{t 'resources.role.principal.description'}}</p>
<Copyable
@text={{@model.role.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{@model.role.id}}</code>
</Copyable>
<Hds::Copy::Snippet @textToCopy={{@model.role.id}} @color='secondary' />
</page.header>
<page.actions>
@@ -65,13 +59,10 @@
{{/if}}
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
<PrincipalTypeBadge @model={{B.data}} />
@@ -26,13 +26,10 @@
@model.channelRecording
}}
</h2>
<Copyable
@text={{@model.channelRecording.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{@model.channelRecording.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{@model.channelRecording.id}}
@color='secondary'
/>
</page.header>
<page.body>
@@ -142,13 +139,10 @@
@color='boundary'
@text={{t 'resources.session-recording.title'}}
>
<Copyable
@text={{@model.sessionRecording.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{@model.sessionRecording.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{@model.sessionRecording.id}}
@color='secondary'
/>
</list.Item>
{{! Connection Recording ID }}
<list.Item
@@ -156,13 +150,10 @@
@color='boundary'
@text={{t 'resources.session-recording.connection.title'}}
>
<Copyable
@text={{@model.channelRecording.connection_recording.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{@model.channelRecording.connection_recording.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{@model.channelRecording.connection_recording.id}}
@color='secondary'
/>
</list.Item>
</LinkListPanel>
</div>
@@ -16,8 +16,12 @@
{{#if
(can 'reapplyStoragePolicy session-recording' @model.sessionRecording)
}}
<Hds::Dropdown data-test-manage-dropdown as |dd|>
<dd.ToggleButton @text={{t 'actions.manage'}} @color='secondary' />
<Hds::Dropdown as |dd|>
<dd.ToggleButton
data-test-manage-dropdown
@text={{t 'actions.manage'}}
@color='secondary'
/>
<dd.Interactive
@text={{t 'resources.policy.actions.update'}}
@@ -26,6 +30,15 @@
(route-action 'reapplyStoragepolicy' @model.sessionRecording)
}}
/>
{{#if (can 'delete session-recording' @model.sessionRecording)}}
<dd.Separator />
<dd.Interactive
data-test-manage-dropdown-delete
@color='critical'
@text={{t 'resources.policy.actions.delete_recording'}}
{{on 'click' (route-action 'delete' @model.sessionRecording)}}
/>
{{/if}}
</Hds::Dropdown>
{{/if}}
</page.actions>
@@ -75,13 +88,10 @@
connection
}}
</p>
<Copyable
@text={{connection.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{connection.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{connection.id}}
@color='secondary'
/>
</div>
{{#if connection.channel_recordings}}
<Hds::Table
@@ -143,13 +153,10 @@
</Rose::MetadataList>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td align='right'>
{{#if (can 'play channel-recording' B.data)}}
@@ -337,13 +344,10 @@
@color='boundary'
@text={{t 'resources.session-recording.title'}}
>
<Copyable
@text={{@model.sessionRecording.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{@model.sessionRecording.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{@model.sessionRecording.id}}
@color='secondary'
/>
</list.Item>
</LinkListPanel>
</div>
@@ -90,13 +90,10 @@
@name='flight-icons/svg/entry-point-16'
@size='medium'
/>
<Copyable
@text={{B.data.session.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<Hds::Text::Code>{{B.data.session.id}}</Hds::Text::Code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.session.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
<Hds::Text::Code>{{B.data.user.id}}</Hds::Text::Code>
@@ -58,13 +58,10 @@
{{/if}}
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{#if B.data.isAWS}}
@@ -13,13 +13,7 @@
{{t 'resources.storage-bucket.title'}}
<DocLink @doc='storage-bucket' @iconSize='large' />
</h2>
<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' />
</page.header>
<page.navigation>
@@ -66,13 +66,10 @@
{{/if}}
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
{{else}}
@@ -99,13 +96,10 @@
{{/if}}
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
{{/if}}
@@ -69,13 +69,10 @@
<CredSourceTypeBadge @model={{B.data}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{#if (can 'removeCredentialSources target' @model)}}
@@ -59,13 +59,10 @@
<HostCatalogTypeBadge @model={{B.data.model}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.model.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.model.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.model.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{#if (can 'removeHostSources target' @model)}}
@@ -73,13 +73,10 @@
<CredSourceTypeBadge @model={{B.data}} />
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
{{#if (can 'removeCredentialSources target' @model)}}
@@ -57,13 +57,10 @@
<p>{{B.data.description}}</p>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -60,13 +60,10 @@
/>
</B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
<B.Td>
@@ -136,13 +136,10 @@
<B.Td>{{B.data.release_version}}</B.Td>
<B.Td>{{B.data.address}} </B.Td>
<B.Td>
<Copyable
@text={{B.data.id}}
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
<code>{{B.data.id}}</code>
</Copyable>
<Hds::Copy::Snippet
@textToCopy={{B.data.id}}
@color='secondary'
/>
</B.Td>
</B.Tr>
</:body>
@@ -15,13 +15,7 @@
<DocLink @doc='worker' @iconSize='large' />
</h2>
<p>{{t 'resources.worker.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' />
</page.header>
<page.navigation>
-7
View File
@@ -39,13 +39,6 @@ module.exports = function (defaults) {
},
});
// Only import when in development or test mode
if (app.env.match(/(development)|(test)/i)) {
app.import('node_modules/clipboard/dist/clipboard.js');
} else {
app.import('node_modules/clipboard/dist/clipboard.min.js');
}
// Use `app.import` to add additional libraries to the generated
// output files.
//
-1
View File
@@ -63,7 +63,6 @@
"@playwright/test": "^1.30.0",
"babel-loader": "^8.2.5",
"broccoli-asset-rev": "^3.0.0",
"clipboard": "^2.0.8",
"concurrently": "^8.0.1",
"core": "*",
"doctoc": "^2.2.0",
@@ -118,7 +118,7 @@ module('Acceptance | auth-methods | create', function (hooks) {
await fillIn('[name="client_id"]', 'client_id');
await fillIn('[name="client_secret"]', 'client_secret');
await select('form fieldset:nth-of-type(1) select', 'RS384');
await click('form fieldset:nth-of-type(1) [title="Add"]');
await click('[data-test-add-option-button]');
await fillIn(ALLOWED_AUDIENCES_INPUT_SELECTOR, 'allowed_audiences');
await click(ALLOWED_AUDIENCES_BTN_SELECTOR, 'allowed_audiences');
await fillIn(CLAIMS_SCOPES_INPUT_SELECTOR, 'claims_scopes');
@@ -53,6 +53,12 @@ module('Acceptance | auth-methods | update', function (hooks) {
const CLAIMS_SCOPES_INPUT_SELECTOR = '[name="claims_scopes"] input';
const TOGGLE_SELECTOR = '[name="prompts"]';
const SIGNING_ALGORITHMS_REMOVE_BTN_SELECTOR =
'[data-test-remove-option-button]';
const SIGNING_ALGORITHMS_INPUT_SELECTOR =
'.list-wrapper-field tbody tr:last-child select';
const SIGNING_ALGORITHMS_ADD_BTN_SELECTOR = '[data-test-add-option-button]';
const instances = {
scopes: {
global: null,
@@ -123,14 +129,16 @@ module('Acceptance | auth-methods | update', function (hooks) {
await fillIn('[name="issuer"]', 'issuer');
await fillIn('[name="client_id"]', 'client_id');
await fillIn('[name="client_secret"]', 'client_secret');
// Remove all signing algorithms
await Promise.all(
findAll('form fieldset:nth-of-type(1) [title="Remove"]').map((element) =>
click(element),
),
);
await select('form fieldset:nth-of-type(1) select', 'RS384');
await click('form fieldset:nth-of-type(1) [title="Add"]');
let removeButtons = findAll(SIGNING_ALGORITHMS_REMOVE_BTN_SELECTOR);
for (const element of removeButtons) {
await click(element);
}
await select(SIGNING_ALGORITHMS_INPUT_SELECTOR, 'RS384');
await click(SIGNING_ALGORITHMS_ADD_BTN_SELECTOR);
// Remove all allowed audiences
const allowedAudiencesList = findAll(ALLOWED_AUDIENCES_REMOVE_BTN_SELECTOR);
@@ -347,8 +355,9 @@ module('Acceptance | auth-methods | update', function (hooks) {
await fillIn(NAME_INPUT_SELECTOR, 'existing auth method');
await click(SAVE_BTN_SELECTOR);
await a11yAudit();
assert.dom(ERROR_MSG_SELECTOR).hasText('The request was invalid.');
assert.dom('.rose-form-error-message').hasText('Name is required.');
assert.dom('.hds-form-error__message').hasText('Name is required.');
});
test('saving an existing ldap auth method with invalid fields displays error messages', async function (assert) {
@@ -76,6 +76,15 @@ module('Acceptance | authentication', function (hooks) {
},
'withChildren',
);
// create an emtpy org with no auth methods
this.server.create(
'scope',
{
type: 'org',
scope: { id: globalScope.id, type: globalScope.type },
},
'withChildren',
);
scope = { id: orgScope.id, type: orgScope.type };
globalAuthMethod = this.server.create('auth-method', {
scope: globalScope,
@@ -366,4 +375,12 @@ module('Acceptance | authentication', function (hooks) {
});
// TODO: test OIDC retry and cancel
test('org scopes with no auth methods are not visible in dropdown', async function (assert) {
await visit(authMethodGlobalAuthenticateURL);
await click('.rose-dropdown-trigger');
assert.dom('.rose-dropdown-content a').exists({ count: 2 });
});
});
@@ -88,12 +88,34 @@ module('Acceptance | credential-libraries | create', function (hooks) {
assert.strictEqual(currentURL(), urls.credentialLibrary);
});
test('can create a credential library', async function (assert) {
test('can create a new credential library of type vault generic', async function (assert) {
const count = getCredentialLibraryCount();
await visit(urls.newCredentialLibrary);
await fillIn('[name="name"]', 'random string');
await select('[name="credential_type"]', 'ssh_private_key');
await select(
'[name="credential_mapping_overrides"] tbody td:nth-of-type(1) select',
'private_key_attribute',
);
await fillIn(
'[name="credential_mapping_overrides"] tbody td:nth-of-type(2) input',
'key',
);
await click('[name="credential_mapping_overrides"] button');
await click('[type="submit"]');
assert.strictEqual(getCredentialLibraryCount(), count + 1);
const credentialLibrary = this.server.schema.credentialLibraries.findBy({
name: 'random string',
});
assert.strictEqual(credentialLibrary.name, 'random string');
assert.strictEqual(credentialLibrary.credentialType, 'ssh_private_key');
assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
private_key_attribute: 'key',
});
});
test('can create a new credential library of type vault ssh cert', async function (assert) {
@@ -22,6 +22,17 @@ module('Acceptance | credential-libraries | update', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
const BUTTON_SELECTOR = '.rose-form-actions [type="button"]';
const SAVE_BTN_SELECTOR = '.rose-form-actions [type="submit"]';
const NAME_INPUT_SELECTOR = '[name="name"]';
const FIELD_ERROR_TEXT_SELECTOR = '.hds-form-error__message';
const DESC_INPUT_SELECTOR = '[name="description"]';
const VAULT_PATH_SELECTOR = '[name="vault_path"]';
const CRED_TYPE_SELECTOR = '[name="credential_type"]';
const CRED_MAPPING_OVERRIDES_SELECT =
'[name="credential_mapping_overrides"] tbody td:nth-of-type(1) select';
const CRED_MAPPING_OVERRIDES_INPUT =
'[name="credential_mapping_overrides"] tbody td:nth-of-type(2) input';
const instances = {
scopes: {
global: null,
@@ -73,43 +84,58 @@ module('Acceptance | credential-libraries | update', function (hooks) {
authenticateSession({});
});
test('can update resource and save changes', async function (assert) {
assert.notEqual(instances.credentialLibrary.name, 'random string');
await visit(urls.credentialLibrary);
await click('form [type="button"]', 'Activate edit mode');
await fillIn('[name="name"]', 'random string');
await click('.rose-form-actions [type="submit"]');
assert.strictEqual(currentURL(), urls.credentialLibrary);
assert.strictEqual(
this.server.schema.credentialLibraries.all().models[0].name,
'random string',
);
});
test('cannot update resource without proper authorization', async function (assert) {
instances.credentialLibrary.authorized_actions =
instances.credentialLibrary.authorized_actions.filter(
(item) => item !== 'update',
);
await visit(urls.credentialLibrary);
assert.notOk(find('form [type="button"]'));
assert.notOk(find(BUTTON_SELECTOR));
});
test('can update a credential library and cancel changes', async function (assert) {
await visit(urls.credentialLibrary);
await click('form [type="button"]', 'Activate edit mode');
await fillIn('[name="name"]', 'random string');
await click('.rose-form-actions [type="button"]');
await click(BUTTON_SELECTOR, 'Activate edit mode');
await fillIn(NAME_INPUT_SELECTOR, 'random string');
await click(BUTTON_SELECTOR);
assert.notEqual(
this.server.schema.credentialLibraries.all().models[0].name,
'random string',
);
assert.strictEqual(
find('[name="name"]').value,
find(NAME_INPUT_SELECTOR).value,
instances.credentialLibrary.name,
);
});
test('can update a vault generic credential library and save changes', async function (assert) {
await visit(
`${urls.credentialLibraries}/${instances.credentialLibrary.id}`,
);
await click(BUTTON_SELECTOR);
await fillIn(NAME_INPUT_SELECTOR, 'random string');
await fillIn(DESC_INPUT_SELECTOR, 'description');
await fillIn(VAULT_PATH_SELECTOR, 'path');
await select(CRED_MAPPING_OVERRIDES_SELECT, 'private_key_attribute');
await fillIn(CRED_MAPPING_OVERRIDES_INPUT, 'key');
await click('[name="credential_mapping_overrides"] button');
await click(SAVE_BTN_SELECTOR);
const credentialLibrary = this.server.schema.credentialLibraries.findBy({
name: 'random string',
});
assert.strictEqual(credentialLibrary.name, 'random string');
assert.strictEqual(credentialLibrary.description, 'description');
assert.strictEqual(credentialLibrary.attributes.path, 'path');
assert.deepEqual(credentialLibrary.credentialMappingOverrides, {
private_key_attribute: 'key',
});
});
test('saving an existing credential library with invalid fields displays error messages', async function (assert) {
this.server.patch('/credential-libraries/:id', () => {
return new Response(
@@ -131,15 +157,15 @@ module('Acceptance | credential-libraries | update', function (hooks) {
);
});
await visit(urls.credentialLibrary);
await click('form [type="button"]', 'Activate edit mode');
await fillIn('[name="name"]', 'random string');
await click('[type="submit"]');
await click(BUTTON_SELECTOR, 'Activate edit mode');
await fillIn(NAME_INPUT_SELECTOR, 'random string');
await click(SAVE_BTN_SELECTOR);
assert.ok(
find('[role="alert"]').textContent.trim(),
'The request was invalid.',
);
assert.ok(
find('.hds-form-error__message').textContent.trim(),
find(FIELD_ERROR_TEXT_SELECTOR).textContent.trim(),
'Name is required.',
);
});
@@ -151,8 +177,8 @@ module('Acceptance | credential-libraries | update', function (hooks) {
assert.notEqual(instances.credentialLibrary.name, 'random string');
await visit(urls.credentialLibrary);
await click('form [type="button"]', 'Activate edit mode');
await fillIn('[name="name"]', 'random string');
await click(BUTTON_SELECTOR, 'Activate edit mode');
await fillIn(NAME_INPUT_SELECTOR, 'random string');
assert.strictEqual(currentURL(), urls.credentialLibrary);
try {
@@ -174,8 +200,8 @@ module('Acceptance | credential-libraries | update', function (hooks) {
confirmService.enabled = true;
assert.notEqual(instances.credentialLibrary.name, 'random string');
await visit(urls.credentialLibrary);
await click('form [type="button"]', 'Activate edit mode');
await fillIn('[name="name"]', 'random string');
await click(BUTTON_SELECTOR, 'Activate edit mode');
await fillIn(NAME_INPUT_SELECTOR, 'random string');
assert.strictEqual(currentURL(), urls.credentialLibrary);
try {
@@ -191,6 +217,12 @@ module('Acceptance | credential-libraries | update', function (hooks) {
}
});
test('cannot update credential type in a vault generic credential library', async function (assert) {
await visit(urls.credentialLibrary);
await click(BUTTON_SELECTOR, 'Activate edit mode');
assert.dom(CRED_TYPE_SELECTOR).isDisabled();
});
test('can update a vault ssh cert credential library and save changes', async function (assert) {
instances.credentialLibrary = this.server.create('credential-library', {
scope: instances.scopes.project,
@@ -200,10 +232,10 @@ module('Acceptance | credential-libraries | update', function (hooks) {
await visit(
`${urls.credentialLibraries}/${instances.credentialLibrary.id}`,
);
await click('form [type="button"]:not(:disabled)', 'Activate edit mode');
await fillIn('[name="name"]', 'name');
await fillIn('[name="description"]', 'description');
await fillIn('[name="vault_path"]', 'path');
await click(BUTTON_SELECTOR, 'Activate edit mode');
await fillIn(NAME_INPUT_SELECTOR, 'name');
await fillIn(DESC_INPUT_SELECTOR, 'description');
await fillIn(VAULT_PATH_SELECTOR, 'path');
await fillIn('[name="username"]', 'username');
await select('[name="key_type"]', 'rsa');
await fillIn('[name="key_bits"]', 100);
@@ -226,8 +258,10 @@ module('Acceptance | credential-libraries | update', function (hooks) {
'[name="extensions"] tbody td:nth-of-type(2) input',
'ext_value',
);
await click('[name="extensions"] button');
await click('[type="submit"]');
await click(SAVE_BTN_SELECTOR);
const credentialLibrary = this.server.schema.credentialLibraries.findBy({
type: TYPE_CREDENTIAL_LIBRARY_VAULT_SSH_CERTIFICATE,
});
@@ -134,7 +134,7 @@ module('Acceptance | credential-stores | create', function (hooks) {
'The request was invalid.',
);
assert.ok(
find('.rose-form-error-message').textContent.trim(),
find('[data-test-error-message-name]').textContent.trim(),
'Name is required.',
);
});
@@ -235,7 +235,7 @@ module(
.dom('.rose-notification-body')
.hasText('Error in provided request.');
assert
.dom('.rose-form-error-message')
.dom('[data-test-error-message-password]')
.hasText('Field required for creating a username-password credential.');
});
@@ -270,7 +270,7 @@ module(
.dom('.rose-notification-body')
.hasText('Error in provided request.');
assert
.dom('.hds-form-error__message')
.dom('[data-test-error-message-private-key]')
.hasText('Field required for creating a username-key-pair credential.');
});
Loaded 100 of 151 files, more files were not shown because too many files have changed in this diff. Show more