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

+11
View File
@@ -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;
}
}
+12 -2
View File
@@ -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(),
+8
View File
@@ -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:
+2 -2
View File
@@ -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
View File
@@ -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": {
+79 -54
View File
@@ -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
@@ -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';
+73 -1
View File
@@ -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;
};
+93
View File
@@ -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');
}
+54 -44
View File
@@ -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');
+1 -1
View File
@@ -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'
+5 -5
View File
@@ -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"
+94 -83
View File
@@ -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":
+322 -1312
View File
File diff suppressed because it is too large. Load diff