Merge main into session recording (#219)
* fix: 🐛 add model hook to host route for dynamic host catalogs (#1659) * fix: 🐛 add model hook to host route for dynamic host catalogs ✅ Closes: ICU-8594 * refactor: 💡 remove page formatting for host route * [COMPLIANCE] Add Copyright and License Headers (#1660) Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com> * chore(deps-dev): bump webpack from 5.59.1 to 5.76.0 (#1654) Bumps [webpack](https://github.com/webpack/webpack) from 5.59.1 to 5.76.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.59.1...v5.76.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Randall Morey <randall@randallmorey.com> Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com> * Feature metadata (#1661) * feat: 🎸 load edition from controller-metadata.json * refactor: 💡 rename edition and add licensed features support * chore: 🤖 support dev toggling of licensed features * chore: 🤖 rename ent edition * Update ui/admin/app/services/feature-edition.js * Update ui/admin/app/instance-initializers/feature-edition.js Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> * chore: 🤖 cleanup * chore: 🤖 feature edition disabled in tests / fix test cases * test: 💍 remove feature disable calls in tests * test: 💍 fix broken tests * fix: 🐛 fix config bug * fix: 🐛 fix broken test due to feature flags --------- Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> * fix: 🐛 Fix missing translation (#1662) Fix missing translation on the toggle color theme selector * Resolutions audit: Delete 3 oldest resolutions (#1663) * Delete bl from resolutions * Delete tough-cookie from resolutions * Delete npm from resolutions * chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#1665) Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/kornelski/http-cache-semantics/releases) - [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: http-cache-semantics dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: 🤖 Update electron-forge/* packages (#1666) Update electron-forge/* packages * feat: 🎸 Add support to display external name for dynamic hosts (#1664) * feat: 🎸 Add support to display external name for dynamic hosts ✅ Closes: ICU-8795 * test(admin/e2e): Add create target with address test (#1667) * chore: 🤖 update design system package (#1668) * test(admin/e2e): Define expected private key for vault credential store test (#1671) * test: 💍 (admin-e2e): Add test to create different credentials (#1670) * chore: 🤖 add json5 to resolutions per dependabot alerts (#1672) * chore: 🤖 add json5 to resolutions per dependabot alerts * fix: 🐛 remove unecessary resolutions * chore: 🤖 upgrade @storybook/ember-cli-storybook to 0.6.0 (#1669) * chore: 🤖 update @storybook/ember-cli-storybook to 0.6.0 ✅ Closes: ICU-6588 * chore: 🤖 remove css-what from resolutions * refactor: 💡 update selector for delete storage bucket test * chore: 🤖 fix yarn.lock --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: lisbet-alvarez <107949262+lisbet-alvarez@users.noreply.github.com> Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Carlos Alcaide Corvo <ccorvo@hashicorp.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Randall Morey <randall@randallmorey.com> Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> Co-authored-by: github-team-secure-boundary <hc-github-team-secure-boundary@hashicorp.com> Co-authored-by: hc-github-team-secure-boundary <82989682+hc-github-team-secure-boundary@users.noreply.github.com> Co-authored-by: Stan Ryzhov <60649800+stasryzhov@users.noreply.github.com> Co-authored-by: Dharini Jeeva <dharini@hashicorp.com>
This commit is contained in:
20 files changed
+951
-1604
No files matched your search
@@ -29,6 +29,12 @@ export default class HostModel extends GeneratedHostModel {
|
||||
})
|
||||
external_id;
|
||||
|
||||
@attr('string', {
|
||||
description: 'The external facing name for the plugin based host.',
|
||||
readOnly: true,
|
||||
})
|
||||
external_name;
|
||||
|
||||
// Aws specific
|
||||
@attr({
|
||||
readOnly: true,
|
||||
@@ -89,4 +95,9 @@ export default class HostModel extends GeneratedHostModel {
|
||||
this.plugin = { name: type };
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin hosts can support an external name
|
||||
get displayName() {
|
||||
return this.name || this.external_name || this.id;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,9 @@ import generateId from '../helpers/id';
|
||||
|
||||
export default factory.extend({
|
||||
id: () => generateId('h_'),
|
||||
|
||||
name() {
|
||||
if (this.type === 'static') return faker.random.words();
|
||||
},
|
||||
type() {
|
||||
return this.hostCatalog?.type || factory.attrs.type;
|
||||
},
|
||||
@@ -34,8 +36,16 @@ export default factory.extend({
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// Return external fields only for plugins
|
||||
external_id() {
|
||||
return faker.datatype.uuid();
|
||||
if (this.type === 'plugin') {
|
||||
return faker.datatype.uuid();
|
||||
}
|
||||
},
|
||||
external_name(i) {
|
||||
if (this.type === 'plugin') {
|
||||
return `${this.plugin.name} provided name ${i}`;
|
||||
}
|
||||
},
|
||||
// Only aws plugins have dns_names
|
||||
dns_names() {
|
||||
|
||||
@@ -11,7 +11,6 @@ import { faker } from '@faker-js/faker';
|
||||
*/
|
||||
export default Factory.extend({
|
||||
type: 'static',
|
||||
name: () => faker.random.words(),
|
||||
description: () => faker.random.words(),
|
||||
created_time: () => faker.date.recent(),
|
||||
updated_time: () => faker.date.recent(),
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
|
||||
id:
|
||||
label: ID
|
||||
external_id:
|
||||
label: External ID
|
||||
help: A read-only ID given by the plugin host catalog provider
|
||||
name:
|
||||
label: Name
|
||||
help: Name for identification purposes
|
||||
external_name:
|
||||
label: External Name
|
||||
help: A read-only name given by the plugin host catalog provider
|
||||
description:
|
||||
label: Description
|
||||
help: Description for identification purposes
|
||||
@@ -153,10 +159,12 @@ disable_credential_rotation:
|
||||
help: Azure host catalogs do not yet support credential rotation.
|
||||
dns_names:
|
||||
label: Latest DNS Names
|
||||
help: Read-only DNS names given by the plugin host catalog provider
|
||||
host:
|
||||
label: Host
|
||||
ip_addresses:
|
||||
label: Latest IP Addresses
|
||||
help: Read-only public and private IP addresses given by the plugin host catalog provider
|
||||
sync-interval:
|
||||
label: Sync Interval
|
||||
help: Optional. Number of seconds between the time Boundary syncs hosts in this set.
|
||||
|
||||
@@ -149,6 +149,7 @@ host-set:
|
||||
host:
|
||||
title: Host
|
||||
title_plural: Hosts
|
||||
no_name_title: Unnamed Host
|
||||
description: A host is a resource that may be accessed by a Boundary target.
|
||||
messages:
|
||||
welcome:
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@embroider/test-setup": "^0.48.1",
|
||||
"@hashicorp/design-system-components": "^1.5.1",
|
||||
"@hashicorp/design-system-components": "^2.1.0",
|
||||
"codemirror": "5.65.7",
|
||||
"ember-auto-import": "^2.4.2",
|
||||
"ember-cli-babel": "^7.26.10",
|
||||
@@ -67,7 +67,7 @@
|
||||
"@storybook/components": "^6.3.12",
|
||||
"@storybook/core-events": "^6.3.0",
|
||||
"@storybook/ember": "^6.3.8",
|
||||
"@storybook/ember-cli-storybook": "^0.5.0",
|
||||
"@storybook/ember-cli-storybook": "^0.6.0",
|
||||
"@storybook/theming": "^6.3.0",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-plugin-ember-modules-api-polyfill": "^2.12.0",
|
||||
|
||||
+2
-5
@@ -49,9 +49,6 @@
|
||||
"lint-staged": "^13.0.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"bl": "~1.2.3",
|
||||
"tough-cookie": "~2.3.3",
|
||||
"npm": "~6.14.6",
|
||||
"npm-registry-fetch": "~8.1.1",
|
||||
"request": "^2.88.0",
|
||||
"tunnel-agent": "~0.6.0",
|
||||
@@ -72,7 +69,6 @@
|
||||
"trim": "~1.0.1",
|
||||
"browserslist": "^4.16.5",
|
||||
"ws": "^7.4.6",
|
||||
"css-what": "^5.0.1",
|
||||
"trim-newlines": "^3.0.1",
|
||||
"clean-css": "^4.1.11",
|
||||
"mem": "^4.0.0",
|
||||
@@ -106,7 +102,8 @@
|
||||
"got": "^11.8.5",
|
||||
"loader-utils": "^2.0.4",
|
||||
"**/@storybook/**/minimatch": "^3.0.5",
|
||||
"**/ember-electron/**/minimatch": "^3.0.5"
|
||||
"**/ember-electron/**/minimatch": "^3.0.5",
|
||||
"**/babel-core/json5": "^2.2.2"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
||||
@@ -11,51 +11,70 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
name='type'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
{{#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>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.textarea
|
||||
@name='description'
|
||||
@type='description'
|
||||
{{#if @model.external_name}}
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.external_name}}
|
||||
@isInvalid={{@model.errors.external_name}}
|
||||
name='external_name'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.external_name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.external_name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.external_name}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.external_name as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.external_id}}
|
||||
@isInvalid={{@model.errors.external_id}}
|
||||
name='external_id'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.external_id.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.external_id.help'}}</F.HelperText>
|
||||
{{#if @model.errors.external_id}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.external_id as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@value={{@model.description}}
|
||||
@label={{t 'form.description.label'}}
|
||||
@error={{@model.errors.description}}
|
||||
@helperText={{t 'form.description.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.description.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.description.help'}}</F.HelperText>
|
||||
{{#if @model.errors.description}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.description as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.textarea>
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<InfoField
|
||||
@value={{t 'descriptions.provider'}}
|
||||
@@ -69,27 +88,33 @@
|
||||
</F.HelperText>
|
||||
</InfoField>
|
||||
|
||||
<form.fieldset>
|
||||
<:title>{{t 'form.ip_addresses.label'}}</:title>
|
||||
<:body>
|
||||
{{#each @model.ip_addresses as |ip_address|}}
|
||||
<form.input
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<F.Legend>{{t 'form.ip_addresses.label'}}</F.Legend>
|
||||
<F.HelperText>{{t 'form.ip_addresses.help'}} </F.HelperText>
|
||||
{{#each @model.ip_addresses as |ip_address|}}
|
||||
<F.Control>
|
||||
<Hds::Form::TextInput::Base
|
||||
@value={{ip_address}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
disabled={{true}}
|
||||
@width='unset'
|
||||
/>
|
||||
{{/each}}
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
</F.Control>
|
||||
{{/each}}
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
<form.fieldset>
|
||||
<:title>{{t 'form.dns_names.label'}}</:title>
|
||||
<:body>
|
||||
{{#each @model.dns_names as |dns_name|}}
|
||||
<form.input @value={{dns_name}} readonly={{true}} @disabled={{true}} />
|
||||
{{/each}}
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<F.Legend>{{t 'form.dns_names.label'}}</F.Legend>
|
||||
<F.HelperText>{{t 'form.dns_names.help'}} </F.HelperText>
|
||||
{{#each @model.dns_names as |dns_name|}}
|
||||
<F.Control>
|
||||
<Hds::Form::TextInput::Base
|
||||
@value={{dns_name}}
|
||||
disabled={{true}}
|
||||
@width='unset'
|
||||
/>
|
||||
</F.Control>
|
||||
{{/each}}
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
|
||||
@@ -11,51 +11,70 @@
|
||||
as |form|
|
||||
>
|
||||
|
||||
<form.input
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.type}}
|
||||
@label={{t 'form.type.label'}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
/>
|
||||
|
||||
<form.input
|
||||
@name='name'
|
||||
@type='name'
|
||||
@value={{@model.name}}
|
||||
@label={{t 'form.name.label'}}
|
||||
@error={{@model.errors.name}}
|
||||
@helperText={{t 'form.name.help'}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
name='type'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
{{#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>
|
||||
<F.Label>{{t 'form.type.label'}}</F.Label>
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<form.textarea
|
||||
@name='description'
|
||||
@type='description'
|
||||
{{#if @model.external_name}}
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.external_name}}
|
||||
@isInvalid={{@model.errors.external_name}}
|
||||
name='external_name'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.external_name.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.external_name.help'}}</F.HelperText>
|
||||
{{#if @model.errors.external_name}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.external_name as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
{{/if}}
|
||||
|
||||
<Hds::Form::TextInput::Field
|
||||
@value={{@model.external_id}}
|
||||
@isInvalid={{@model.errors.external_id}}
|
||||
name='external_id'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.external_id.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.external_id.help'}}</F.HelperText>
|
||||
{{#if @model.errors.external_id}}
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.external_id as |error|}}
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</Hds::Form::TextInput::Field>
|
||||
|
||||
<Hds::Form::Textarea::Field
|
||||
@value={{@model.description}}
|
||||
@label={{t 'form.description.label'}}
|
||||
@error={{@model.errors.description}}
|
||||
@helperText={{t 'form.description.help'}}
|
||||
disabled={{@model.isSaving}}
|
||||
readonly={{false}}
|
||||
as |field|
|
||||
@isInvalid={{@model.errors.description}}
|
||||
name='description'
|
||||
disabled={{true}}
|
||||
as |F|
|
||||
>
|
||||
<F.Label>{{t 'form.description.label'}}</F.Label>
|
||||
<F.HelperText>{{t 'form.description.help'}}</F.HelperText>
|
||||
{{#if @model.errors.description}}
|
||||
<field.errors as |errors|>
|
||||
<F.Error as |E|>
|
||||
{{#each @model.errors.description as |error|}}
|
||||
<errors.message>{{error.message}}</errors.message>
|
||||
<E.Message>{{error.message}}</E.Message>
|
||||
{{/each}}
|
||||
</field.errors>
|
||||
</F.Error>
|
||||
{{/if}}
|
||||
</form.textarea>
|
||||
</Hds::Form::Textarea::Field>
|
||||
|
||||
<InfoField
|
||||
@value={{t 'descriptions.provider'}}
|
||||
@@ -68,19 +87,20 @@
|
||||
{{t 'resources.host-catalog.types.azure'}}
|
||||
</F.HelperText>
|
||||
</InfoField>
|
||||
<form.fieldset>
|
||||
<:title>{{t 'form.ip_addresses.label'}}</:title>
|
||||
<:body>
|
||||
{{#each @model.ip_addresses as |ip_address|}}
|
||||
|
||||
<form.input
|
||||
<Hds::Form::Fieldset as |F|>
|
||||
<F.Legend>{{t 'form.ip_addresses.label'}}</F.Legend>
|
||||
<F.HelperText>{{t 'form.ip_addresses.help'}} </F.HelperText>
|
||||
{{#each @model.ip_addresses as |ip_address|}}
|
||||
<F.Control>
|
||||
<Hds::Form::TextInput::Base
|
||||
@value={{ip_address}}
|
||||
readonly={{true}}
|
||||
@disabled={{true}}
|
||||
disabled={{true}}
|
||||
@width='unset'
|
||||
/>
|
||||
{{/each}}
|
||||
</:body>
|
||||
</form.fieldset>
|
||||
</F.Control>
|
||||
{{/each}}
|
||||
</Hds::Form::Fieldset>
|
||||
|
||||
{{#if (can 'save model' @model)}}
|
||||
<form.actions
|
||||
|
||||
+6
-2
@@ -31,10 +31,14 @@
|
||||
<Rose::Table as |table|>
|
||||
<table.header as |header|>
|
||||
<header.row as |row|>
|
||||
<row.headerCell>{{t 'form.name.label'}}</row.headerCell>
|
||||
{{#if @model.hostSet.isStatic}}
|
||||
<row.headerCell>{{t 'form.name.label'}}</row.headerCell>
|
||||
{{else}}
|
||||
<row.headerCell>{{t 'form.external_name.label'}}</row.headerCell>
|
||||
{{/if}}
|
||||
<row.headerCell>{{t 'form.type.label'}}</row.headerCell>
|
||||
<row.headerCell>{{t 'form.id.label'}}</row.headerCell>
|
||||
{{#if @model.isStatic}}
|
||||
{{#if @model.hostSet.isStatic}}
|
||||
<row.headerCell>{{t 'titles.actions'}}</row.headerCell>
|
||||
{{/if}}
|
||||
</header.row>
|
||||
|
||||
@@ -19,7 +19,7 @@ module('Acceptance | storage-buckets | delete', function (hooks) {
|
||||
let getStorageBucketCount;
|
||||
|
||||
const DROPDOWN_BUTTON_SELECTOR = '.hds-dropdown-toggle-icon';
|
||||
const DELETE_DROPDOWN_SELECTOR = '.hds-dropdown-list [type="button"]';
|
||||
const DELETE_DROPDOWN_SELECTOR = '.hds-dropdown-list-item [type="button"]';
|
||||
const DIALOG_DELETE_BTN_SELECTOR = '.rose-dialog .rose-button-primary';
|
||||
const DIALOG_CANCEL_BTN_SELECTOR = '.rose-dialog .rose-button-secondary';
|
||||
const DIALOG_MESSAGE_SELECTOR = '.rose-dialog-body';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
const { execSync } = require('child_process');
|
||||
const { execSync, exec } = require('child_process');
|
||||
|
||||
/**
|
||||
* Checks that the boundary cli is available
|
||||
@@ -36,3 +36,75 @@ exports.authenticateBoundaryCli = async () => {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to connect to the specified target
|
||||
* @param {string} targetId ID of the target to be connected to
|
||||
* @returns ChildProcess representing the result of the command execution
|
||||
*/
|
||||
exports.connectToTarget = async (targetId) => {
|
||||
let connect;
|
||||
try {
|
||||
connect = exec(
|
||||
'boundary connect' +
|
||||
' -target-id=' +
|
||||
targetId +
|
||||
' -exec /usr/bin/ssh --' +
|
||||
' -l ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
' -i ' +
|
||||
process.env.E2E_SSH_KEY_PATH +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes' + // forces the use of the provided key
|
||||
' -p {{boundary.port}}' +
|
||||
' {{boundary.ip}}'
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
return connect;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to delete the specified organization
|
||||
* @param {string} orgId ID of the organization to be deleted
|
||||
*/
|
||||
exports.deleteOrg = async (orgId) => {
|
||||
try {
|
||||
exec('boundary scopes delete -id=' + orgId);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the boundary CLI to get a session created for the specified target
|
||||
* @param {string} orgName Name of the organization with the specified project
|
||||
* @param {string} projectName Name of project with the specified target
|
||||
* @param {string} targetName Name of the target that the anticipated session is created for
|
||||
* @returns An object representing an active session created for the specified target
|
||||
*/
|
||||
exports.getSessionCli = async (orgName, projectName, targetName) => {
|
||||
let session;
|
||||
try {
|
||||
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
|
||||
const org = orgs.items.filter((obj) => obj.name == orgName)[0];
|
||||
const projects = JSON.parse(
|
||||
execSync(`boundary scopes list -format json -scope-id ${org.id}`)
|
||||
);
|
||||
const project = projects.items.filter((obj) => obj.name == projectName)[0];
|
||||
const targets = JSON.parse(
|
||||
execSync(`boundary targets list -format json -scope-id ${project.id}`)
|
||||
);
|
||||
const target = targets.items.filter((obj) => obj.name == targetName)[0];
|
||||
session = JSON.parse(
|
||||
execSync(
|
||||
`boundary targets authorize-session -id ${target.id} -format json`
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`${e.stderr}`);
|
||||
}
|
||||
return session;
|
||||
};
|
||||
@@ -167,6 +167,36 @@ exports.createNewTarget = async (page) => {
|
||||
return targetName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to create a new target with address. Assumes you have selected the desired project.
|
||||
* @param {Page} page Playwright page object
|
||||
* @returns Name of the target
|
||||
*/
|
||||
exports.createNewTargetWithAddress = async (page) => {
|
||||
const targetName = 'Target ' + nanoid();
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Targets' })
|
||||
.click();
|
||||
await page.getByRole('link', { name: 'New' }).click();
|
||||
await page.getByLabel('Name').fill(targetName);
|
||||
await page.getByLabel('Description').fill('This is an automated test');
|
||||
await page.getByLabel('Target Address').fill(process.env.E2E_TARGET_IP);
|
||||
await page.getByLabel('Default Port').fill(process.env.E2E_SSH_PORT);
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await expect(
|
||||
page.getByRole('alert').getByText('Success', { exact: true })
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(
|
||||
page
|
||||
.getByRole('navigation', { name: 'breadcrumbs' })
|
||||
.getByRole('link', { name: targetName })
|
||||
).toBeVisible();
|
||||
|
||||
return targetName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to add a host source to a target. Assume you have selected the desired target.
|
||||
* @param {Page} page Playwright page object
|
||||
@@ -190,3 +220,66 @@ exports.addHostSourceToTarget = async (page, hostSourceName) => {
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: hostSourceName })).toBeVisible();
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to navigate to Sessions and waits for the session to appear.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} targetName Name of the target associated with the session
|
||||
*/
|
||||
exports.waitForSessionToBeVisible = async (page, targetName) => {
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Sessions' })
|
||||
.click();
|
||||
let i = 0;
|
||||
let sessionIsVisible = false;
|
||||
do {
|
||||
i = i + 1;
|
||||
sessionIsVisible = await page
|
||||
.getByRole('cell', { name: targetName })
|
||||
.isVisible();
|
||||
if (sessionIsVisible) {
|
||||
break;
|
||||
}
|
||||
await page.getByRole('button', { name: 'Refresh' }).click();
|
||||
await expect(page.getByRole('button', { name: 'Refresh' })).toBeEnabled();
|
||||
} while (i < 5);
|
||||
|
||||
if (!sessionIsVisible) {
|
||||
throw new Error('Session is not visible');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Uses the UI to navigate to the specified Target and add the Brokered Credentials to it.
|
||||
* @param {Page} page Playwright page object
|
||||
* @param {string} targetName Name of the target associated with the session
|
||||
* @param {string} credentialName Name of the credentials to be added to the target
|
||||
*/
|
||||
exports.addBrokeredCredentialsToTarget = async (page, targetName, credentialName) => {
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Targets' })
|
||||
.click();
|
||||
await page.getByRole('link', { name: targetName }).click();
|
||||
await page
|
||||
.getByRole('link', { name: 'Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('article')
|
||||
.getByRole('link', { name: 'Add Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('cell', { name: credentialName })
|
||||
.locator('..')
|
||||
.getByRole('checkbox')
|
||||
.click({ force: true });
|
||||
await page
|
||||
.getByRole('button', { name: 'Add Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await expect(
|
||||
page.getByRole('alert').getByText('Success', { exact: true })
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: credentialName })).toBeVisible();
|
||||
}
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
const { test, expect } = require('@playwright/test');
|
||||
const { execSync } = require('child_process');
|
||||
const { readFile } = require('fs/promises');
|
||||
const { nanoid } = require('nanoid');
|
||||
const { checkEnv, authenticatedState } = require('../helpers/general');
|
||||
const {
|
||||
authenticateBoundaryCli,
|
||||
checkBoundaryCli,
|
||||
getSessionCli,
|
||||
} = require('../helpers/boundary-cli');
|
||||
const {
|
||||
createNewOrg,
|
||||
@@ -20,6 +20,7 @@ const {
|
||||
createNewHostSet,
|
||||
createNewHostInHostSet,
|
||||
createNewTarget,
|
||||
addBrokeredCredentialsToTarget,
|
||||
addHostSourceToTarget,
|
||||
} = require('../helpers/boundary-ui');
|
||||
|
||||
@@ -36,17 +37,19 @@ test.beforeAll(async () => {
|
||||
await checkBoundaryCli();
|
||||
});
|
||||
|
||||
let orgName;
|
||||
let projectName;
|
||||
let targetName;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('Static Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
const orgName = await createNewOrg(page);
|
||||
const projectName = await createNewProject(page);
|
||||
orgName = await createNewOrg(page);
|
||||
projectName = await createNewProject(page);
|
||||
await createNewHostCatalog(page);
|
||||
const hostSetName = await createNewHostSet(page);
|
||||
await createNewHostInHostSet(page);
|
||||
const targetName = await createNewTarget(page);
|
||||
targetName = await createNewTarget(page);
|
||||
await addHostSourceToTarget(page, hostSetName);
|
||||
|
||||
const credentialStoreName = 'Credential Store ' + nanoid();
|
||||
@@ -66,7 +69,9 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
await expect(
|
||||
page.getByRole('link', { name: credentialStoreName })
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('Static Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
const credentialName = 'Credential ' + nanoid();
|
||||
await page.getByRole('link', { name: 'Credentials', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'New', exact: true }).click();
|
||||
@@ -90,47 +95,10 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: credentialName })).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Targets' })
|
||||
.click();
|
||||
await page.getByRole('link', { name: targetName }).click();
|
||||
await page
|
||||
.getByRole('link', { name: 'Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('article')
|
||||
.getByRole('link', { name: 'Add Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await page
|
||||
.getByRole('cell', { name: credentialName })
|
||||
.locator('..')
|
||||
.getByRole('checkbox')
|
||||
.click({ force: true });
|
||||
await page
|
||||
.getByRole('button', { name: 'Add Brokered Credentials', exact: true })
|
||||
.click();
|
||||
await expect(
|
||||
page.getByRole('alert').getByText('Success', { exact: true })
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: credentialName })).toBeVisible();
|
||||
await addBrokeredCredentialsToTarget(page, targetName, credentialName);
|
||||
|
||||
await authenticateBoundaryCli();
|
||||
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
|
||||
const org = orgs.items.filter((obj) => obj.name == orgName)[0];
|
||||
const projects = JSON.parse(
|
||||
execSync(`boundary scopes list -format json -scope-id ${org.id}`)
|
||||
);
|
||||
const project = projects.items.filter((obj) => obj.name == projectName)[0];
|
||||
const targets = JSON.parse(
|
||||
execSync(`boundary targets list -format json -scope-id ${project.id}`)
|
||||
);
|
||||
const target = targets.items.filter((obj) => obj.name == targetName)[0];
|
||||
|
||||
const session = JSON.parse(
|
||||
execSync(`boundary targets authorize-session -id ${target.id} -format json`)
|
||||
);
|
||||
const session = await getSessionCli(orgName, projectName, targetName);
|
||||
const retrievedUser = session.item.credentials[0].credential.username;
|
||||
const retrievedKey = session.item.credentials[0].credential.private_key;
|
||||
|
||||
@@ -146,3 +114,107 @@ test('Static Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
throw new Error('Stored Key does not match');
|
||||
}
|
||||
});
|
||||
|
||||
test('Static Credential Store (Username & Password)', async ({ page }) => {
|
||||
const credentialName = 'Credential ' + nanoid();
|
||||
await page.getByRole('link', { name: 'Credentials', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'New', exact: true }).click();
|
||||
await page.getByLabel('Name', { exact: true }).fill(credentialName);
|
||||
await page.getByLabel('Description').fill('This is an automated test');
|
||||
await page
|
||||
.getByRole('group', { name: 'Type' })
|
||||
.getByLabel('Username & Password')
|
||||
.click();
|
||||
await page
|
||||
.getByLabel('Username', { exact: true })
|
||||
.fill(process.env.E2E_SSH_USER);
|
||||
const testPassword = 'password';
|
||||
await page.getByLabel('Password', { exact: true }).fill(testPassword);
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await expect(
|
||||
page.getByRole('alert').getByText('Success', { exact: true })
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: credentialName })).toBeVisible();
|
||||
|
||||
await addBrokeredCredentialsToTarget(page, targetName, credentialName);
|
||||
|
||||
await authenticateBoundaryCli();
|
||||
const session = await getSessionCli(orgName, projectName, targetName);
|
||||
const retrievedUser = session.item.credentials[0].credential.username;
|
||||
const retrievedPassword = session.item.credentials[0].credential.password;
|
||||
|
||||
if (process.env.E2E_SSH_USER != retrievedUser) {
|
||||
throw new Error(
|
||||
'Stored User does not match. EXPECTED: ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
', ACTUAL: ' +
|
||||
retrievedUser
|
||||
);
|
||||
}
|
||||
if (testPassword != retrievedPassword) {
|
||||
throw new Error(
|
||||
'Stored Password does not match. EXPECTED: ' +
|
||||
testPassword +
|
||||
', ACTUAL: ' +
|
||||
retrievedPassword
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('Static Credential Store (JSON)', async ({ page }) => {
|
||||
const credentialName = 'Credential ' + nanoid();
|
||||
await page.getByRole('link', { name: 'Credentials', exact: true }).click();
|
||||
await page.getByRole('link', { name: 'New', exact: true }).click();
|
||||
await page.getByLabel('Name', { exact: true }).fill(credentialName);
|
||||
await page.getByLabel('Description').fill('This is an automated test');
|
||||
await page.getByRole('group', { name: 'Type' }).getByLabel('JSON').click();
|
||||
await page.getByText('{}').click();
|
||||
const testName = 'name-json';
|
||||
const testPassword = 'password-json';
|
||||
const testId = 'id-json';
|
||||
await page.keyboard.type(
|
||||
`"username": "${testName}",
|
||||
"password": "${testPassword}",
|
||||
"id": "${testId}"`
|
||||
);
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await expect(
|
||||
page.getByRole('alert').getByText('Success', { exact: true })
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dismiss' }).click();
|
||||
await expect(page.getByRole('link', { name: credentialName })).toBeVisible();
|
||||
|
||||
await addBrokeredCredentialsToTarget(page, targetName, credentialName);
|
||||
|
||||
await authenticateBoundaryCli();
|
||||
const session = await getSessionCli(orgName, projectName, targetName);
|
||||
const retrievedUser = session.item.credentials[0].credential.username;
|
||||
const retrievedPassword = session.item.credentials[0].credential.password;
|
||||
const retrievedId = session.item.credentials[0].credential.id;
|
||||
|
||||
if (testName != retrievedUser) {
|
||||
throw new Error(
|
||||
'Stored User does not match. EXPECTED: ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
', ACTUAL: ' +
|
||||
retrievedUser
|
||||
);
|
||||
}
|
||||
if (testPassword != retrievedPassword) {
|
||||
throw new Error(
|
||||
'Stored Password does not match. EXPECTED: ' +
|
||||
testPassword +
|
||||
', ACTUAL: ' +
|
||||
retrievedPassword
|
||||
);
|
||||
}
|
||||
if (testId != retrievedId) {
|
||||
throw new Error(
|
||||
'Stored ID does not match. EXPECTED: ' +
|
||||
testId +
|
||||
', ACTUAL: ' +
|
||||
retrievedId
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -22,6 +22,7 @@ const {
|
||||
createNewTarget,
|
||||
addHostSourceToTarget,
|
||||
} = require('../helpers/boundary-ui');
|
||||
const { readFile } = require('fs/promises');
|
||||
|
||||
const secretsPath = 'e2e_secrets';
|
||||
const secretName = 'cred';
|
||||
@@ -180,6 +181,9 @@ test('Vault Credential Store (User & Key Pair)', async ({ page }) => {
|
||||
retrievedUser
|
||||
);
|
||||
}
|
||||
const keyData = await readFile(process.env.E2E_SSH_KEY_PATH, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
if (keyData != retrievedKey) {
|
||||
throw new Error('Stored Key does not match');
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
const { test, expect } = require('@playwright/test');
|
||||
const { exec, execSync } = require('child_process');
|
||||
const { test } = require('@playwright/test');
|
||||
const { execSync } = require('child_process');
|
||||
const { checkEnv, authenticatedState } = require('../helpers/general');
|
||||
const {
|
||||
authenticateBoundaryCli,
|
||||
checkBoundaryCli,
|
||||
connectToTarget,
|
||||
deleteOrg,
|
||||
} = require('../helpers/boundary-cli');
|
||||
const {
|
||||
createNewOrg,
|
||||
@@ -18,6 +20,8 @@ const {
|
||||
createNewHostSet,
|
||||
createNewHostInHostSet,
|
||||
createNewTarget,
|
||||
createNewTargetWithAddress,
|
||||
waitForSessionToBeVisible,
|
||||
addHostSourceToTarget,
|
||||
} = require('../helpers/boundary-ui');
|
||||
|
||||
@@ -34,10 +38,12 @@ test.beforeAll(async () => {
|
||||
await checkBoundaryCli();
|
||||
});
|
||||
|
||||
test('Verify session created then cancel the session', async ({ page }) => {
|
||||
test('Verify session created to target with host, then cancel the session', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
|
||||
var connect;
|
||||
let org;
|
||||
let connect;
|
||||
try {
|
||||
const orgName = await createNewOrg(page);
|
||||
const projectName = await createNewProject(page);
|
||||
@@ -49,7 +55,7 @@ test('Verify session created then cancel the session', async ({ page }) => {
|
||||
|
||||
await authenticateBoundaryCli();
|
||||
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
|
||||
const org = orgs.items.filter((obj) => obj.name == orgName)[0];
|
||||
org = orgs.items.filter((obj) => obj.name == orgName)[0];
|
||||
const projects = JSON.parse(
|
||||
execSync('boundary scopes list -format json -scope-id ' + org.id)
|
||||
);
|
||||
@@ -59,50 +65,54 @@ test('Verify session created then cancel the session', async ({ page }) => {
|
||||
);
|
||||
const target = targets.items.filter((obj) => obj.name == targetName)[0];
|
||||
|
||||
connect = exec(
|
||||
'boundary connect' +
|
||||
' -target-id=' +
|
||||
target.id +
|
||||
' -exec /usr/bin/ssh --' +
|
||||
' -l ' +
|
||||
process.env.E2E_SSH_USER +
|
||||
' -i ' +
|
||||
process.env.E2E_SSH_KEY_PATH +
|
||||
' -o UserKnownHostsFile=/dev/null' +
|
||||
' -o StrictHostKeyChecking=no' +
|
||||
' -o IdentitiesOnly=yes' + // forces the use of the provided key
|
||||
' -p {{boundary.port}}' +
|
||||
' {{boundary.ip}}'
|
||||
);
|
||||
|
||||
await page
|
||||
.getByRole('navigation', { name: 'Resources' })
|
||||
.getByRole('link', { name: 'Sessions' })
|
||||
.click();
|
||||
let i = 0;
|
||||
let sessionIsVisible = false;
|
||||
do {
|
||||
i = i + 1;
|
||||
sessionIsVisible = await page
|
||||
.getByRole('cell', { name: targetName })
|
||||
.isVisible();
|
||||
if (sessionIsVisible) {
|
||||
break;
|
||||
}
|
||||
await page.getByRole('button', { name: 'Refresh' }).click();
|
||||
await expect(page.getByRole('button', { name: 'Refresh' })).toBeEnabled();
|
||||
} while (i < 5);
|
||||
|
||||
if (!sessionIsVisible) {
|
||||
throw new Error('Session is not visible');
|
||||
}
|
||||
|
||||
connect = await connectToTarget(target.id);
|
||||
await waitForSessionToBeVisible(page, targetName);
|
||||
await page
|
||||
.getByRole('cell', { name: targetName })
|
||||
.locator('..')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
} finally {
|
||||
await deleteOrg(org.id);
|
||||
// End `boundary connect` process
|
||||
if (connect) {
|
||||
connect.kill('SIGTERM');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('Verify session created to target with address, then cancel the session', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
let org;
|
||||
let connect;
|
||||
try {
|
||||
const orgName = await createNewOrg(page);
|
||||
const projectName = await createNewProject(page);
|
||||
const targetName = await createNewTargetWithAddress(page);
|
||||
|
||||
await authenticateBoundaryCli();
|
||||
const orgs = JSON.parse(execSync('boundary scopes list -format json'));
|
||||
org = orgs.items.filter((obj) => obj.name == orgName)[0];
|
||||
const projects = JSON.parse(
|
||||
execSync('boundary scopes list -format json -scope-id ' + org.id)
|
||||
);
|
||||
const project = projects.items.filter((obj) => obj.name == projectName)[0];
|
||||
const targets = JSON.parse(
|
||||
execSync('boundary targets list -format json -scope-id ' + project.id)
|
||||
);
|
||||
const target = targets.items.filter((obj) => obj.name == targetName)[0];
|
||||
|
||||
connect = await connectToTarget(target.id);
|
||||
await waitForSessionToBeVisible(page, targetName);
|
||||
await page
|
||||
.getByRole('cell', { name: targetName })
|
||||
.locator('..')
|
||||
.getByRole('button', { name: 'Cancel' })
|
||||
.click();
|
||||
} finally {
|
||||
await deleteOrg(org.id);
|
||||
// End `boundary connect` process
|
||||
if (connect) {
|
||||
connect.kill('SIGTERM');
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
<dropdown.separator />
|
||||
|
||||
<dropdown.section @title={{t 'titles.toggle-color-theme'}}>
|
||||
<dropdown.section @title={{t 'actions.toggle-color-theme'}}>
|
||||
<Rose::Form as |form|>
|
||||
<form.radioGroup
|
||||
@name='theme'
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
"tree-kill": "^1.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.0.4",
|
||||
"@electron-forge/maker-deb": "^6.0.4",
|
||||
"@electron-forge/maker-dmg": "^6.0.4",
|
||||
"@electron-forge/maker-squirrel": "^6.0.4",
|
||||
"@electron-forge/maker-zip": "^6.0.4",
|
||||
"@electron-forge/cli": "^6.1.1",
|
||||
"@electron-forge/maker-deb": "^6.1.1",
|
||||
"@electron-forge/maker-dmg": "^6.1.1",
|
||||
"@electron-forge/maker-squirrel": "^6.1.1",
|
||||
"@electron-forge/maker-zip": "^6.1.1",
|
||||
"decompress": "^4.2.1",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "21.2.0"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@electron-forge/cli@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-6.0.4.tgz#0a98ebdf2ec09744129209effd3f10606ef5083c"
|
||||
integrity sha512-iyQyh0g/cSWVQs30wsAqmTmqgV8E/i9Cy/CsHwHxQlsHHcq8N61k1JlB2dpEV1Hy9Lxafql5TE3/6uI7939IEg==
|
||||
"@electron-forge/cli@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-6.1.1.tgz#671b81f365570a385b40d9726b3d9a027c503782"
|
||||
integrity sha512-ufD9wKh35Mynj5MEKcWQKLpuIgxPvehwvykHRULi2ev8MWLCqxN4wda1Wy/cj57Uaeokf2rTbcGHGqbBX60bFQ==
|
||||
dependencies:
|
||||
"@electron-forge/core" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/core" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron/get" "^2.0.0"
|
||||
chalk "^4.0.0"
|
||||
commander "^4.1.1"
|
||||
@@ -17,12 +17,12 @@
|
||||
listr2 "^5.0.3"
|
||||
semver "^7.2.1"
|
||||
|
||||
"@electron-forge/core-utils@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-6.0.4.tgz#dae0a47d9ffb93ee02de05720617d39b65666731"
|
||||
integrity sha512-nOCjmm8Qr/bYkVNfEiXSk/LKjtv6iBrKcyhKIanNM3n7MJRuTH0ksvuajFBqg+V+EHplMb7y6acDvI+TTRDUxg==
|
||||
"@electron-forge/core-utils@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-6.1.1.tgz#4eaa3b3d5f4d0b888c3500e3b6f4f0b975100c2c"
|
||||
integrity sha512-7Kt0o85UEzpYjWU2WQ3pVuSOnRIDfuFimCQ1bh9qym5NLrkDcIQx9sIsCFIFkWYkUY7oIuMIMOhrGA4tyWGl2w==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron/rebuild" "^3.2.10"
|
||||
"@malept/cross-spawn-promise" "^2.0.0"
|
||||
chalk "^4.0.0"
|
||||
@@ -33,19 +33,20 @@
|
||||
semver "^7.2.1"
|
||||
yarn-or-npm "^3.0.1"
|
||||
|
||||
"@electron-forge/core@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-6.0.4.tgz#a6b32b7e4d88d35b2f1e052b2d5cd83c617bb63b"
|
||||
integrity sha512-l3OiXB/9ebtZZtcQAbofaTmivQUqUVv8TKoxQ8GJbH48Eyk//mphbo7hDC5kb5Tyd0UedMOM9MxJrYjnd6jRnA==
|
||||
"@electron-forge/core@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-6.1.1.tgz#09995ca65c3b35efef24695fdb8b8033585965ac"
|
||||
integrity sha512-Fh1rNY1eI2wqbFXJ8eRBsJDS6gxfElgVR4nhMY+I+MZs9ddw1MFHIWwoqYjGFJKUBd9xTXCk5lkf8TwCpb4Igg==
|
||||
dependencies:
|
||||
"@electron-forge/core-utils" "^6.0.4"
|
||||
"@electron-forge/maker-base" "^6.0.4"
|
||||
"@electron-forge/plugin-base" "^6.0.4"
|
||||
"@electron-forge/publisher-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/template-base" "^6.0.4"
|
||||
"@electron-forge/template-webpack" "^6.0.4"
|
||||
"@electron-forge/template-webpack-typescript" "^6.0.4"
|
||||
"@electron-forge/core-utils" "6.1.1"
|
||||
"@electron-forge/maker-base" "6.1.1"
|
||||
"@electron-forge/plugin-base" "6.1.1"
|
||||
"@electron-forge/publisher-base" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron-forge/template-base" "6.1.1"
|
||||
"@electron-forge/template-vite" "6.1.1"
|
||||
"@electron-forge/template-webpack" "6.1.1"
|
||||
"@electron-forge/template-webpack-typescript" "6.1.1"
|
||||
"@electron/get" "^2.0.0"
|
||||
"@electron/rebuild" "^3.2.10"
|
||||
"@malept/cross-spawn-promise" "^2.0.0"
|
||||
@@ -71,107 +72,117 @@
|
||||
username "^5.1.0"
|
||||
yarn-or-npm "^3.0.1"
|
||||
|
||||
"@electron-forge/maker-base@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-6.0.4.tgz#7de68dd11d2a670b552860aea01767870bb44f92"
|
||||
integrity sha512-qJJ2oPFlyt6u/H67WLfZL0JclSpFj4VwxPfwxqNL/HcwXULJcOeat7oqJLY9UKBE4U2j+++xbA3LSoPAErroIg==
|
||||
"@electron-forge/maker-base@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-6.1.1.tgz#2c8fdaaaa28ff39fbf4ff26e664dc79265f96b49"
|
||||
integrity sha512-qEW8vuSq6/r1rKh7JENK9yGmueymMzbm817GDk5usHia5o7otHYY4JMkdzZaKww56Ed/Ege2ch6LEYqYGTfl/Q==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
which "^2.0.2"
|
||||
|
||||
"@electron-forge/maker-deb@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-6.0.4.tgz#5ac9a844f31898e0bd33b73919622583cc7ded75"
|
||||
integrity sha512-kBqRiPqAInPqBEZD1iRYiF2yb7Mhcdlrn80kCtTwTF8oAA6d081g6mcrMt12sf5GBGF8IXKzm6JqbqelpYbKww==
|
||||
"@electron-forge/maker-deb@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-6.1.1.tgz#6482e239b09438f57cbdfd60b9f6474fbf09c334"
|
||||
integrity sha512-Qk/QMBwWP/D6Fx7+VU54xHec47R9CYg0TCaRtQ1KeBNFdJ3DpwCARr966/IJqEUxX7y8vv8Awc8HvKDPxbpIUA==
|
||||
dependencies:
|
||||
"@electron-forge/maker-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/maker-base" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
optionalDependencies:
|
||||
electron-installer-debian "^3.0.0"
|
||||
|
||||
"@electron-forge/maker-dmg@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-dmg/-/maker-dmg-6.0.4.tgz#c41ed8608295900ab3582699cf8297609071e8f4"
|
||||
integrity sha512-03Q6dVpZu7HdvBFtcZVoCSN0lA3Iqi3H/JjR82G0cWINwgwAKzBlGIcZmkfU+fdBAiO4Z6tUfaYrDDtBhpn1sQ==
|
||||
"@electron-forge/maker-dmg@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-dmg/-/maker-dmg-6.1.1.tgz#8e36906611a4fc809b711f8558a94610e3d7c713"
|
||||
integrity sha512-ko9ZkbXgsRUoRFVpfESVr7O68QmoIylOscoBHLxdESHy4FPI+C6BYxQrxIRdAR27vQmRmdVm6zVXRXmaQgLQBQ==
|
||||
dependencies:
|
||||
"@electron-forge/maker-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/maker-base" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
optionalDependencies:
|
||||
electron-installer-dmg "^4.0.0"
|
||||
|
||||
"@electron-forge/maker-squirrel@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-squirrel/-/maker-squirrel-6.0.4.tgz#21b09a5165b27cc156e3c15989f7fe157752d8ac"
|
||||
integrity sha512-1bZ5RgSex5Y45HSuOqjki2oHIq/CquVPP5sLYhObd2p2ABj4ZzyqErNFK1eerDIjoesici3KKCASqBpKf2N90Q==
|
||||
"@electron-forge/maker-squirrel@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-squirrel/-/maker-squirrel-6.1.1.tgz#34bcaf25f3872d8394826ab9237ad2716111eb06"
|
||||
integrity sha512-YA7EY7He5FGGiwNlcOLSHwtrDFmq1XZ+0sKHy/xLu0Q8JZzo15WQ0vwJJEIAxL8KAtjwfhyV5VAWI6w0elr/jg==
|
||||
dependencies:
|
||||
"@electron-forge/maker-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/maker-base" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
optionalDependencies:
|
||||
electron-winstaller "^5.0.0"
|
||||
|
||||
"@electron-forge/maker-zip@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-6.0.4.tgz#db4cc7f44ccf1d30fa1bc95c36d6b9708d3e5888"
|
||||
integrity sha512-tjBi46qU4vKpYUNUIv5ar6hBDjr9G7+QIUiaOj4UIN3Rwa20EvsYMBoMJBxV/CUUwkQc1NBihUPLco7PAVNb+g==
|
||||
"@electron-forge/maker-zip@^6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-6.1.1.tgz#fba5cd18b6f33497f3aadbdade5c0a2142ca9e9a"
|
||||
integrity sha512-3T2bIbYhKl3Z/VyeN+X7+7U+HhgaCtBCfDi0k/Ga7CoUpge2uJS/+yjfGJdwFk4TbWhS3sNkZV2mFMKhx/rlmQ==
|
||||
dependencies:
|
||||
"@electron-forge/maker-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/maker-base" "6.1.1"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
cross-zip "^4.0.0"
|
||||
fs-extra "^10.0.0"
|
||||
got "^11.8.5"
|
||||
|
||||
"@electron-forge/plugin-base@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-6.0.4.tgz#a3b62e006632dab66d35f845ca61e09745ccbb82"
|
||||
integrity sha512-iILzbFzmUIGggsTNL9PO1ma6e4OuuhKunNnOkpkoyg6jIaz8Oh1WSHhOALMztlBn2FhreabZnBRy7JsvHVDXlg==
|
||||
"@electron-forge/plugin-base@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-6.1.1.tgz#73f4688654cd29591af533be53c2a3a656405331"
|
||||
integrity sha512-xZWZxvD2fQYnkFREK+46FS59vMEsPFINwydtD24QGTBoRMOKXkfXv16yN4eexVi+02Hj6mihYY8zhxJi56OmxA==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
|
||||
"@electron-forge/publisher-base@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-6.0.4.tgz#dd5db7ec04f8c5a6a70afa548950381052673806"
|
||||
integrity sha512-0C86jnOSTo0z/W58zRx6BijuR4lscB0F6yXaBCFA5xaJ8+fVIsgz29kmVlLrp+YFRgatDCljvk+1+qVRM/Mfpg==
|
||||
"@electron-forge/publisher-base@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-6.1.1.tgz#45e53554613b9ff9bca18cd2b4c8aab5ba85f099"
|
||||
integrity sha512-vxGzx2G7bWhz2G091MzNh+LHGrOM4gmp8FqW2VNpFJfFEYODr6D9KxitUihKAWc79bwG+YywvISXEMy5IBQu0Q==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
|
||||
"@electron-forge/shared-types@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-6.0.4.tgz#f8cdcf453459caa156d513582054b8e81057584f"
|
||||
integrity sha512-lILLKcGZqfJYVI1x6RssVh37E934rCOaSdBQ9I7LypdfI2NWL+5PLLoUqvXbok1V28m3/O5JrXdigwEIZdhjzQ==
|
||||
"@electron-forge/shared-types@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-6.1.1.tgz#f08cf783bf0a086331784b9f13110b4fade84846"
|
||||
integrity sha512-sFQQ2ldMq5mlNv4m7lZOZLf9aOn6MLNc8QVeTzOBQ+psxI3mVTDjb+/Lhs/jU8dm2igVfEqAmlj57Gi+C4u4Vw==
|
||||
dependencies:
|
||||
"@electron/rebuild" "^3.2.10"
|
||||
electron-packager "^17.1.1"
|
||||
listr2 "^5.0.3"
|
||||
|
||||
"@electron-forge/template-base@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-6.0.4.tgz#9d42af1fe77cf6d1ee8e43109d3eefabd1caf95e"
|
||||
integrity sha512-23/b0n+ls0+c2+OG1XrHROk6i3PseONLJY3tcR42uFaP/yGZL8nJfgXE2qTKBwUyFQ0tCgUAD3a4vYkMPLKrwg==
|
||||
"@electron-forge/template-base@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-6.1.1.tgz#ff6f32735491a235f404bf0cb069c8737fbfc4d4"
|
||||
integrity sha512-i4EZHXIFTo+nJXJHPS1k9PAnWKEKGC4kMUvIsyYKEu+NrOTcGLMT4FIRM9VYe1nGarQLd486/274S3b2SaCUuw==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@malept/cross-spawn-promise" "^2.0.0"
|
||||
debug "^4.3.1"
|
||||
fs-extra "^10.0.0"
|
||||
username "^5.1.0"
|
||||
|
||||
"@electron-forge/template-webpack-typescript@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-6.0.4.tgz#8dea2d6deb6be9b73203fc93c49d88dfe86f2c1f"
|
||||
integrity sha512-Z9fJ0JfZw9w5OVZgy0qVGapGMQqfaLyQSHzEfm2HQdGGJrHkeXJkMn8Yd1E8h5EPMb3jF5tHRw3VopelzcPQxQ==
|
||||
"@electron-forge/template-vite@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-6.1.1.tgz#b4eff93c1f9c4e6eeb60d0c71359c36f0c485a13"
|
||||
integrity sha512-/6Sv7trkfjJR9LI7i83xmddVhi32pDlDE2kwlCkRgcoE2jGoW0fJU1BNfjNWy61Rd1wNzgrpfjMTPQlMnwHb4g==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/template-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron-forge/template-base" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
|
||||
"@electron-forge/template-webpack@^6.0.4":
|
||||
version "6.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-6.0.4.tgz#17bfd20d93be8238a6ee62cc1cf5c4484906dbde"
|
||||
integrity sha512-mrzNzkhsLfD20y/vfTYVBFSkptmgSEwqn4zh4vnzP9tzAJ4eMbvhfVtkK/XQfm8ZspPjs+RZSzRrRNo+e0iEaw==
|
||||
"@electron-forge/template-webpack-typescript@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-6.1.1.tgz#422a9e93daa9ed957dc3ee28d9d5092a8ee3397b"
|
||||
integrity sha512-Ck7EgqoqfUL4r4NCioTsQT1/EFNCUqnsNd71MboU1RUvRbcrqpYvkoKk99+9QvxBrljMQp935gTieY7HADWQ9A==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "^6.0.4"
|
||||
"@electron-forge/template-base" "^6.0.4"
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron-forge/template-base" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
|
||||
"@electron-forge/template-webpack@6.1.1":
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-6.1.1.tgz#34413a0c21a68b70ea06b00c8b9d76df2cf6cbab"
|
||||
integrity sha512-M3hTEF3iV6VYufassMilautoOYTLbqD06U1u3B6MDZVn74xAzprIZ+5EgrvQR33N+E3PyDpkgyMh+FJtWCo0/A==
|
||||
dependencies:
|
||||
"@electron-forge/shared-types" "6.1.1"
|
||||
"@electron-forge/template-base" "6.1.1"
|
||||
fs-extra "^10.0.0"
|
||||
|
||||
"@electron/asar@^3.2.1":
|
||||
|
||||
Reference in new issue
Block a user