Merge branch 'main' into chore-enhanced-user-info
This commit is contained in:
41 files changed
+731
-166
No files matched your search
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/account';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/group';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/host-set';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/role';
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/user';
|
||||
@@ -9,6 +9,7 @@ export default factory.extend({
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'set-password',
|
||||
],
|
||||
attributes() {
|
||||
switch (this.type) {
|
||||
|
||||
@@ -9,6 +9,8 @@ export default factory.extend({
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'add-members',
|
||||
'remove-members',
|
||||
],
|
||||
id: (i) => `group-${i}`,
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ export default factory.extend({
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'add-hosts',
|
||||
'remove-hosts',
|
||||
],
|
||||
id: (i) => `host-set-id-${i}`,
|
||||
});
|
||||
@@ -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: () => [
|
||||
|
||||
@@ -8,6 +8,8 @@ export default factory.extend({
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
'add-accounts',
|
||||
'remove-accounts',
|
||||
],
|
||||
id: (i) => `user-${i}`,
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
@@ -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,8 @@
|
||||
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.5",
|
||||
"babel-loader": "^8.2.2",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@ember/test-helpers": "^2.4.2",
|
||||
"@glimmer/component": "^1.0.4",
|
||||
@@ -47,6 +48,7 @@
|
||||
"@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",
|
||||
|
||||
@@ -1,39 +1,43 @@
|
||||
<Rose::Form
|
||||
@onSubmit={{fn this.createGrant @addGrant}}
|
||||
@cancel={{@cancel}}
|
||||
@disabled={{@model.isSaving}}
|
||||
as |form|
|
||||
>
|
||||
<Rose::List::KeyValue as |list|>
|
||||
{{! Add grant field (only one per form) }}
|
||||
<list.item as |item|>
|
||||
<form.input
|
||||
@contextual={{true}}
|
||||
@name='grant'
|
||||
@type='text'
|
||||
@value={{this.newGrantString}}
|
||||
as |input|
|
||||
>
|
||||
<item.key>
|
||||
<input.label>{{t 'resources.role.grant.actions.create'}}</input.label>
|
||||
</item.key>
|
||||
<item.cell>
|
||||
<input.field title={{t 'form.grant.help'}} />
|
||||
</item.cell>
|
||||
<item.cell>
|
||||
<Rose::Button
|
||||
@submit={{true}}
|
||||
@disabled={{this.cannotSave}}
|
||||
@style='secondary'
|
||||
title={{t 'actions.add'}}
|
||||
>
|
||||
{{t 'actions.add'}}
|
||||
</Rose::Button>
|
||||
</item.cell>
|
||||
</form.input>
|
||||
</list.item>
|
||||
</Rose::List::KeyValue>
|
||||
</Rose::Form>
|
||||
{{#if (can 'setGrants role' @model)}}
|
||||
<Rose::Form
|
||||
@onSubmit={{fn this.createGrant @addGrant}}
|
||||
@cancel={{@cancel}}
|
||||
@disabled={{@model.isSaving}}
|
||||
as |form|
|
||||
>
|
||||
<Rose::List::KeyValue as |list|>
|
||||
{{! Add grant field (only one per form) }}
|
||||
<list.item as |item|>
|
||||
<form.input
|
||||
@contextual={{true}}
|
||||
@name='grant'
|
||||
@type='text'
|
||||
@value={{this.newGrantString}}
|
||||
as |input|
|
||||
>
|
||||
<item.key>
|
||||
<input.label>{{t
|
||||
'resources.role.grant.actions.create'
|
||||
}}</input.label>
|
||||
</item.key>
|
||||
<item.cell>
|
||||
<input.field title={{t 'form.grant.help'}} />
|
||||
</item.cell>
|
||||
<item.cell>
|
||||
<Rose::Button
|
||||
@submit={{true}}
|
||||
@disabled={{this.cannotSave}}
|
||||
@style='secondary'
|
||||
title={{t 'actions.add'}}
|
||||
>
|
||||
{{t 'actions.add'}}
|
||||
</Rose::Button>
|
||||
</item.cell>
|
||||
</form.input>
|
||||
</list.item>
|
||||
</Rose::List::KeyValue>
|
||||
</Rose::Form>
|
||||
{{/if}}
|
||||
|
||||
<Rose::Form
|
||||
@onSubmit={{fn @submit this.grantStrings}}
|
||||
@@ -61,6 +65,7 @@
|
||||
@name='grant'
|
||||
@type='text'
|
||||
@value={{grant.value}}
|
||||
@disabled={{if (can 'setGrants role' @model) false true}}
|
||||
@error={{@model.errors.grant_strings}}
|
||||
as |input|
|
||||
>
|
||||
@@ -72,23 +77,27 @@
|
||||
</item.cell>
|
||||
</form.input>
|
||||
<item.cell>
|
||||
<Rose::Button
|
||||
@style='secondary'
|
||||
@iconOnly='flight-icons/svg/trash-16'
|
||||
title={{t 'actions.remove'}}
|
||||
{{on 'click' (fn @removeGrant grant.value)}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</Rose::Button>
|
||||
{{#if (can 'setGrants role' @model)}}
|
||||
<Rose::Button
|
||||
@style='secondary'
|
||||
@iconOnly='flight-icons/svg/trash-16'
|
||||
title={{t 'actions.remove'}}
|
||||
{{on 'click' (fn @removeGrant grant.value)}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</Rose::Button>
|
||||
{{/if}}
|
||||
</item.cell>
|
||||
</list.item>
|
||||
{{/each}}
|
||||
</Rose::List::KeyValue>
|
||||
|
||||
<form.actions
|
||||
@disabled={{if @model.cannotSave @model.cannotSave}}
|
||||
@submitText={{t 'actions.save'}}
|
||||
@cancelText={{t 'actions.cancel'}}
|
||||
/>
|
||||
{{#if (can 'setGrants role' @model)}}
|
||||
<form.actions
|
||||
@disabled={{if @model.cannotSave @model.cannotSave}}
|
||||
@submitText={{t 'actions.save'}}
|
||||
@cancelText={{t 'actions.cancel'}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
</Rose::Form>
|
||||
+7
-5
@@ -5,10 +5,12 @@
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
{{#if @model.isPassword}}
|
||||
<nav.link
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account.set-password'
|
||||
>
|
||||
{{t 'actions.set-password'}}
|
||||
</nav.link>
|
||||
{{#if (can 'setPassword account' @model)}}
|
||||
<nav.link
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.account.set-password'
|
||||
>
|
||||
{{t 'actions.set-password'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</Rose::Nav::Tabs>
|
||||
@@ -3,9 +3,11 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.link @route='scopes.scope.groups.group.add-members'>
|
||||
{{t 'resources.group.actions.add-members'}}
|
||||
</dropdown.link>
|
||||
{{#if (can 'addMembers group' @model)}}
|
||||
<dropdown.link @route='scopes.scope.groups.group.add-members'>
|
||||
{{t 'resources.group.actions.add-members'}}
|
||||
</dropdown.link>
|
||||
{{/if}}
|
||||
{{#if (can 'delete model' @model)}}
|
||||
<dropdown.separator />
|
||||
<dropdown.button
|
||||
|
||||
@@ -29,21 +29,26 @@
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on 'click' (route-action 'removeMember' @model.group member)}}
|
||||
{{#if (can 'removeMembers group' @model.group)}}
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on
|
||||
'click'
|
||||
(route-action 'removeMember' @model.group member)
|
||||
}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
{{/if}}
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
|
||||
+12
-10
@@ -3,16 +3,18 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.host-set.create-and-add-host'
|
||||
>
|
||||
{{t 'resources.host-set.actions.create-and-add-host'}}
|
||||
</dropdown.link>
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.host-set.add-hosts'
|
||||
>
|
||||
{{t 'resources.host-set.actions.add-hosts'}}
|
||||
</dropdown.link>
|
||||
{{#if (can 'addHosts hostSet' @model)}}
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.host-set.create-and-add-host'
|
||||
>
|
||||
{{t 'resources.host-set.actions.create-and-add-host'}}
|
||||
</dropdown.link>
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.host-set.add-hosts'
|
||||
>
|
||||
{{t 'resources.host-set.actions.add-hosts'}}
|
||||
</dropdown.link>
|
||||
{{/if}}
|
||||
{{#if (can 'delete model' @model)}}
|
||||
<dropdown.separator />
|
||||
<dropdown.button
|
||||
|
||||
+16
-14
@@ -36,21 +36,23 @@
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on 'click' (route-action 'removeHost' @model.hostSet host)}}
|
||||
{{#if (can 'removeHosts hostSet' @model.hostSet)}}
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on 'click' (route-action 'removeHost' @model.hostSet host)}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
{{/if}}
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.link @route='scopes.scope.roles.role.add-principals'>
|
||||
{{t 'resources.role.principal.actions.add-principals'}}
|
||||
</dropdown.link>
|
||||
{{#if (can 'addPrincipals role' @model)}}
|
||||
<dropdown.link @route='scopes.scope.roles.role.add-principals'>
|
||||
{{t 'resources.role.principal.actions.add-principals'}}
|
||||
</dropdown.link>
|
||||
{{/if}}
|
||||
{{#if (can 'delete model' @model)}}
|
||||
<dropdown.separator />
|
||||
<dropdown.button
|
||||
|
||||
@@ -33,21 +33,26 @@
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on 'click' (route-action 'removePrincipal' principal.model)}}
|
||||
{{#if (can 'removePrincipals role' @model.role)}}
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on
|
||||
'click'
|
||||
(route-action 'removePrincipal' principal.model)
|
||||
}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
{{/if}}
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.link @route='scopes.scope.users.user.add-accounts'>
|
||||
{{t 'resources.user.actions.add-accounts'}}
|
||||
</dropdown.link>
|
||||
{{#if (can 'addAccounts user' @model)}}
|
||||
<dropdown.link @route='scopes.scope.users.user.add-accounts'>
|
||||
{{t 'resources.user.actions.add-accounts'}}
|
||||
</dropdown.link>
|
||||
{{/if}}
|
||||
{{#if (can 'delete model' @model)}}
|
||||
<dropdown.separator />
|
||||
<dropdown.button
|
||||
|
||||
@@ -33,24 +33,26 @@
|
||||
</Copyable>
|
||||
</row.cell>
|
||||
<row.cell>
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on
|
||||
'click'
|
||||
(route-action 'removeAccount' @model.user account)
|
||||
}}
|
||||
{{#if (can 'removeAccounts user' @model.user)}}
|
||||
<Rose::Dropdown
|
||||
@icon='flight-icons/svg/more-horizontal-16'
|
||||
@iconOnly={{true}}
|
||||
@showCaret={{false}}
|
||||
@dropdownRight={{true}}
|
||||
@text='{{t 'actions.manage'}}'
|
||||
as |dropdown|
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
<dropdown.button
|
||||
@style='danger'
|
||||
{{on
|
||||
'click'
|
||||
(route-action 'removeAccount' @model.user account)
|
||||
}}
|
||||
>
|
||||
{{t 'actions.remove'}}
|
||||
</dropdown.button>
|
||||
</Rose::Dropdown>
|
||||
{{/if}}
|
||||
</row.cell>
|
||||
</body.row>
|
||||
{{/each}}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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: [] });
|
||||
|
||||
@@ -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: [] });
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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: [] });
|
||||
|
||||
@@ -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: [] });
|
||||
|
||||
+15
-6
@@ -1,6 +1,6 @@
|
||||
# Client Connect UI
|
||||
# Desktop client UI
|
||||
|
||||
The client UI for Boundary.
|
||||
The desktop client UI for Boundary.
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
@@ -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-name>`
|
||||
|
||||
| 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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -2693,6 +2693,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 +2734,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 +2858,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 +2899,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 +3021,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 +3208,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 +3266,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,14 +6432,14 @@ 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.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.2.tgz#aa15dbd2fab399a399fe4df601bb09363c5458a6"
|
||||
integrity sha512-jSDZyqJmkKMEMi7SZAgX5UltFdR5NAO43vY0AwTpu4X3sGH7GLLQ83KiUomgrnvZRCeW0yPPnKqnxPqQOER9zQ==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001259"
|
||||
electron-to-chromium "^1.3.846"
|
||||
caniuse-lite "^1.0.30001261"
|
||||
electron-to-chromium "^1.3.854"
|
||||
escalade "^3.1.1"
|
||||
nanocolors "^0.1.5"
|
||||
nanocolors "^0.2.12"
|
||||
node-releases "^1.1.76"
|
||||
|
||||
bser@2.1.1:
|
||||
@@ -6675,10 +6774,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.30001261:
|
||||
version "1.0.30001263"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001263.tgz#7ce7a6fb482a137585cbc908aaf38e90c53a16a4"
|
||||
integrity sha512-doiV5dft6yzWO1WwU19kt8Qz8R0/8DgEziz6/9n2FxUasteZNwNNYSmJO3GLBH8lCVE73AB1RPDPAeYbcO5Cvw==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -7954,7 +8053,7 @@ debug@^3.0.0, debug@^3.0.1, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debuglog@^1.0.1:
|
||||
debuglog@*, debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
|
||||
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
|
||||
@@ -8525,10 +8624,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.854:
|
||||
version "1.3.856"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.856.tgz#75dee0eef9702bffabbf4c1293c989cd3cacb7ba"
|
||||
integrity sha512-lSezYIe1/p5qkEswAfaQUseOBiwGwuCvRl/MKzOEVe++DcmQ92+43dznDl4rFJ4Zpu+kevhwyIf7KjJevyDA/A==
|
||||
|
||||
element-resize-detector@^1.2.2:
|
||||
version "1.2.3"
|
||||
@@ -12734,7 +12833,7 @@ import-lazy@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
|
||||
integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
imurmurhash@*, imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
@@ -14431,6 +14530,11 @@ lodash._baseflatten@^3.0.0:
|
||||
lodash.isarguments "^3.0.0"
|
||||
lodash.isarray "^3.0.0"
|
||||
|
||||
lodash._baseindexof@*:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
|
||||
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
|
||||
|
||||
lodash._baseuniq@~4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
|
||||
@@ -14439,11 +14543,16 @@ lodash._baseuniq@~4.6.0:
|
||||
lodash._createset "~4.0.0"
|
||||
lodash._root "~3.0.0"
|
||||
|
||||
lodash._bindcallback@^3.0.0:
|
||||
lodash._bindcallback@*, lodash._bindcallback@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
|
||||
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
|
||||
|
||||
lodash._cacheindexof@*:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
|
||||
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
|
||||
|
||||
lodash._createassigner@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11"
|
||||
@@ -14453,12 +14562,19 @@ lodash._createassigner@^3.0.0:
|
||||
lodash._isiterateecall "^3.0.0"
|
||||
lodash.restparam "^3.0.0"
|
||||
|
||||
lodash._createcache@*:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
|
||||
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
|
||||
lodash._createset@~4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
|
||||
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
|
||||
|
||||
lodash._getnative@^3.0.0:
|
||||
lodash._getnative@*, lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
|
||||
@@ -14676,7 +14792,7 @@ lodash.pick@^4.4.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
|
||||
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
|
||||
|
||||
lodash.restparam@^3.0.0:
|
||||
lodash.restparam@*, lodash.restparam@^3.0.0:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
|
||||
@@ -15695,10 +15811,10 @@ 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==
|
||||
nanocolors@^0.2.12:
|
||||
version "0.2.12"
|
||||
resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777"
|
||||
integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug==
|
||||
|
||||
nanoid@3.1.20:
|
||||
version "3.1.20"
|
||||
|
||||
Reference in new issue
Block a user