diff --git a/addons/api/addon/abilities/account.js b/addons/api/addon/abilities/account.js
new file mode 100644
index 000000000..147f73b9f
--- /dev/null
+++ b/addons/api/addon/abilities/account.js
@@ -0,0 +1,15 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for accounts.
+ */
+export default class AccountAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canSetPassword() {
+ return this.hasAuthorizedAction('set-password');
+ }
+}
diff --git a/addons/api/addon/abilities/group.js b/addons/api/addon/abilities/group.js
new file mode 100644
index 000000000..810cc82c2
--- /dev/null
+++ b/addons/api/addon/abilities/group.js
@@ -0,0 +1,22 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for groups.
+ */
+export default class GroupAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canAddMembers() {
+ return this.hasAuthorizedAction('add-members');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canRemoveMembers() {
+ return this.hasAuthorizedAction('remove-members');
+ }
+}
diff --git a/addons/api/addon/abilities/host-set.js b/addons/api/addon/abilities/host-set.js
new file mode 100644
index 000000000..088683178
--- /dev/null
+++ b/addons/api/addon/abilities/host-set.js
@@ -0,0 +1,22 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for host sets.
+ */
+export default class UserAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canAddHosts() {
+ return this.hasAuthorizedAction('add-hosts');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canRemoveHosts() {
+ return this.hasAuthorizedAction('remove-hosts');
+ }
+}
diff --git a/addons/api/addon/abilities/role.js b/addons/api/addon/abilities/role.js
new file mode 100644
index 000000000..f0c6d62ec
--- /dev/null
+++ b/addons/api/addon/abilities/role.js
@@ -0,0 +1,29 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for roles.
+ */
+export default class RoleAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canSetGrants() {
+ return this.hasAuthorizedAction('set-grants');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canAddPrincipals() {
+ return this.hasAuthorizedAction('add-principals');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canRemovePrincipals() {
+ return this.hasAuthorizedAction('remove-principals');
+ }
+}
diff --git a/addons/api/addon/abilities/target.js b/addons/api/addon/abilities/target.js
index fb6b30d33..11516c3b5 100644
--- a/addons/api/addon/abilities/target.js
+++ b/addons/api/addon/abilities/target.js
@@ -1,7 +1,7 @@
import ModelAbility from './model';
/**
- * Provides a `connect` ability for targets.
+ * Provides abilities for targets.
*/
export default class TargetAbility extends ModelAbility {
// =permissions
diff --git a/addons/api/addon/abilities/user.js b/addons/api/addon/abilities/user.js
new file mode 100644
index 000000000..dd2440fe7
--- /dev/null
+++ b/addons/api/addon/abilities/user.js
@@ -0,0 +1,22 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for users.
+ */
+export default class UserAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canAddAccounts() {
+ return this.hasAuthorizedAction('add-accounts');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canRemoveAccounts() {
+ return this.hasAuthorizedAction('remove-accounts');
+ }
+}
diff --git a/addons/api/app/abilities/account.js b/addons/api/app/abilities/account.js
new file mode 100644
index 000000000..e64435a5e
--- /dev/null
+++ b/addons/api/app/abilities/account.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/account';
diff --git a/addons/api/app/abilities/group.js b/addons/api/app/abilities/group.js
new file mode 100644
index 000000000..308aacba4
--- /dev/null
+++ b/addons/api/app/abilities/group.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/group';
diff --git a/addons/api/app/abilities/host-set.js b/addons/api/app/abilities/host-set.js
new file mode 100644
index 000000000..37ccd5e81
--- /dev/null
+++ b/addons/api/app/abilities/host-set.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/host-set';
diff --git a/addons/api/app/abilities/role.js b/addons/api/app/abilities/role.js
new file mode 100644
index 000000000..aefb6fd13
--- /dev/null
+++ b/addons/api/app/abilities/role.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/role';
diff --git a/addons/api/app/abilities/user.js b/addons/api/app/abilities/user.js
new file mode 100644
index 000000000..b02ba6ee2
--- /dev/null
+++ b/addons/api/app/abilities/user.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/user';
diff --git a/addons/api/mirage/factories/account.js b/addons/api/mirage/factories/account.js
index 5b7a14c09..f5da7b5af 100644
--- a/addons/api/mirage/factories/account.js
+++ b/addons/api/mirage/factories/account.js
@@ -9,6 +9,7 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'set-password',
],
attributes() {
switch (this.type) {
diff --git a/addons/api/mirage/factories/group.js b/addons/api/mirage/factories/group.js
index 1f7256543..6a16d3fb0 100644
--- a/addons/api/mirage/factories/group.js
+++ b/addons/api/mirage/factories/group.js
@@ -9,6 +9,8 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'add-members',
+ 'remove-members',
],
id: (i) => `group-${i}`,
diff --git a/addons/api/mirage/factories/host-set.js b/addons/api/mirage/factories/host-set.js
index def5ff70f..3b88650b7 100644
--- a/addons/api/mirage/factories/host-set.js
+++ b/addons/api/mirage/factories/host-set.js
@@ -8,6 +8,8 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'add-hosts',
+ 'remove-hosts',
],
id: (i) => `host-set-id-${i}`,
});
diff --git a/addons/api/mirage/factories/role.js b/addons/api/mirage/factories/role.js
index a057fc29f..be13712b8 100644
--- a/addons/api/mirage/factories/role.js
+++ b/addons/api/mirage/factories/role.js
@@ -9,6 +9,9 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'set-grants',
+ 'add-principals',
+ 'remove-principals',
],
// eslint-disable-next-line ember/avoid-leaking-state-in-ember-objects
grant_strings: () => [
diff --git a/addons/api/mirage/factories/user.js b/addons/api/mirage/factories/user.js
index b8463506d..837adba44 100644
--- a/addons/api/mirage/factories/user.js
+++ b/addons/api/mirage/factories/user.js
@@ -8,6 +8,8 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'add-accounts',
+ 'remove-accounts',
],
id: (i) => `user-${i}`,
});
diff --git a/addons/api/package.json b/addons/api/package.json
index bf5a662a2..8be07dd77 100644
--- a/addons/api/package.json
+++ b/addons/api/package.json
@@ -33,6 +33,7 @@
"ember-fetch": "^8.1.1"
},
"devDependencies": {
+ "@babel/core": "^7.15.8",
"@ember/optional-features": "^2.0.0",
"@ember/test-helpers": "^2.4.2",
"@glimmer/component": "^1.0.4",
diff --git a/addons/api/tests/unit/abilities/account-test-.js b/addons/api/tests/unit/abilities/account-test-.js
new file mode 100644
index 000000000..afd89329d
--- /dev/null
+++ b/addons/api/tests/unit/abilities/account-test-.js
@@ -0,0 +1,17 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | Account', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given account may set password based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['set-password'],
+ };
+ assert.ok(service.can('setPassword target', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('setPassword target', model));
+ });
+});
diff --git a/addons/api/tests/unit/abilities/group-test.js b/addons/api/tests/unit/abilities/group-test.js
new file mode 100644
index 000000000..a53be03c2
--- /dev/null
+++ b/addons/api/tests/unit/abilities/group-test.js
@@ -0,0 +1,28 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | Group', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given group resource may add members based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['add-members'],
+ };
+ assert.ok(service.can('addMembers group', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('addMembers group', model));
+ });
+
+ test('it reflects when a given group resource may remove members based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['remove-members'],
+ };
+ assert.ok(service.can('removeMembers group', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('removeMembers group', model));
+ });
+});
diff --git a/addons/api/tests/unit/abilities/host-set-test.js b/addons/api/tests/unit/abilities/host-set-test.js
new file mode 100644
index 000000000..24b0efa15
--- /dev/null
+++ b/addons/api/tests/unit/abilities/host-set-test.js
@@ -0,0 +1,28 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | Host Set', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given host set resource may add hosts based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['add-hosts'],
+ };
+ assert.ok(service.can('addHosts hostSet', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('addHosts hostSet', model));
+ });
+
+ test('it reflects when a given hostSet resource may remove hosts based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['remove-hosts'],
+ };
+ assert.ok(service.can('removeHosts hostSet', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('removeHosts hostSet', model));
+ });
+});
diff --git a/addons/api/tests/unit/abilities/role-test.js b/addons/api/tests/unit/abilities/role-test.js
new file mode 100644
index 000000000..462743446
--- /dev/null
+++ b/addons/api/tests/unit/abilities/role-test.js
@@ -0,0 +1,39 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | Role', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given role may set grants based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['set-grants'],
+ };
+ assert.ok(service.can('setGrants role', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('setGrants role', model));
+ });
+
+ test('it reflects when a given role may add principals based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['add-principals'],
+ };
+ assert.ok(service.can('addPrincipals role', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('addPrincipals role', model));
+ });
+
+ test('it reflects when a given role may remove principals based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['remove-principals'],
+ };
+ assert.ok(service.can('removePrincipals role', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('removePrincipals role', model));
+ });
+});
diff --git a/addons/api/tests/unit/abilities/user-test.js b/addons/api/tests/unit/abilities/user-test.js
new file mode 100644
index 000000000..33d8f78e7
--- /dev/null
+++ b/addons/api/tests/unit/abilities/user-test.js
@@ -0,0 +1,28 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | User', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given user resource may add accounts based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['add-accounts'],
+ };
+ assert.ok(service.can('addAccounts user', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('addAccounts user', model));
+ });
+
+ test('it reflects when a given user resource may remove accounts based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['remove-accounts'],
+ };
+ assert.ok(service.can('removeAccounts user', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('removeAccounts user', model));
+ });
+});
diff --git a/addons/rose/package.json b/addons/rose/package.json
index 8a0a04d78..845b6c33c 100644
--- a/addons/rose/package.json
+++ b/addons/rose/package.json
@@ -29,7 +29,6 @@
"doc:toc": "doctoc README.md"
},
"dependencies": {
- "babel-loader": "^8.2.2",
"ember-cli-babel": "^7.26.6",
"ember-cli-htmlbars": "^5.7.1",
"ember-focus-trap": "^0.7.0",
@@ -39,6 +38,7 @@
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774"
},
"devDependencies": {
+ "@babel/core": "^7.15.5",
"@ember/optional-features": "^2.0.0",
"@ember/test-helpers": "^2.4.2",
"@glimmer/component": "^1.0.4",
@@ -47,9 +47,11 @@
"@storybook/addon-actions": "^6.3.8",
"@storybook/addon-docs": "^6.3.8",
"@storybook/addon-knobs": "^6.3.1",
+ "@storybook/addons": "^6.3.9",
"@storybook/ember": "^6.3.8",
"@storybook/ember-cli-storybook": "^0.4.0",
"babel-eslint": "^10.1.0",
+ "babel-loader": "^8.2.2",
"broccoli-asset-rev": "^3.0.0",
"doctoc": "^2.0.1",
"ember-auto-import": "^1.12.0",
@@ -83,6 +85,8 @@
"prettier": "^2.4.0",
"qunit": "^2.17.1",
"qunit-dom": "^2.0.0",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
"sass": "^1.41.0",
"sass-lint": "^1.13.1"
},
diff --git a/ui/admin/app/components/form/role/grants/index.hbs b/ui/admin/app/components/form/role/grants/index.hbs
index 79766a2e1..d6aaad424 100644
--- a/ui/admin/app/components/form/role/grants/index.hbs
+++ b/ui/admin/app/components/form/role/grants/index.hbs
@@ -1,39 +1,43 @@
-
-
- {{! Add grant field (only one per form) }}
-
-
-
- {{t 'resources.role.grant.actions.create'}}
-
-
-
-
-
-
- {{t 'actions.add'}}
-
-
-
-
-
-
+{{#if (can 'setGrants role' @model)}}
+
+
+ {{! Add grant field (only one per form) }}
+
+
+
+ {{t
+ 'resources.role.grant.actions.create'
+ }}
+
+
+
+
+
+
+ {{t 'actions.add'}}
+
+
+
+
+
+
+{{/if}}
@@ -72,23 +77,27 @@
-
- {{t 'actions.remove'}}
-
+ {{#if (can 'setGrants role' @model)}}
+
+ {{t 'actions.remove'}}
+
+ {{/if}}
{{/each}}
-
+ {{#if (can 'setGrants role' @model)}}
+
+ {{/if}}
\ No newline at end of file
diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-navigation.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-navigation.hbs
index da08d1834..12ca372ce 100644
--- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-navigation.hbs
+++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/account/-navigation.hbs
@@ -5,10 +5,12 @@
{{t 'titles.details'}}
{{#if @model.isPassword}}
-
- {{t 'actions.set-password'}}
-
+ {{#if (can 'setPassword account' @model)}}
+
+ {{t 'actions.set-password'}}
+
+ {{/if}}
{{/if}}
\ No newline at end of file
diff --git a/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs b/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
index 253b39ab0..7dbbf977b 100644
--- a/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
+++ b/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
@@ -3,9 +3,11 @@
@dropdownRight={{true}}
as |dropdown|
>
-
- {{t 'resources.group.actions.add-members'}}
-
+ {{#if (can 'addMembers group' @model)}}
+
+ {{t 'resources.group.actions.add-members'}}
+
+ {{/if}}
{{#if (can 'delete model' @model)}}
-
-
- {{t 'actions.remove'}}
-
-
+
+ {{t 'actions.remove'}}
+
+
+ {{/if}}
{{/each}}
diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs
index d78e1b940..d0bae064d 100644
--- a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs
+++ b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/-actions.hbs
@@ -3,16 +3,18 @@
@dropdownRight={{true}}
as |dropdown|
>
-
- {{t 'resources.host-set.actions.create-and-add-host'}}
-
-
- {{t 'resources.host-set.actions.add-hosts'}}
-
+ {{#if (can 'addHosts hostSet' @model)}}
+
+ {{t 'resources.host-set.actions.create-and-add-host'}}
+
+
+ {{t 'resources.host-set.actions.add-hosts'}}
+
+ {{/if}}
{{#if (can 'delete model' @model)}}
-
-
- {{t 'actions.remove'}}
-
-
+
+ {{t 'actions.remove'}}
+
+
+ {{/if}}
{{/each}}
diff --git a/ui/admin/app/templates/scopes/scope/roles/role/-actions.hbs b/ui/admin/app/templates/scopes/scope/roles/role/-actions.hbs
index 88add065c..6c01fcc16 100644
--- a/ui/admin/app/templates/scopes/scope/roles/role/-actions.hbs
+++ b/ui/admin/app/templates/scopes/scope/roles/role/-actions.hbs
@@ -3,9 +3,11 @@
@dropdownRight={{true}}
as |dropdown|
>
-
- {{t 'resources.role.principal.actions.add-principals'}}
-
+ {{#if (can 'addPrincipals role' @model)}}
+
+ {{t 'resources.role.principal.actions.add-principals'}}
+
+ {{/if}}
{{#if (can 'delete model' @model)}}
-
-
- {{t 'actions.remove'}}
-
-
+
+ {{t 'actions.remove'}}
+
+
+ {{/if}}
{{/each}}
diff --git a/ui/admin/app/templates/scopes/scope/users/user/-actions.hbs b/ui/admin/app/templates/scopes/scope/users/user/-actions.hbs
index 280fd98bb..998af871b 100644
--- a/ui/admin/app/templates/scopes/scope/users/user/-actions.hbs
+++ b/ui/admin/app/templates/scopes/scope/users/user/-actions.hbs
@@ -3,9 +3,11 @@
@dropdownRight={{true}}
as |dropdown|
>
-
- {{t 'resources.user.actions.add-accounts'}}
-
+ {{#if (can 'addAccounts user' @model)}}
+
+ {{t 'resources.user.actions.add-accounts'}}
+
+ {{/if}}
{{#if (can 'delete model' @model)}}
-
-
- {{t 'actions.remove'}}
-
-
+
+ {{t 'actions.remove'}}
+
+
+ {{/if}}
{{/each}}
diff --git a/ui/admin/tests/acceptance/accounts/set-password-test.js b/ui/admin/tests/acceptance/accounts/set-password-test.js
index 677e9bd7c..89f9ce3e7 100644
--- a/ui/admin/tests/acceptance/accounts/set-password-test.js
+++ b/ui/admin/tests/acceptance/accounts/set-password-test.js
@@ -49,7 +49,8 @@ module('Acceptance | accounts | set password', function (hooks) {
urls.authMethods = `${urls.orgScope}/auth-methods`;
urls.authMethod = `${urls.authMethods}/${instances.authMethod.id}`;
urls.accounts = `${urls.authMethod}/accounts`;
- urls.setPassword = `${urls.accounts}/${instances.account.id}/set-password`;
+ urls.account = `${urls.accounts}/${instances.account.id}`;
+ urls.setPassword = `${urls.account}/set-password`;
});
test('visiting account set password', async function (assert) {
@@ -59,6 +60,26 @@ module('Acceptance | accounts | set password', function (hooks) {
assert.equal(currentURL(), urls.setPassword);
});
+ test('can navigate to route with proper authorization', async function (assert) {
+ assert.expect(1);
+ await visit(urls.account);
+ assert.ok(
+ find(`.rose-layout-page-navigation [href="${urls.setPassword}"]`)
+ );
+ });
+
+ test('cannot navigate to route without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.account.authorized_actions.filter(
+ (item) => item !== 'set-password'
+ );
+ instances.account.update({ authorized_actions });
+ await visit(urls.account);
+ assert.notOk(
+ find(`.rose-layout-page-navigation [href="${urls.setPassword}"]`)
+ );
+ });
+
test('can set a new password for account', async function (assert) {
assert.expect(1);
this.server.post(
diff --git a/ui/admin/tests/acceptance/groups/members-test.js b/ui/admin/tests/acceptance/groups/members-test.js
index 2d615b8ba..295db8404 100644
--- a/ui/admin/tests/acceptance/groups/members-test.js
+++ b/ui/admin/tests/acceptance/groups/members-test.js
@@ -68,6 +68,16 @@ module('Acceptance | groups | members', function (hooks) {
assert.equal(findAll('tbody tr').length, membersCount - 1);
});
+ test('cannot remove a member without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.group.authorized_actions.filter(
+ (item) => item !== 'remove-members'
+ );
+ instances.group.update({ authorized_actions });
+ await visit(urls.members);
+ assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
+ });
+
test('shows error message on member remove', async function (assert) {
assert.expect(2);
this.server.post('/groups/:idMethod', () => {
@@ -95,6 +105,22 @@ module('Acceptance | groups | members', function (hooks) {
assert.equal(currentURL(), urls.addMembers);
});
+ test('can navigate to add members with proper authorization', async function (assert) {
+ assert.expect(1);
+ await visit(urls.group);
+ assert.ok(find(`[href="${urls.addMembers}"]`));
+ });
+
+ test('cannot navigate to add members without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.group.authorized_actions.filter(
+ (item) => item !== 'add-members'
+ );
+ instances.group.update({ authorized_actions });
+ await visit(urls.group);
+ assert.notOk(find(`[href="${urls.addMembers}"]`));
+ });
+
test('select and save members to add', async function (assert) {
assert.expect(3);
instances.group.update({ memberIds: [] });
diff --git a/ui/admin/tests/acceptance/host-catalogs/host-sets/hosts-test.js b/ui/admin/tests/acceptance/host-catalogs/host-sets/hosts-test.js
index 3140961c7..2423c62ca 100644
--- a/ui/admin/tests/acceptance/host-catalogs/host-sets/hosts-test.js
+++ b/ui/admin/tests/acceptance/host-catalogs/host-sets/hosts-test.js
@@ -99,6 +99,16 @@ module('Acceptance | host-catalogs | host-sets | hosts', function (hooks) {
assert.equal(findAll('tbody tr').length, count - 1);
});
+ test('cannot remove a host without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.hostSet.authorized_actions.filter(
+ (item) => item !== 'remove-hosts'
+ );
+ instances.hostSet.update({ authorized_actions });
+ await visit(urls.hostSetHosts);
+ assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
+ });
+
test('shows error message on host remove error', async function (assert) {
assert.expect(2);
this.server.post('/host-sets/:idMethod', () => {
@@ -126,6 +136,22 @@ module('Acceptance | host-catalogs | host-sets | hosts', function (hooks) {
assert.equal(currentURL(), urls.addHosts);
});
+ test('can navigate to add hosts with proper authorization', async function (assert) {
+ assert.expect(1);
+ await visit(urls.hostSet);
+ assert.ok(find(`[href="${urls.addHosts}"]`));
+ });
+
+ test('cannot navigate to add hosts without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.hostSet.authorized_actions.filter(
+ (item) => item !== 'add-hosts'
+ );
+ instances.hostSet.update({ authorized_actions });
+ await visit(urls.hostSet);
+ assert.notOk(find(`[href="${urls.addHosts}"]`));
+ });
+
test('select and save hosts to add', async function (assert) {
assert.expect(3);
instances.hostSet.update({ hostIds: [] });
diff --git a/ui/admin/tests/acceptance/roles/grants-test.js b/ui/admin/tests/acceptance/roles/grants-test.js
index d13eb4f46..fd169aa46 100644
--- a/ui/admin/tests/acceptance/roles/grants-test.js
+++ b/ui/admin/tests/acceptance/roles/grants-test.js
@@ -63,6 +63,26 @@ module('Acceptance | roles | grants', function (hooks) {
assert.equal(findAll(`${grantsForm} [name="grant"]`).length, grantsCount);
});
+ test('cannot set grants without proper authorization', async function (assert) {
+ assert.expect(4);
+ const authorized_actions = instances.role.authorized_actions.filter(
+ (item) => item !== 'set-grants'
+ );
+ instances.role.update({ authorized_actions });
+ await visit(urls.grants);
+ assert.equal(
+ findAll('main form').length,
+ 1,
+ 'New grant form is not displayed.'
+ );
+ assert.notOk(
+ find('main form button:not([type="submit"])'),
+ 'Grant delete button is not displayed.'
+ );
+ assert.notOk(find('.rose-form-actions'), 'Form actions are not displayed.');
+ assert.ok(find('main form input[disabled]'), 'Grant fields are disabled.');
+ });
+
test('update a grant', async function (assert) {
assert.expect(1);
this.server.post(
diff --git a/ui/admin/tests/acceptance/roles/principals-test.js b/ui/admin/tests/acceptance/roles/principals-test.js
index b26cfe398..998c9acc5 100644
--- a/ui/admin/tests/acceptance/roles/principals-test.js
+++ b/ui/admin/tests/acceptance/roles/principals-test.js
@@ -69,6 +69,16 @@ module('Acceptance | roles | principals', function (hooks) {
assert.equal(findAll('tbody tr').length, principalsCount - 1);
});
+ test('principal cannot be removed from a role without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.role.authorized_actions.filter(
+ (item) => item !== 'remove-principals'
+ );
+ instances.role.update({ authorized_actions });
+ await visit(urls.rolePrincipals);
+ assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
+ });
+
test('shows error message on principal remove', async function (assert) {
assert.expect(2);
this.server.post('/roles/:idMethod', () => {
@@ -89,6 +99,16 @@ module('Acceptance | roles | principals', function (hooks) {
assert.ok(find('[role="alert"]'));
});
+ test('cannot navigate to add principals without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.role.authorized_actions.filter(
+ (item) => item !== 'add-principals'
+ );
+ instances.role.update({ authorized_actions });
+ await visit(urls.rolePrincipals);
+ assert.notOk(find('.rose-layout-page-actions a'));
+ });
+
test('select and save principals to add', async function (assert) {
assert.expect(3);
instances.role.update({ userIds: [], groupIds: [] });
diff --git a/ui/admin/tests/acceptance/users/accounts-test.js b/ui/admin/tests/acceptance/users/accounts-test.js
index 8b7caaba6..fe556f84a 100644
--- a/ui/admin/tests/acceptance/users/accounts-test.js
+++ b/ui/admin/tests/acceptance/users/accounts-test.js
@@ -61,7 +61,7 @@ module('Acceptance | users | accounts', function (hooks) {
assert.equal(findAll('tbody tr').length, accountsCount);
});
- test('can remove a account', async function (assert) {
+ test('can remove an account', async function (assert) {
assert.expect(2);
await visit(urls.accounts);
assert.equal(findAll('tbody tr').length, accountsCount);
@@ -69,6 +69,16 @@ module('Acceptance | users | accounts', function (hooks) {
assert.equal(findAll('tbody tr').length, accountsCount - 1);
});
+ test('cannot remove an account without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.user.authorized_actions.filter(
+ (item) => item !== 'remove-accounts'
+ );
+ instances.user.update({ authorized_actions });
+ await visit(urls.accounts);
+ assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
+ });
+
test('shows error message on account remove', async function (assert) {
assert.expect(2);
this.server.post('/users/:idMethod', () => {
@@ -92,10 +102,27 @@ module('Acceptance | users | accounts', function (hooks) {
test('visiting account add accounts', async function (assert) {
assert.expect(1);
await visit(urls.addAccounts);
+ await visit(urls.addAccounts);
await a11yAudit();
assert.equal(currentURL(), urls.addAccounts);
});
+ test('can navigate to add accounts with proper authorization', async function (assert) {
+ assert.expect(1);
+ await visit(urls.accounts);
+ assert.ok(find(`[href="${urls.addAccounts}"]`));
+ });
+
+ test('cannot navigate to add accounts without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.user.authorized_actions.filter(
+ (item) => item !== 'add-accounts'
+ );
+ instances.user.update({ authorized_actions });
+ await visit(urls.accounts);
+ assert.notOk(find(`[href="${urls.addAccounts}"]`));
+ });
+
test('select and save accounts to add', async function (assert) {
assert.expect(3);
instances.user.update({ accountIds: [] });
diff --git a/ui/desktop/README.md b/ui/desktop/README.md
index ba9ca6e88..f80ab75d2 100644
--- a/ui/desktop/README.md
+++ b/ui/desktop/README.md
@@ -1,6 +1,6 @@
-# Client Connect UI
+# Desktop client UI
-The client UI for Boundary.
+The desktop client UI for Boundary.
@@ -31,7 +31,7 @@ You will need the following things properly installed on your computer.
## Installation
-See boundary-ui README for installation instructions.
+See [boundary-ui README](https://github.com/hashicorp/boundary-ui#installation) for installation instructions.
## Yarn Commands
@@ -39,24 +39,32 @@ List of available project commands. `yarn run `
| Command | Description |
| ------- | ----------- |
-| build:development | Builds the UI in development mode. |
| build | Builds the UI for production. |
+| build:development | Builds the UI in development mode. |
| build:desktop:debianOnMacOS | Builds debian based linux artifacts on MacOS. |
| lint | Runs all lint commands. |
+| lint:fix | Runs all automatic linting fixes. |
| lint:hbs | Lints `hbs` template files. |
+| lint:hbs:fix | Runs the automatic linting fix for `hbs` template files. |
| lint:js | Lints `js` files. |
+| lint:js:fix | Runs the automatic linting fix for `js` files. |
| lint:sass | Lints `scss` files. |
+| lint:electron | Runs a linter tool to identify misconfigurations and security anti-patterns in Electron. |
| format | Runs all auto-formatters. |
+| format:hbs | Auto-formats `hbs` files using Prettier. |
| format:js | Auto-formats `js` files using Prettier. |
| format:sass | Auto-formats `scss` files using Prettier. |
-| start | Runs the dummy app local server. |
+| start | Runs the dummy app local server as web app. |
| start:desktop | Runs the dummy app as an electron app. |
+| clean:coverage | Cleans coverage reporting directory. |
| test | Runs all tests in random order, with coverage reporting. |
+| test:ember | Runs ember tests in random order, with coverage reporting. |
| doc:toc | Automatically generates a table of contents for this README file. |
## Running / Development
+To run as web app:
* `yarn start`
* Visit your app at [http://localhost:4200](http://localhost:4200).
* Visit your tests at [http://localhost:4200/tests](http://localhost:4200/tests).
@@ -90,11 +98,12 @@ These environment variables may be used to customized the build.
| `BYPASS_CLI_SETUP` | Disable download and extraction of cli. For development use only. |
| `BYPASS_APP_UPDATER` | Disable app updater feature. For development use only. |
| `DISABLE_WINDOW_CHROME` | Disable window chrome. For internal use only. |
+| `ENABLE_MIRAGE` | Enable (`true`) or disable (`false`) mirage. Default value is `true`. |
### Building for Production
Before executing a build, be sure to set any environment variables necessary
-for your target [environment](#environment-variables). To build this UI for
+for your target [environment](#environment-variables). To build this UI for
production, run the following commands from this folder:
```bash
diff --git a/ui/desktop/package.json b/ui/desktop/package.json
index 2c30fa816..4f0dfb6ca 100755
--- a/ui/desktop/package.json
+++ b/ui/desktop/package.json
@@ -23,13 +23,13 @@
"lint:hbs": "ember-template-lint .",
"lint:hbs:fix": "ember-template-lint . --fix",
"lint:js": "eslint .",
+ "lint:js:fix": "eslint . --fix",
"lint:sass": "stylelint '**/*.scss'",
"lint:electron": "electronegativity -r -i ./electron-app",
"format": "npm-run-all format:*",
"format:hbs": "prettier --write 'app/**/*.hbs'",
"format:js": "prettier --write '{app,config,stories,tests,electron-app/src}/**/*.js' *.js",
"format:sass": "prettier --write app/**/*.scss",
- "lint:js:fix": "eslint . --fix",
"start": "ember serve",
"prestart:desktop": "cd electron-app && yarn premake",
"start:desktop": "ember electron",
diff --git a/yarn.lock b/yarn.lock
index 66274fcb4..a467a175c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -23,6 +23,13 @@
dependencies:
"@babel/highlight" "^7.14.5"
+"@babel/code-frame@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503"
+ integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==
+ dependencies:
+ "@babel/highlight" "^7.14.5"
+
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
@@ -92,6 +99,27 @@
semver "^6.3.0"
source-map "^0.5.0"
+"@babel/core@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
+ integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
+ dependencies:
+ "@babel/code-frame" "^7.15.8"
+ "@babel/generator" "^7.15.8"
+ "@babel/helper-compilation-targets" "^7.15.4"
+ "@babel/helper-module-transforms" "^7.15.8"
+ "@babel/helpers" "^7.15.4"
+ "@babel/parser" "^7.15.8"
+ "@babel/template" "^7.15.4"
+ "@babel/traverse" "^7.15.4"
+ "@babel/types" "^7.15.6"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.1.2"
+ semver "^6.3.0"
+ source-map "^0.5.0"
+
"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.15.0":
version "7.15.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15"
@@ -110,6 +138,15 @@
jsesc "^2.5.1"
source-map "^0.5.0"
+"@babel/generator@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1"
+ integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==
+ dependencies:
+ "@babel/types" "^7.15.6"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
"@babel/helper-annotate-as-pure@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61"
@@ -302,6 +339,20 @@
"@babel/traverse" "^7.15.4"
"@babel/types" "^7.15.4"
+"@babel/helper-module-transforms@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2"
+ integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.15.4"
+ "@babel/helper-replace-supers" "^7.15.4"
+ "@babel/helper-simple-access" "^7.15.4"
+ "@babel/helper-split-export-declaration" "^7.15.4"
+ "@babel/helper-validator-identifier" "^7.15.7"
+ "@babel/template" "^7.15.4"
+ "@babel/traverse" "^7.15.4"
+ "@babel/types" "^7.15.6"
+
"@babel/helper-optimise-call-expression@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c"
@@ -395,6 +446,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
+"@babel/helper-validator-identifier@^7.15.7":
+ version "7.15.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
+ integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
+
"@babel/helper-validator-option@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
@@ -447,6 +503,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549"
integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==
+"@babel/parser@^7.15.8":
+ version "7.15.8"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016"
+ integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==
+
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e"
@@ -1278,7 +1339,7 @@
"@babel/helper-validator-identifier" "^7.14.9"
to-fast-properties "^2.0.0"
-"@babel/types@^7.15.4":
+"@babel/types@^7.15.4", "@babel/types@^7.15.6":
version "7.15.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
@@ -2693,6 +2754,21 @@
global "^4.4.0"
regenerator-runtime "^0.13.7"
+"@storybook/addons@^6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.3.9.tgz#e12c8d4351b861d67cb6b8d64ed33b1f6b90994f"
+ integrity sha512-5tRkeHgdb/I/rp3GBkxonDLVsA45Vpgh/vFrsecrS/98wkSYfPEhqrDGLOosJHFrN3J2pznAuNFaA05158uBsw==
+ dependencies:
+ "@storybook/api" "6.3.9"
+ "@storybook/channels" "6.3.9"
+ "@storybook/client-logger" "6.3.9"
+ "@storybook/core-events" "6.3.9"
+ "@storybook/router" "6.3.9"
+ "@storybook/theming" "6.3.9"
+ core-js "^3.8.2"
+ global "^4.4.0"
+ regenerator-runtime "^0.13.7"
+
"@storybook/api@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.3.8.tgz#251bcf6cc3a4e0b908bea7fb0aa9e48d6c48d720"
@@ -2719,6 +2795,32 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
+"@storybook/api@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.3.9.tgz#f36c8f01cac602c67b8f22b144e8bd6478039abb"
+ integrity sha512-lwen3jcY4YbnD8spAZrmXcToed/pwad9QpxkG0GNf6ctcOumN6HIK93fKeJ0vvPYc3v/uq1qKeLyTZ3NrgHQRg==
+ dependencies:
+ "@reach/router" "^1.3.4"
+ "@storybook/channels" "6.3.9"
+ "@storybook/client-logger" "6.3.9"
+ "@storybook/core-events" "6.3.9"
+ "@storybook/csf" "0.0.1"
+ "@storybook/router" "6.3.9"
+ "@storybook/semver" "^7.3.2"
+ "@storybook/theming" "6.3.9"
+ "@types/reach__router" "^1.3.7"
+ core-js "^3.8.2"
+ fast-deep-equal "^3.1.3"
+ global "^4.4.0"
+ lodash "^4.17.20"
+ memoizerific "^1.11.3"
+ qs "^6.10.0"
+ regenerator-runtime "^0.13.7"
+ store2 "^2.12.0"
+ telejson "^5.3.2"
+ ts-dedent "^2.0.0"
+ util-deprecate "^1.0.2"
+
"@storybook/builder-webpack4@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.3.8.tgz#9ffe866fbd50a94b3cf3ecde1fe4d5f29dd337e8"
@@ -2817,6 +2919,15 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
+"@storybook/channels@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.3.9.tgz#40907734460fbcb08fe018c794890ffe668e873d"
+ integrity sha512-ZeHXLFJ43Wn6HJMiGgKUWUMtKcXDoWxL50Qr5Wwbsnmtp2BX7R8aak/Vw9TVT46J86QXkdI3CAKAEvb6esiLRQ==
+ dependencies:
+ core-js "^3.8.2"
+ ts-dedent "^2.0.0"
+ util-deprecate "^1.0.2"
+
"@storybook/client-api@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.3.8.tgz#60e608a5c2afbe6d63a4a063e616bedde8466584"
@@ -2849,6 +2960,14 @@
core-js "^3.8.2"
global "^4.4.0"
+"@storybook/client-logger@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.3.9.tgz#ef8c89e96f79927d46dd1dacddb58f3a43154b9a"
+ integrity sha512-oww+P062SaOQfsTphAQBL6xe5DCv78Po/f/ROk7iYGAbV8HcCCscpzyJSeLfus2CunFYS2ngPcllbvEnqWk7dQ==
+ dependencies:
+ core-js "^3.8.2"
+ global "^4.4.0"
+
"@storybook/components@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.3.8.tgz#cb84b0245d8784d41e7e6be25a0d5774363e5b87"
@@ -2963,6 +3082,13 @@
dependencies:
core-js "^3.8.2"
+"@storybook/core-events@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.3.9.tgz#17127905a2d7773b6e02f15bfbddb1fd1b0bce75"
+ integrity sha512-6ELOkroH0Oz7+OR1SqGMKAC1+ufituqSxDp08AyvrHPSYqK/db+P2kSCJBdqyUXTvt8lPvqlCOidkRhGrNB/+A==
+ dependencies:
+ core-js "^3.8.2"
+
"@storybook/core-server@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.3.8.tgz#0d141e6f315b735a442aebc0f424f911456c769c"
@@ -3143,6 +3269,22 @@
qs "^6.10.0"
ts-dedent "^2.0.0"
+"@storybook/router@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.3.9.tgz#a299091426349b9dc0bb8610773918712b453dc4"
+ integrity sha512-uXNrZS9tsZr6fStIv/MHQfy3xSsc7RLYWbY4wkgZH+y5K97RtuwXgtbx7uyEpsQwse1Z4PikKu/ejN46F0oPGQ==
+ dependencies:
+ "@reach/router" "^1.3.4"
+ "@storybook/client-logger" "6.3.9"
+ "@types/reach__router" "^1.3.7"
+ core-js "^3.8.2"
+ fast-deep-equal "^3.1.3"
+ global "^4.4.0"
+ lodash "^4.17.20"
+ memoizerific "^1.11.3"
+ qs "^6.10.0"
+ ts-dedent "^2.0.0"
+
"@storybook/semver@^7.3.2":
version "7.3.2"
resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0"
@@ -3185,6 +3327,24 @@
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
+"@storybook/theming@6.3.9":
+ version "6.3.9"
+ resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.3.9.tgz#8e4500dacd298a2ca6bf47b5729449688338283c"
+ integrity sha512-vyMSLvEXrTC4rnUdWLUNmBNeOdBCl0Nt3R6y/laY+LQZ9Ljz/poRTrIYTkmenYieq4N7787s9zHmxvym/ZvKtw==
+ dependencies:
+ "@emotion/core" "^10.1.1"
+ "@emotion/is-prop-valid" "^0.8.6"
+ "@emotion/styled" "^10.0.27"
+ "@storybook/client-logger" "6.3.9"
+ core-js "^3.8.2"
+ deep-object-diff "^1.1.0"
+ emotion-theming "^10.0.27"
+ global "^4.4.0"
+ memoizerific "^1.11.3"
+ polished "^4.0.5"
+ resolve-from "^5.0.0"
+ ts-dedent "^2.0.0"
+
"@storybook/ui@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.3.8.tgz#9fb71befbe76f06c478925610ce998c23260a3f3"
@@ -6333,15 +6493,15 @@ browserify-zlib@^0.2.0:
pako "~1.0.5"
browserslist@4.14.2, browserslist@^3.2.6, browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.5, browserslist@^4.16.6, browserslist@^4.16.7:
- version "4.17.1"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9"
- integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ==
+ version "4.17.3"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.3.tgz#2844cd6eebe14d12384b0122d217550160d2d624"
+ integrity sha512-59IqHJV5VGdcJZ+GZ2hU5n4Kv3YiASzW6Xk5g9tf5a/MAzGeFwgGWU39fVzNIOVcgB3+Gp+kiQu0HEfTVU/3VQ==
dependencies:
- caniuse-lite "^1.0.30001259"
- electron-to-chromium "^1.3.846"
+ caniuse-lite "^1.0.30001264"
+ electron-to-chromium "^1.3.857"
escalade "^3.1.1"
- nanocolors "^0.1.5"
- node-releases "^1.1.76"
+ node-releases "^1.1.77"
+ picocolors "^0.2.1"
bser@2.1.1:
version "2.1.1"
@@ -6675,10 +6835,10 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001259:
- version "1.0.30001259"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001259.tgz#ae21691d3da9c4be6144403ac40f71d9f6efd790"
- integrity sha512-V7mQTFhjITxuk9zBpI6nYsiTXhcPe05l+364nZjK7MFK/E7ibvYBSAXr4YcA6oPR8j3ZLM/LN+lUqUVAQEUZFg==
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001264:
+ version "1.0.30001265"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz#0613c9e6c922e422792e6fcefdf9a3afeee4f8c3"
+ integrity sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==
capture-exit@^2.0.0:
version "2.0.0"
@@ -8525,10 +8685,10 @@ electron-rebuild@^2.0.3:
tar "^6.0.5"
yargs "^16.0.0"
-electron-to-chromium@^1.3.846:
- version "1.3.846"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.846.tgz#a55fd59613dbcaed609e965e3e88f42b08c401d3"
- integrity sha512-2jtSwgyiRzybHRxrc2nKI+39wH3AwQgn+sogQ+q814gv8hIFwrcZbV07Ea9f8AmK0ufPVZUvvAG1uZJ+obV4Jw==
+electron-to-chromium@^1.3.857:
+ version "1.3.860"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.860.tgz#d612e54ed75fa524c12af8da3ad8121ebfe2802b"
+ integrity sha512-gWwGZ+Wv4Mou2SJRH6JQzhTPjL5f95SX7n6VkLTQ/Q/INsZLZNQ1vH2GlZjozKyvT0kkFuCmWTwIoCj+/hUDPw==
element-resize-detector@^1.2.2:
version "1.2.3"
@@ -15695,11 +15855,6 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
-nanocolors@^0.1.5:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.6.tgz#bc2350d3edfdbfadd7ac018c855ae7c13905a6ad"
- integrity sha512-2pvTw6vYRaBLGir2xR7MxaJtyWkrn+C53EpW8yPotG+pdAwBvt0Xwk4VJ6VHLY0aLthVZPvDfm9TdZvrvAm5UQ==
-
nanoid@3.1.20:
version "3.1.20"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
@@ -15923,10 +16078,10 @@ node-pre-gyp@^0.11.0:
semver "^5.3.0"
tar "^4"
-node-releases@^1.1.76:
- version "1.1.76"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e"
- integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA==
+node-releases@^1.1.77:
+ version "1.1.77"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e"
+ integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==
node-uuid@~1.4.7:
version "1.4.8"
@@ -17135,6 +17290,11 @@ pend@~1.2.0:
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
+picocolors@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+ integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
@@ -17918,6 +18078,15 @@ react-dom@16.14.0:
prop-types "^15.6.2"
scheduler "^0.19.1"
+react-dom@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
+ integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ scheduler "^0.20.2"
+
react-draggable@^4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
@@ -18066,6 +18235,14 @@ react@16.14.0:
object-assign "^4.1.1"
prop-types "^15.6.2"
+react@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
+ integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
read-cmd-shim@^1.0.1, read-cmd-shim@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
@@ -19100,6 +19277,14 @@ scheduler@^0.19.1:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+scheduler@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
schema-utils@2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"