mirror of https://github.com/status-im/consul.git
ui: Implement ACLs access based on ACLs (#9835)
Adds restrictions to everything within the ACLs (and nspaces) area based on your ACLs (including readonly views etc.)
This commit is contained in:
parent
6fe45c075f
commit
fa6687b7f4
|
@ -1,9 +1,6 @@
|
||||||
import BaseAbility from './base';
|
import BaseAbility from './base';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
// ACL ability covers all of the ACL things, like tokens, policies, roles and
|
|
||||||
// auth methods and this therefore should not be deleted once we remove the on
|
|
||||||
// legacy ACLs related classes
|
|
||||||
export default class ACLAbility extends BaseAbility {
|
export default class ACLAbility extends BaseAbility {
|
||||||
@service('env') env;
|
@service('env') env;
|
||||||
|
|
||||||
|
@ -13,4 +10,10 @@ export default class ACLAbility extends BaseAbility {
|
||||||
get canRead() {
|
get canRead() {
|
||||||
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
||||||
}
|
}
|
||||||
|
get canDuplicate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canWrite;
|
||||||
|
}
|
||||||
|
get canDelete() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && this.item.ID !== 'anonymous' && super.canWrite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import BaseAbility from './base';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
|
export default class AuthMethodAbility extends BaseAbility {
|
||||||
|
@service('env') env;
|
||||||
|
|
||||||
|
resource = 'acl';
|
||||||
|
segmented = false;
|
||||||
|
|
||||||
|
get canRead() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canCreate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canDelete() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canDelete;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,10 @@ export default class NspaceAbility extends BaseAbility {
|
||||||
return this.canCreate;
|
return this.canCreate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get canDelete() {
|
||||||
|
return this.item.Name !== 'default' && super.canDelete;
|
||||||
|
}
|
||||||
|
|
||||||
get canChoose() {
|
get canChoose() {
|
||||||
return this.env.var('CONSUL_NSPACES_ENABLED') && this.nspaces.length > 0;
|
return this.env.var('CONSUL_NSPACES_ENABLED') && this.nspaces.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import BaseAbility from './base';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { typeOf } from 'consul-ui/helpers/policy/typeof';
|
||||||
|
|
||||||
|
export default class PolicyAbility extends BaseAbility {
|
||||||
|
@service('env') env;
|
||||||
|
|
||||||
|
resource = 'acl';
|
||||||
|
segmented = false;
|
||||||
|
|
||||||
|
get canRead() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canWrite() {
|
||||||
|
return (
|
||||||
|
this.env.var('CONSUL_ACLS_ENABLED') &&
|
||||||
|
(typeof this.item === 'undefined' || typeOf([this.item]) !== 'policy-management') &&
|
||||||
|
super.canRead
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get canCreate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canDelete() {
|
||||||
|
return (
|
||||||
|
this.env.var('CONSUL_ACLS_ENABLED') &&
|
||||||
|
(typeof this.item === 'undefined' || typeOf([this.item]) !== 'policy-management') &&
|
||||||
|
super.canDelete
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import BaseAbility from './base';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
|
export default class RoleAbility extends BaseAbility {
|
||||||
|
@service('env') env;
|
||||||
|
|
||||||
|
resource = 'acl';
|
||||||
|
segmented = false;
|
||||||
|
|
||||||
|
get canRead() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canCreate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canDelete() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canDelete;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import BaseAbility from './base';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
|
import { isLegacy } from 'consul-ui/helpers/token/is-legacy';
|
||||||
|
import { isAnonymous } from 'consul-ui/helpers/token/is-anonymous';
|
||||||
|
|
||||||
|
export default class TokenAbility extends BaseAbility {
|
||||||
|
@service('env') env;
|
||||||
|
|
||||||
|
resource = 'acl';
|
||||||
|
segmented = false;
|
||||||
|
|
||||||
|
get canRead() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canCreate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && super.canCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canDelete() {
|
||||||
|
return (
|
||||||
|
this.env.var('CONSUL_ACLS_ENABLED') &&
|
||||||
|
!isAnonymous([this.item]) &&
|
||||||
|
this.item.AccessorID !== this.token.AccessorID &&
|
||||||
|
super.canDelete
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get canDuplicate() {
|
||||||
|
return this.env.var('CONSUL_ACLS_ENABLED') && !isLegacy([this.item]) && super.canWrite;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
{{#if (not disabled)}}
|
||||||
<YieldSlot @name="create">{{yield}}</YieldSlot>
|
<YieldSlot @name="create">{{yield}}</YieldSlot>
|
||||||
<label class="type-text">
|
<label class="type-text">
|
||||||
<span><YieldSlot @name="label">{{yield}}</YieldSlot></span>
|
<span><YieldSlot @name="label">{{yield}}</YieldSlot></span>
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
</PowerSelect>
|
</PowerSelect>
|
||||||
</DataCollection>
|
</DataCollection>
|
||||||
</label>
|
</label>
|
||||||
|
{{/if}}
|
||||||
{{#if (gt items.length 0)}}
|
{{#if (gt items.length 0)}}
|
||||||
<YieldSlot @name="set">{{yield}}</YieldSlot>
|
<YieldSlot @name="set">{{yield}}</YieldSlot>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -29,7 +29,13 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||||
<li role="none">
|
<li role="none">
|
||||||
<a data-test-edit role="menuitem" tabindex="-1" href={{href-to 'dc.acls.edit' item.ID}}>Edit</a>
|
<a data-test-edit role="menuitem" tabindex="-1" href={{href-to 'dc.acls.edit' item.ID}}>
|
||||||
|
{{#if (can "write acl" item=item)}}
|
||||||
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{{#if (eq item.ID token.SecretID) }}
|
{{#if (eq item.ID token.SecretID) }}
|
||||||
<li role="none">
|
<li role="none">
|
||||||
|
@ -87,10 +93,12 @@
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if (can "duplicate acl" item=item)}}
|
||||||
<li role="none">
|
<li role="none">
|
||||||
<button role="menuitem" tabindex="-1" type="button" data-test-clone {{action @onclone item}}>Duplicate</button>
|
<button role="menuitem" tabindex="-1" type="button" data-test-clone {{action @onclone item}}>Duplicate</button>
|
||||||
</li>
|
</li>
|
||||||
{{# if (not-eq item.ID 'anonymous') }}
|
{{/if}}
|
||||||
|
{{#if (can "delete acl" item=item)}}
|
||||||
<li role="none" class="dangerous">
|
<li role="none" class="dangerous">
|
||||||
<label for={{concat confirm 'delete'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
<label for={{concat confirm 'delete'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
||||||
<div role="menu">
|
<div role="menu">
|
||||||
|
|
|
@ -29,10 +29,14 @@ as |item|>
|
||||||
<Actions as |Action|>
|
<Actions as |Action|>
|
||||||
<Action data-test-edit-action @href={{href-to 'dc.nspaces.edit' item.Name}}>
|
<Action data-test-edit-action @href={{href-to 'dc.nspaces.edit' item.Name}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
|
{{#if (can "write nspace" item=item)}}
|
||||||
Edit
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{#if (not-eq item.Name 'default') }}
|
{{#if (can "delete nspace" item=item)}}
|
||||||
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
|
|
|
@ -35,14 +35,14 @@ as |item|>
|
||||||
<Actions as |Action|>
|
<Actions as |Action|>
|
||||||
<Action data-test-edit-action @href={{href-to 'dc.acls.policies.edit' item.ID}}>
|
<Action data-test-edit-action @href={{href-to 'dc.acls.policies.edit' item.ID}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
{{#if (can "write policy" item=item)}}
|
||||||
View
|
|
||||||
{{else}}
|
|
||||||
Edit
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{#if (not-eq (policy/typeof item) 'policy-management')}}
|
{{#if (can "delete policy" item=item)}}
|
||||||
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
|
|
|
@ -19,9 +19,14 @@ as |item|>
|
||||||
<Actions as |Action|>
|
<Actions as |Action|>
|
||||||
<Action data-test-edit-action @href={{href-to 'dc.acls.roles.edit' item.ID}}>
|
<Action data-test-edit-action @href={{href-to 'dc.acls.roles.edit' item.ID}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
|
{{#if (can "write role" item=item)}}
|
||||||
Edit
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
|
{{#if (can "delete role" item=item)}}
|
||||||
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
|
@ -42,6 +47,7 @@ as |item|>
|
||||||
</Confirmation>
|
</Confirmation>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
|
{{/if}}
|
||||||
</Actions>
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
|
@ -30,19 +30,25 @@ as |item|>
|
||||||
</dl>
|
</dl>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="actions" as |Actions|>
|
<BlockSlot @name="actions" as |Actions|>
|
||||||
|
|
||||||
<Actions as |Action|>
|
<Actions as |Action|>
|
||||||
<Action data-test-edit-action @href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>
|
<Action data-test-edit-action @href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
|
{{#if (can "write token" item=item)}}
|
||||||
Edit
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{#if (not (token/is-legacy item))}}
|
{{#if (can "duplicate token" item=item)}}
|
||||||
<Action data-test-clone-action @onclick={{action @onclone item}}>
|
<Action data-test-clone-action @onclick={{action @onclone item}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Duplicate
|
Duplicate
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||||
<Action data-test-logout-action class="dangerous" @onclick={{action @onlogout item}}>
|
<Action data-test-logout-action class="dangerous" @onclick={{action @onlogout item}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
|
@ -86,7 +92,9 @@ as |item|>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (not (or (token/is-anonymous item) (eq item.AccessorID @token.AccessorID)))}}
|
|
||||||
|
|
||||||
|
{{#if (can "delete token" item=item token=@token)}}
|
||||||
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
|
@ -107,7 +115,8 @@ as |item|>
|
||||||
</Confirmation>
|
</Confirmation>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</Actions>
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
|
@ -1,5 +1,8 @@
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<fieldset ...attributes>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write policy" item=item)) "disabled"}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
{{#yield-slot name='template'}}
|
{{#yield-slot name='template'}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<header>
|
<header>
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
<ChildSelector ...attributes @repo={{repo}} @dc={{dc}} @nspace={{nspace}} @type="policy" @placeholder="Search for policy" @items={{items}}>
|
<ChildSelector
|
||||||
|
@disabled={{disabled}}
|
||||||
|
@repo={{repo}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace={{nspace}}
|
||||||
|
@type="policy"
|
||||||
|
@placeholder="Search for policy"
|
||||||
|
@items={{items}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Apply an existing policy
|
Apply an existing policy
|
||||||
|
@ -112,6 +121,7 @@
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
|
{{#if (not disabled)}}
|
||||||
<div>
|
<div>
|
||||||
<ConfirmationDialog @message="Are you sure you want to remove this policy from this token?">
|
<ConfirmationDialog @message="Are you sure you want to remove this policy from this token?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
|
@ -127,6 +137,7 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</TabularDetails>
|
</TabularDetails>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<fieldset class="role-form" data-test-role-form>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write role" item=item)) "disabled"}}
|
||||||
|
class="role-form"
|
||||||
|
data-test-role-form
|
||||||
|
>
|
||||||
<label class="type-text{{if item.error.Name ' has-error'}}">
|
<label class="type-text{{if item.error.Name ' has-error'}}">
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<input type="text" value={{item.Name}} name="role[Name]" autofocus="autofocus" oninput={{action 'change'}} />
|
<input type="text" value={{item.Name}} name="role[Name]" autofocus="autofocus" oninput={{action 'change'}} />
|
||||||
|
@ -21,6 +25,11 @@
|
||||||
{{#yield-slot name='policy' params=(block-params item)}}
|
{{#yield-slot name='policy' params=(block-params item)}}
|
||||||
{{yield}}
|
{{yield}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<PolicySelector @dc={{dc}} @nspace={{nspace}} @items={{item.Policies}} />
|
<PolicySelector
|
||||||
|
@disabled={{not (can "write role" item=item)}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace={{nspace}}
|
||||||
|
@items={{item.Policies}}
|
||||||
|
/>
|
||||||
{{/yield-slot}}
|
{{/yield-slot}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -59,7 +59,7 @@ as |modal|>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
|
|
||||||
<ChildSelector @repo={{repo}} @dc={{dc}} @nspace={{nspace}} @type="role" @placeholder="Search for role" @items={{items}}>
|
<ChildSelector @disabled={{disabled}} @repo={{repo}} @dc={{dc}} @nspace={{nspace}} @type="role" @placeholder="Search for role" @items={{items}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Apply an existing role
|
Apply an existing role
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -70,7 +70,6 @@ as |modal|>
|
||||||
>
|
>
|
||||||
<span>Create new role</span>
|
<span>Create new role</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="option" as |option|>
|
<BlockSlot @name="option" as |option|>
|
||||||
{{option.Name}}
|
{{option.Name}}
|
||||||
|
@ -100,8 +99,15 @@ as |modal|>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||||
<li role="none">
|
<li role="none">
|
||||||
<a role="menuitem" tabindex="-1" href={{href-to 'dc.acls.roles.edit' item.ID}}>Edit</a>
|
<a role="menuitem" tabindex="-1" href={{href-to 'dc.acls.roles.edit' item.ID}}>
|
||||||
|
{{#if (can "edit role" item=item)}}
|
||||||
|
Edit
|
||||||
|
{{else}}
|
||||||
|
View
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{{#if (not disabled)}}
|
||||||
<li role="none" class="dangerous">
|
<li role="none" class="dangerous">
|
||||||
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Remove</label>
|
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Remove</label>
|
||||||
<div role="menu">
|
<div role="menu">
|
||||||
|
@ -125,6 +131,7 @@ as |modal|>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverMenu>
|
</PopoverMenu>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -128,42 +128,69 @@ export const routes = {
|
||||||
},
|
},
|
||||||
// ACLs
|
// ACLs
|
||||||
acls: {
|
acls: {
|
||||||
_options: { path: '/acls' },
|
_options: {
|
||||||
|
path: '/acls',
|
||||||
|
abilities: ['read acls'],
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
_options: { path: '/:id' },
|
_options: { path: '/:id' },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
_options: { path: '/create' },
|
_options: {
|
||||||
|
path: '/create',
|
||||||
|
abilities: ['create acls'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
policies: {
|
policies: {
|
||||||
_options: { path: '/policies' },
|
_options: {
|
||||||
|
path: '/policies',
|
||||||
|
abilities: ['read policies'],
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
_options: { path: '/:id' },
|
_options: { path: '/:id' },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
_options: { path: '/create' },
|
_options: {
|
||||||
|
path: '/create',
|
||||||
|
abilities: ['create policies'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
roles: {
|
roles: {
|
||||||
_options: { path: '/roles' },
|
_options: {
|
||||||
|
path: '/roles',
|
||||||
|
abilities: ['read roles'],
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
_options: { path: '/:id' },
|
_options: { path: '/:id' },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
_options: { path: '/create' },
|
_options: {
|
||||||
|
path: '/create',
|
||||||
|
abilities: ['create roles'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
_options: { path: '/tokens' },
|
_options: {
|
||||||
|
path: '/tokens',
|
||||||
|
abilities: ['read tokens'],
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
_options: { path: '/:id' },
|
_options: { path: '/:id' },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
_options: { path: '/create' },
|
_options: {
|
||||||
|
path: '/create',
|
||||||
|
abilities: ['create tokens'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'auth-methods': {
|
'auth-methods': {
|
||||||
_options: { path: '/auth-methods' },
|
_options: {
|
||||||
|
path: '/auth-methods',
|
||||||
|
abilities: ['read auth-methods'],
|
||||||
|
},
|
||||||
show: {
|
show: {
|
||||||
_options: { path: '/show' },
|
_options: { path: '/show' },
|
||||||
},
|
},
|
||||||
|
@ -185,12 +212,18 @@ export const routes = {
|
||||||
};
|
};
|
||||||
if (env('CONSUL_NSPACES_ENABLED')) {
|
if (env('CONSUL_NSPACES_ENABLED')) {
|
||||||
routes.dc.nspaces = {
|
routes.dc.nspaces = {
|
||||||
_options: { path: '/namespaces' },
|
_options: {
|
||||||
|
path: '/namespaces',
|
||||||
|
abilities: ['read nspaces'],
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
_options: { path: '/:name' },
|
_options: { path: '/:name' },
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
_options: { path: '/create' },
|
_options: {
|
||||||
|
path: '/create',
|
||||||
|
abilities: ['create nspaces'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
routes.nspace = {
|
routes.nspace = {
|
||||||
|
|
|
@ -4,12 +4,10 @@ import CreatingRoute from 'consul-ui/mixins/creating-route';
|
||||||
export default class CreateRoute extends Route.extend(CreatingRoute) {
|
export default class CreateRoute extends Route.extend(CreatingRoute) {
|
||||||
templateName = 'dc/nspaces/edit';
|
templateName = 'dc/nspaces/edit';
|
||||||
|
|
||||||
beforeModel() {
|
async beforeModel() {
|
||||||
|
// TODO: Update nspace CRUD to use Data components
|
||||||
// we need to skip CreatingRoute.beforeModel here
|
// we need to skip CreatingRoute.beforeModel here
|
||||||
// TODO(octane): ideally we'd like to call Route.beforeModel
|
// but still call Route.beforeModel
|
||||||
// but its not clear how to do that with old ember
|
return Route.prototype.beforeModel.apply(this, arguments);
|
||||||
// maybe it will be more normal with modern ember
|
|
||||||
// up until now we haven't been calling super here anyway
|
|
||||||
// so this is probably ok until we can skip a parent super
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,19 @@ export default class BaseRoute extends Route {
|
||||||
* Inspects a custom `abilities` array on the router for this route. Every
|
* Inspects a custom `abilities` array on the router for this route. Every
|
||||||
* abililty needs to 'pass' for the route not to throw a 403 error. Anything
|
* abililty needs to 'pass' for the route not to throw a 403 error. Anything
|
||||||
* more complex then this (say ORs) should use a single ability and perform
|
* more complex then this (say ORs) should use a single ability and perform
|
||||||
* the OR lgic in the test for the ability. Note, this ability check happens
|
* the OR logic in the test for the ability. Note, this ability check happens
|
||||||
* before any calls to the backend for this model/route.
|
* before any calls to the backend for this model/route.
|
||||||
*/
|
*/
|
||||||
async beforeModel() {
|
async beforeModel() {
|
||||||
const abilities = get(routes, `${this.routeName}._options.abilities`) || [];
|
// remove any references to index as it is the same as the root routeName
|
||||||
|
const routeName = this.routeName
|
||||||
|
.split('.')
|
||||||
|
.filter(item => item !== 'index')
|
||||||
|
.join('.');
|
||||||
|
const abilities = get(routes, `${routeName}._options.abilities`) || [];
|
||||||
if (abilities.length > 0) {
|
if (abilities.length > 0) {
|
||||||
if (!abilities.every(ability => this.permissions.can(ability))) {
|
if (!abilities.every(ability => this.permissions.can(ability))) {
|
||||||
throw new HTTPError(403);
|
throw new HTTPError('403');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@ const REQUIRED_PERMISSIONS = [
|
||||||
Resource: 'operator',
|
Resource: 'operator',
|
||||||
Access: 'write',
|
Access: 'write',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Resource: 'operator',
|
||||||
|
Access: 'read',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Resource: 'service',
|
Resource: 'service',
|
||||||
Access: 'read',
|
Access: 'read',
|
||||||
|
|
|
@ -70,6 +70,9 @@ html[data-route$='create'] main,
|
||||||
html[data-route$='edit'] main {
|
html[data-route$='edit'] main {
|
||||||
@extend %content-container-restricted;
|
@extend %content-container-restricted;
|
||||||
}
|
}
|
||||||
|
html:not([data-route$='index']):not([data-route$='instances']) main {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
@media #{$--lt-spacious-page-header} {
|
@media #{$--lt-spacious-page-header} {
|
||||||
.actions button.copy-btn {
|
.actions button.copy-btn {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<form>
|
<form>
|
||||||
<fieldset>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write acl" item=item)) "disabled"}}
|
||||||
|
>
|
||||||
<label class="type-text{{if item.error.Name ' has-error'}}">
|
<label class="type-text{{if item.error.Name ' has-error'}}">
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<Input @value={{item.Name}} @name="name" @autofocus="autofocus" />
|
<Input @value={{item.Name}} @name="name" @autofocus="autofocus" />
|
||||||
|
@ -25,12 +27,16 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div>
|
<div>
|
||||||
{{#if create }}
|
{{#if (and create (can "create acls")) }}
|
||||||
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
||||||
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>{{else}}<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>
|
||||||
|
{{else}}
|
||||||
|
{{#if (can "write acl" item=item)}}
|
||||||
|
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
||||||
{{# if (and (not create) (not-eq item.ID 'anonymous')) }}
|
{{# if (and (not create) (can "delete acl" item=item) ) }}
|
||||||
<ConfirmationDialog @message="Are you sure you want to delete this ACL token?">
|
<ConfirmationDialog @message="Are you sure you want to delete this ACL token?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item parent}}>Delete</button>
|
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item parent}}>Delete</button>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<CopyButton @value={{item.ID}} @name="token ID">
|
<CopyButton @value={{item.ID}} @name="token ID">
|
||||||
Copy token ID
|
Copy token ID
|
||||||
</CopyButton>
|
</CopyButton>
|
||||||
|
{{#if (can "duplicate acl" item=item)}}
|
||||||
<button type="button" {{ action "clone" item }}>Clone token</button>
|
<button type="button" {{ action "clone" item }}>Clone token</button>
|
||||||
<ConfirmationDialog @message="Are you sure you want to use this ACL token?">
|
<ConfirmationDialog @message="Are you sure you want to use this ACL token?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
<button type="button" class="type-cancel" {{action cancel}}>Cancel</button>
|
<button type="button" class="type-cancel" {{action cancel}}>Cancel</button>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="content">
|
<BlockSlot @name="content">
|
||||||
|
|
|
@ -32,7 +32,9 @@ as |sort filters items|}}
|
||||||
<label for="toolbar-toggle"></label>
|
<label for="toolbar-toggle"></label>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="actions">
|
<BlockSlot @name="actions">
|
||||||
|
{{#if (can "create acls")}}
|
||||||
<a data-test-create href="{{href-to 'dc.acls.create'}}" class="type-create">Create</a>
|
<a data-test-create href="{{href-to 'dc.acls.create'}}" class="type-create">Create</a>
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="toolbar">
|
<BlockSlot @name="toolbar">
|
||||||
{{#if (gt items.length 0) }}
|
{{#if (gt items.length 0) }}
|
||||||
|
|
|
@ -7,14 +7,16 @@
|
||||||
<TokenList @caption="Applied to the following tokens:" @items={{items}} />
|
<TokenList @caption="Applied to the following tokens:" @items={{items}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div>
|
<div>
|
||||||
{{#if create }}
|
{{#if (and create (can "create tokens")) }}
|
||||||
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
||||||
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>
|
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
{{#if (can "write policy" item=item)}}
|
||||||
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
||||||
{{# if (not create) }}
|
{{# if (and (not create) (can "delete policy" item=item) ) }}
|
||||||
<ConfirmationDialog @message="Are you sure you want to delete this Policy?">
|
<ConfirmationDialog @message="Are you sure you want to delete this Policy?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
{{#if create }}
|
{{#if create }}
|
||||||
New Policy
|
New Policy
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
{{#if (can "write policy" item=item)}}
|
||||||
View Policy
|
|
||||||
{{else}}
|
|
||||||
Edit Policy
|
Edit Policy
|
||||||
|
{{else}}
|
||||||
|
View Policy
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
<TokenList @caption="Tokens" @items={{items}} />
|
<TokenList @caption="Tokens" @items={{items}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div>
|
<div>
|
||||||
{{#if create }}
|
{{#if (and create (can "create roles")) }}
|
||||||
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
{{! we only need to check for an empty name here as ember munges autofocus, once we have autofocus back revisit this}}
|
||||||
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>
|
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid (eq item.Name '')) 'disabled'}}>Save</button>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
{{#if (can "write role" item=item)}}
|
||||||
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
||||||
{{# if (not create) }}
|
{{# if (and (not create) (can "delete role" item=item) ) }}
|
||||||
<ConfirmationDialog @message="Are you sure you want to delete this Role?">
|
<ConfirmationDialog @message="Are you sure you want to delete this Role?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<fieldset>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write token" item=item)) "disabled"}}
|
||||||
|
>
|
||||||
<label class="type-text{{if item.error.Name ' has-error'}}">
|
<label class="type-text{{if item.error.Name ' has-error'}}">
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<Input @value={{item.Description}} @name="name" @autofocus="autofocus" />
|
<Input @value={{item.Description}} @name="name" @autofocus="autofocus" />
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<fieldset>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write token" item=item)) "disabled"}}
|
||||||
|
>
|
||||||
{{#if create }}
|
{{#if create }}
|
||||||
<div class="type-toggle">
|
<div class="type-toggle">
|
||||||
<label>
|
<label>
|
||||||
|
@ -15,9 +17,19 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset id="roles">
|
<fieldset id="roles">
|
||||||
<h2>Roles</h2>
|
<h2>Roles</h2>
|
||||||
<RoleSelector @dc={{dc}} @nspace={{nspace}} @items={{item.Roles}} />
|
<RoleSelector
|
||||||
|
@disabled={{not (can "write token" item=item)}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace={{nspace}}
|
||||||
|
@items={{item.Roles}}
|
||||||
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset id="policies">
|
<fieldset id="policies">
|
||||||
<h2>Policies</h2>
|
<h2>Policies</h2>
|
||||||
<PolicySelector @dc={{dc}} @nspace={{nspace}} @items={{item.Policies}} />
|
<PolicySelector
|
||||||
|
@disabled={{not (can "write token" item=item)}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace={{nspace}}
|
||||||
|
@items={{item.Policies}}
|
||||||
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -6,14 +6,17 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{!TODO: Make this into a slotted component}}
|
{{!TODO: Make this into a slotted component}}
|
||||||
<div>
|
<div>
|
||||||
{{#if create }}
|
{{#if (and create (can "create tokens")) }}
|
||||||
{{! new tokens can be saved without you filling anything in, old tokens remain using isPristine }}
|
{{! new tokens can be saved without you filling anything in, old tokens remain using isPristine }}
|
||||||
<button type="submit" {{ action "create" item}} disabled={{if (or (and (token/is-legacy item) item.isPristine) item.isInvalid) 'disabled'}}>Save</button>
|
<button type="submit" {{ action "create" item}} disabled={{if (or (and (token/is-legacy item) item.isPristine) item.isInvalid) 'disabled'}}>Save</button>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
|
{{#if (can "write token" item=item)}}
|
||||||
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
||||||
{{# if (and (not create) (not (token/is-anonymous item)) (not-eq item.AccessorID token.AccessorID) ) }}
|
{{# if (and (not create) (can "delete token" item=item token=token) ) }}
|
||||||
<ConfirmationDialog @message="Are you sure you want to delete this Token?">
|
<ConfirmationDialog @message="Are you sure you want to delete this Token?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
<button type="button" data-test-delete class="type-delete" {{action confirm 'delete' item}}>Delete</button>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (not (token/is-legacy item))}}
|
{{#if (can "duplicate token" item=item)}}
|
||||||
<button data-test-clone type="button" {{ action "clone" item }}>Duplicate</button>
|
<button data-test-clone type="button" {{ action "clone" item }}>Duplicate</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -48,7 +48,9 @@ as |sort filters items|}}
|
||||||
</h1>
|
</h1>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="actions">
|
<BlockSlot @name="actions">
|
||||||
|
{{#if (can "create tokens")}}
|
||||||
<a data-test-create href="{{href-to 'dc.acls.tokens.create'}}" class="type-create">Create</a>
|
<a data-test-create href="{{href-to 'dc.acls.tokens.create'}}" class="type-create">Create</a>
|
||||||
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="toolbar">
|
<BlockSlot @name="toolbar">
|
||||||
{{#if (gt items.length 0)}}
|
{{#if (gt items.length 0)}}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<form>
|
<form>
|
||||||
<fieldset>
|
<fieldset
|
||||||
|
disabled={{if (not (can "write nspace" item=item)) "disabled"}}
|
||||||
|
>
|
||||||
{{#if create }}
|
{{#if create }}
|
||||||
<label class="type-text{{if item.error.Name ' has-error'}}">
|
<label class="type-text{{if item.error.Name ' has-error'}}">
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
|
@ -21,26 +23,47 @@
|
||||||
<fieldset id="roles">
|
<fieldset id="roles">
|
||||||
<h2>Roles</h2>
|
<h2>Roles</h2>
|
||||||
<p>
|
<p>
|
||||||
|
{{#if (can "write nspace" item=item)}}
|
||||||
By adding roles to this namespaces, you will apply them to all tokens created within this namespace.
|
By adding roles to this namespaces, you will apply them to all tokens created within this namespace.
|
||||||
|
{{else}}
|
||||||
|
The following roles are applied to all tokens created within this namespace.
|
||||||
|
{{/if}}
|
||||||
</p>
|
</p>
|
||||||
<RoleSelector @dc={{dc}} @nspace="default" @items={{item.ACLs.RoleDefaults}} />
|
<RoleSelector
|
||||||
|
@disabled={{not (can "write nspace" item=item)}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace="default"
|
||||||
|
@items={{item.ACLs.RoleDefaults}}
|
||||||
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset id="policies">
|
<fieldset id="policies">
|
||||||
<h2>Policies</h2>
|
<h2>Policies</h2>
|
||||||
<p>
|
<p>
|
||||||
|
{{#if (can "write nspace" item=item)}}
|
||||||
By adding policies to this namespaces, you will apply them to all tokens created within this namespace.
|
By adding policies to this namespaces, you will apply them to all tokens created within this namespace.
|
||||||
|
{{else}}
|
||||||
|
The following policies are applied to all tokens created within this namespace.
|
||||||
|
{{/if}}
|
||||||
</p>
|
</p>
|
||||||
<PolicySelector @dc={{dc}} @nspace="default" @allowIdentity={{false}} @items={{item.ACLs.PolicyDefaults}} />
|
<PolicySelector
|
||||||
|
@disabled={{not (can "write nspace" item=item)}}
|
||||||
|
@dc={{dc}}
|
||||||
|
@nspace="default"
|
||||||
|
@allowIdentity={{false}}
|
||||||
|
@items={{item.ACLs.PolicyDefaults}}
|
||||||
|
/>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div>
|
<div>
|
||||||
{{#if create }}
|
{{#if (and create (can "create nspaces")) }}
|
||||||
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid) 'disabled'}}>Save</button>
|
<button type="submit" {{ action "create" item}} disabled={{if (or item.isPristine item.isInvalid) 'disabled'}}>Save</button>
|
||||||
{{ else }}
|
{{else}}
|
||||||
|
{{#if (can "write nspace" item=item)}}
|
||||||
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
<button type="submit" {{ action "update" item}} disabled={{if item.isInvalid 'disabled'}}>Save</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
<button type="reset" {{ action "cancel" item}}>Cancel</button>
|
||||||
{{# if (and (not create) (not-eq item.Name 'default')) }}
|
{{# if (and (not create) (can "delete nspace" item=item) ) }}
|
||||||
<ConfirmationDialog @message="Are you sure you want to delete this Namespace?">
|
<ConfirmationDialog @message="Are you sure you want to delete this Namespace?">
|
||||||
<BlockSlot @name="action" as |confirm|>
|
<BlockSlot @name="action" as |confirm|>
|
||||||
<button data-test-delete type="button" class="type-delete" {{action confirm 'delete' item parent}}>Delete</button>
|
<button data-test-delete type="button" class="type-delete" {{action confirm 'delete' item parent}}>Delete</button>
|
||||||
|
|
Loading…
Reference in New Issue