ui: Support for Node Identities (#8137)
* Add all the new data required for NodeIdentities * Add potential NodeIdentity to the token list component * Amend the policy-form/selector to allow node identity creation * Fix up CSS for radio buttons and select label * Add node-identity policy template component * Fix up and add acceptance tests for NodeIndentities * Make sure policy previews take node identities into account * Only show certain policy markup if those we have those policies * Potentially temporarily hide dt's that don't have icons yet
This commit is contained in:
parent
146afbe9a2
commit
c5d0216939
|
@ -50,6 +50,7 @@ export default Adapter.extend({
|
||||||
Description: serialized.Description,
|
Description: serialized.Description,
|
||||||
Policies: serialized.Policies,
|
Policies: serialized.Policies,
|
||||||
ServiceIdentities: serialized.ServiceIdentities,
|
ServiceIdentities: serialized.ServiceIdentities,
|
||||||
|
NodeIdentities: serialized.NodeIdentities,
|
||||||
...Namespace(serialized.Namespace),
|
...Namespace(serialized.Namespace),
|
||||||
}}
|
}}
|
||||||
`;
|
`;
|
||||||
|
@ -66,6 +67,7 @@ export default Adapter.extend({
|
||||||
Description: serialized.Description,
|
Description: serialized.Description,
|
||||||
Policies: serialized.Policies,
|
Policies: serialized.Policies,
|
||||||
ServiceIdentities: serialized.ServiceIdentities,
|
ServiceIdentities: serialized.ServiceIdentities,
|
||||||
|
NodeIdentities: serialized.NodeIdentities,
|
||||||
...Namespace(serialized.Namespace),
|
...Namespace(serialized.Namespace),
|
||||||
}}
|
}}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default Adapter.extend({
|
||||||
Policies: serialized.Policies,
|
Policies: serialized.Policies,
|
||||||
Roles: serialized.Roles,
|
Roles: serialized.Roles,
|
||||||
ServiceIdentities: serialized.ServiceIdentities,
|
ServiceIdentities: serialized.ServiceIdentities,
|
||||||
|
NodeIdentities: serialized.NodeIdentities,
|
||||||
Local: serialized.Local,
|
Local: serialized.Local,
|
||||||
...Namespace(serialized.Namespace),
|
...Namespace(serialized.Namespace),
|
||||||
}}
|
}}
|
||||||
|
@ -84,6 +85,7 @@ export default Adapter.extend({
|
||||||
Policies: serialized.Policies,
|
Policies: serialized.Policies,
|
||||||
Roles: serialized.Roles,
|
Roles: serialized.Roles,
|
||||||
ServiceIdentities: serialized.ServiceIdentities,
|
ServiceIdentities: serialized.ServiceIdentities,
|
||||||
|
NodeIdentities: serialized.NodeIdentities,
|
||||||
Local: serialized.Local,
|
Local: serialized.Local,
|
||||||
...Namespace(serialized.Namespace),
|
...Namespace(serialized.Namespace),
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div role="group">
|
<div role="group">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<h2>Source</h2>
|
<h2>Source</h2>
|
||||||
<label data-test-source-element class="type-text{{if _item.error.SourceName ' has-error'}}">
|
<label data-test-source-element class="type-select{{if _item.error.SourceName ' has-error'}}">
|
||||||
<span>Source Service</span>
|
<span>Source Service</span>
|
||||||
<PowerSelectWithCreate
|
<PowerSelectWithCreate
|
||||||
@options={{_services}}
|
@options={{_services}}
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<em>Search for an existing service, or enter any Service name.</em>
|
<em>Search for an existing service, or enter any Service name.</em>
|
||||||
</label>
|
</label>
|
||||||
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
||||||
<label data-test-source-nspace class="type-text{{if _item.error.SourceNS ' has-error'}}">
|
<label data-test-source-nspace class="type-select{{if _item.error.SourceNS ' has-error'}}">
|
||||||
<span>Source Namespace</span>
|
<span>Source Namespace</span>
|
||||||
<PowerSelectWithCreate
|
<PowerSelectWithCreate
|
||||||
@options={{_nspaces}}
|
@options={{_nspaces}}
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<h2>Destination</h2>
|
<h2>Destination</h2>
|
||||||
<label data-test-destination-element class="type-text{{if _item.error.DestinationName ' has-error'}}">
|
<label data-test-destination-element class="type-select{{if _item.error.DestinationName ' has-error'}}">
|
||||||
<span>Destination Service</span>
|
<span>Destination Service</span>
|
||||||
<PowerSelectWithCreate
|
<PowerSelectWithCreate
|
||||||
@options={{_services}}
|
@options={{_services}}
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
<em>Search for an existing service, or enter any Service name.</em>
|
<em>Search for an existing service, or enter any Service name.</em>
|
||||||
</label>
|
</label>
|
||||||
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
||||||
<label data-test-destination-nspace class="type-text{{if _item.error.DestinationNS ' has-error'}}">
|
<label data-test-destination-nspace class="type-select{{if _item.error.DestinationNS ' has-error'}}">
|
||||||
<span>Destination Namespace</span>
|
<span>Destination Namespace</span>
|
||||||
<PowerSelectWithCreate
|
<PowerSelectWithCreate
|
||||||
@options={{_nspaces}}
|
@options={{_nspaces}}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<a href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>{{substr item.AccessorID -8}}</a>
|
<a href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>{{substr item.AccessorID -8}}</a>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="details">
|
<BlockSlot @name="details">
|
||||||
<dl>
|
<dl>
|
||||||
|
@ -23,7 +23,9 @@
|
||||||
{{#let (get policies 'management') as |management|}}
|
{{#let (get policies 'management') as |management|}}
|
||||||
{{#if (gt management.length 0)}}
|
{{#if (gt management.length 0)}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Management</dt>
|
<dt>
|
||||||
|
Management
|
||||||
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{#each (get policies 'management') as |item|}}
|
{{#each (get policies 'management') as |item|}}
|
||||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||||
|
@ -32,26 +34,34 @@
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
|
{{#let (get policies 'identities') as |identities|}}
|
||||||
|
{{#if (gt identities.length 0)}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Identities</dt>
|
<dt>Identities</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{#each (append (get policies 'identities')) as |item|}}
|
{{#each identities as |item|}}
|
||||||
<span data-test-policy class={{policy/typeof item}}>Service Identity: {{item.Name}}</span>
|
<span data-test-policy class={{policy/typeof item}}>{{if (eq item.template 'service-identity') 'Service' 'Node'}} Identity: {{item.Name}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
{{/if}}
|
||||||
|
{{/let}}
|
||||||
|
{{#let (append (get policies 'policies') item.Roles) as |policies|}}
|
||||||
|
{{#if (gt policies.length 0)}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Rules</dt>
|
<dt>Rules</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{#if (token/is-legacy item) }}
|
{{#if (token/is-legacy item) }}
|
||||||
Legacy tokens have embedded rules.
|
Legacy tokens have embedded rules.
|
||||||
{{ else }}
|
{{ else }}
|
||||||
{{#each (append (get policies 'policies') item.Roles) as |item|}}
|
{{#each policies as |item|}}
|
||||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
{{/if}}
|
||||||
|
{{/let}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Description</dt>
|
<dt>Description</dt>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
node "{{name}}" {
|
||||||
|
policy = "write"
|
||||||
|
}
|
||||||
|
service_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import Component from '@ember/component';
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
tagName: '',
|
||||||
|
});
|
|
@ -3,11 +3,11 @@
|
||||||
{{#yield-slot name='template'}}
|
{{#yield-slot name='template'}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<header>
|
<header>
|
||||||
Policy{{if allowServiceIdentity ' or service identity?' ''}}
|
Policy{{if allowIdentity ' or identity?' ''}}
|
||||||
</header>
|
</header>
|
||||||
{{#if allowServiceIdentity}}
|
{{#if allowIdentity}}
|
||||||
<p>
|
<p>
|
||||||
A Service Identity is default policy with a configurable service name. This saves you some time and effort you're using Consul for Connect features.
|
Identities are default policies with configurable names. They save you some time and effort you're using Consul for Connect features.
|
||||||
</p>
|
</p>
|
||||||
{{! this should use radio-group }}
|
{{! this should use radio-group }}
|
||||||
<div role="radiogroup" class={{if item.error.Type ' has-error'}}>
|
<div role="radiogroup" class={{if item.error.Type ' has-error'}}>
|
||||||
|
@ -34,17 +34,38 @@
|
||||||
</label>
|
</label>
|
||||||
<label class="type-text" data-test-rules>
|
<label class="type-text" data-test-rules>
|
||||||
<span>Rules <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl.html#rule-specification" rel="help noopener noreferrer" target="_blank">(HCL Format)</a></span>
|
<span>Rules <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl.html#rule-specification" rel="help noopener noreferrer" target="_blank">(HCL Format)</a></span>
|
||||||
{{#if (eq item.template '') }}
|
{{#if (eq item.template 'service-identity')}}
|
||||||
|
<CodeEditor @readonly={{true}} @name={{concat name "[Rules]"}} @syntax="hcl" @oninput={{action "change" (concat name "[Rules]")}}>
|
||||||
|
{{~component 'service-identity' name=item.Name~}}
|
||||||
|
</CodeEditor>
|
||||||
|
{{else if (eq item.template 'node-identity')}}
|
||||||
|
<CodeEditor @readonly={{true}} @name={{concat name "[Rules]"}} @syntax="hcl" @oninput={{action "change" (concat name "[Rules]")}}>
|
||||||
|
{{~component 'node-identity' name=item.Name~}}
|
||||||
|
</CodeEditor>
|
||||||
|
{{else}}
|
||||||
<CodeEditor @syntax="hcl" @class={{if item.error.Rules "error"}} @name={{concat name "[Rules]"}} @value={{item.Rules}} @onkeyup={{action "change" (concat name "[Rules]")}} />
|
<CodeEditor @syntax="hcl" @class={{if item.error.Rules "error"}} @name={{concat name "[Rules]"}} @value={{item.Rules}} @onkeyup={{action "change" (concat name "[Rules]")}} />
|
||||||
{{#if item.error.Rules}}
|
{{#if item.error.Rules}}
|
||||||
<strong>{{item.error.Rules.validation}}</strong>
|
<strong>{{item.error.Rules.validation}}</strong>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
|
||||||
<CodeEditor @readonly={{true}} @name={{concat name "[Rules]"}} @syntax="hcl" @oninput={{action "change" (concat name "[Rules]")}}>
|
|
||||||
{{~component 'service-identity' name=item.Name~}}
|
|
||||||
</CodeEditor>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
|
{{#if (eq item.template 'node-identity')}}
|
||||||
|
|
||||||
|
<DataSource @src="/*/*/datacenters"
|
||||||
|
@onchange={{action (mut datacenters) value="data"}}
|
||||||
|
/>
|
||||||
|
<label class="type-select" data-test-datacenter>
|
||||||
|
<span>Datacenter</span>
|
||||||
|
<PowerSelect
|
||||||
|
@options={{map-by 'Name' datacenters}}
|
||||||
|
@searchField="Name"
|
||||||
|
@selected={{or item.Datacenter dc}}
|
||||||
|
@searchPlaceholder="Type a datacenter name"
|
||||||
|
@onChange={{action "change" "Datacenter"}} as |Name|>
|
||||||
|
{{Name}}
|
||||||
|
</PowerSelect>
|
||||||
|
</label>
|
||||||
|
{{else}}
|
||||||
<div class="type-toggle">
|
<div class="type-toggle">
|
||||||
<span>Valid datacenters</span>
|
<span>Valid datacenters</span>
|
||||||
<label>
|
<label>
|
||||||
|
@ -52,10 +73,11 @@
|
||||||
<span>All</span>
|
<span>All</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{{#if isScoped }}
|
{{#if isScoped }}
|
||||||
<DataSource @src="/*/*/datacenters"
|
<DataSource @src="/*/*/datacenters"
|
||||||
@onchange={{action (mut datacenters) value="data"}}
|
@onchange={{action (mut datacenters) value="data"}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="checkbox-group" role="group">
|
<div class="checkbox-group" role="group">
|
||||||
{{#each datacenters as |dc| }}
|
{{#each datacenters as |dc| }}
|
||||||
<label class="type-checkbox">
|
<label class="type-checkbox">
|
||||||
|
@ -72,6 +94,9 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq item.template '') }}
|
{{#if (eq item.template '') }}
|
||||||
<label class="type-text">
|
<label class="type-text">
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { get, set } from '@ember/object';
|
||||||
export default FormComponent.extend({
|
export default FormComponent.extend({
|
||||||
type: 'policy',
|
type: 'policy',
|
||||||
name: 'policy',
|
name: 'policy',
|
||||||
allowServiceIdentity: true,
|
allowIdentity: true,
|
||||||
classNames: ['policy-form'],
|
classNames: ['policy-form'],
|
||||||
|
|
||||||
isScoped: false,
|
isScoped: false,
|
||||||
|
@ -20,6 +20,10 @@ export default FormComponent.extend({
|
||||||
name: 'Service Identity',
|
name: 'Service Identity',
|
||||||
template: 'service-identity',
|
template: 'service-identity',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Node Identity',
|
||||||
|
template: 'node-identity',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default (submitable, cancelable, radiogroup, text) => (
|
||||||
prefix: 'policy',
|
prefix: 'policy',
|
||||||
...submitable(),
|
...submitable(),
|
||||||
...cancelable(),
|
...cancelable(),
|
||||||
...radiogroup('template', ['', 'service-identity'], 'policy'),
|
...radiogroup('template', ['', 'service-identity', 'node-identity'], 'policy'),
|
||||||
rules: {
|
rules: {
|
||||||
error: text('[data-test-rules] strong'),
|
error: text('[data-test-rules] strong'),
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,35 +50,48 @@
|
||||||
<BlockSlot @name="row">
|
<BlockSlot @name="row">
|
||||||
<td class={{policy/typeof item}}>
|
<td class={{policy/typeof item}}>
|
||||||
{{#if item.ID }}
|
{{#if item.ID }}
|
||||||
<a href={{href-to 'dc.acls.policies.edit' item.ID}}>{{item.Name}}</a>
|
<a href={{href-to 'dc.acls.policies.edit' item.ID}}>{{item.Name}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a name={{item.Name}}>{{item.Name}}</a>
|
<a name={{item.Name}}>{{item.Name}}</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="details">
|
<BlockSlot @name="details">
|
||||||
{{#if (eq item.template '')}}
|
{{#if (eq item.template '')}}
|
||||||
<DataSource
|
<DataSource
|
||||||
@src={{concat '/' item.Namespace '/' dc '/policy/' item.ID}}
|
@src={{concat '/' item.Namespace '/' dc '/policy/' item.ID}}
|
||||||
@onchange={{action (mut loadedItem) value="data"}}
|
@onchange={{action (mut loadedItem) value="data"}}
|
||||||
@loading="lazy"
|
@loading="lazy"
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if (eq item.template 'node-identity')}}
|
||||||
|
<dl>
|
||||||
|
<dt>Datacenter:</dt>
|
||||||
|
<dd>
|
||||||
|
{{item.Datacenter}}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
{{else}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Datacenters:</dt>
|
<dt>Datacenters:</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{join ', ' (policy/datacenters (or loadedItem item))}}
|
{{join ', ' (policy/datacenters (or loadedItem item))}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
{{/if}}
|
||||||
<label class="type-text">
|
<label class="type-text">
|
||||||
<span>Rules <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl.html#rule-specification" rel="help noopener noreferrer" target="_blank">(HCL Format)</a></span>
|
<span>Rules <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl.html#rule-specification" rel="help noopener noreferrer" target="_blank">(HCL Format)</a></span>
|
||||||
{{#if (eq item.template '')}}
|
{{#if (eq item.template 'service-identity')}}
|
||||||
<CodeEditor @syntax="hcl" @readonly={{true}} @value={{or loadedItem.Rules item.Rules}} />
|
<CodeEditor @syntax="hcl" @readonly={{true}}>
|
||||||
{{else}}
|
{{~component 'service-identity' name=item.Name~}}
|
||||||
<CodeEditor @syntax="hcl" @readonly={{true}}>
|
</CodeEditor>
|
||||||
{{~component 'service-identity' name=item.Name~}}
|
{{else if (eq item.template 'node-identity')}}
|
||||||
</CodeEditor>
|
<CodeEditor @syntax="hcl" @readonly={{true}}>
|
||||||
{{/if}}
|
{{~component 'node-identity' name=item.Name~}}
|
||||||
|
</CodeEditor>
|
||||||
|
{{else}}
|
||||||
|
<CodeEditor @syntax="hcl" @readonly={{true}} @value={{or loadedItem.Rules item.Rules}} />
|
||||||
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
<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?">
|
||||||
|
|
|
@ -10,7 +10,7 @@ export default ChildSelectorComponent.extend({
|
||||||
repo: service('repository/policy/component'),
|
repo: service('repository/policy/component'),
|
||||||
name: 'policy',
|
name: 'policy',
|
||||||
type: 'policy',
|
type: 'policy',
|
||||||
allowServiceIdentity: true,
|
allowIdentity: true,
|
||||||
classNames: ['policy-selector'],
|
classNames: ['policy-selector'],
|
||||||
init: function() {
|
init: function() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
|
@ -3,14 +3,14 @@ import { get } from '@ember/object';
|
||||||
|
|
||||||
import minimizeModel from 'consul-ui/utils/minimizeModel';
|
import minimizeModel from 'consul-ui/utils/minimizeModel';
|
||||||
|
|
||||||
const normalizeServiceIdentities = function(items) {
|
const normalizeIdentities = function(items, template, name, dc) {
|
||||||
return (items || []).map(function(item) {
|
return (items || []).map(function(item) {
|
||||||
const policy = {
|
const policy = {
|
||||||
template: 'service-identity',
|
template: template,
|
||||||
Name: item.ServiceName,
|
Name: item[name],
|
||||||
};
|
};
|
||||||
if (typeof item.Datacenters !== 'undefined') {
|
if (typeof item[dc] !== 'undefined') {
|
||||||
policy.Datacenters = item.Datacenters;
|
policy[dc] = item[dc];
|
||||||
}
|
}
|
||||||
return policy;
|
return policy;
|
||||||
});
|
});
|
||||||
|
@ -25,17 +25,17 @@ const normalizePolicies = function(items) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const serializeServiceIdentities = function(items) {
|
const serializeIdentities = function(items, template, name, dc) {
|
||||||
return items
|
return items
|
||||||
.filter(function(item) {
|
.filter(function(item) {
|
||||||
return get(item, 'template') === 'service-identity';
|
return get(item, 'template') === template;
|
||||||
})
|
})
|
||||||
.map(function(item) {
|
.map(function(item) {
|
||||||
const identity = {
|
const identity = {
|
||||||
ServiceName: get(item, 'Name'),
|
[name]: get(item, 'Name'),
|
||||||
};
|
};
|
||||||
if (get(item, 'Datacenters')) {
|
if (typeof get(item, dc) !== 'undefined') {
|
||||||
identity.Datacenters = get(item, 'Datacenters');
|
identity[dc] = get(item, dc);
|
||||||
}
|
}
|
||||||
return identity;
|
return identity;
|
||||||
});
|
});
|
||||||
|
@ -51,9 +51,18 @@ export default Mixin.create({
|
||||||
respondForQueryRecord: function(respond, query) {
|
respondForQueryRecord: function(respond, query) {
|
||||||
return this._super(function(cb) {
|
return this._super(function(cb) {
|
||||||
return respond((headers, body) => {
|
return respond((headers, body) => {
|
||||||
body.Policies = normalizePolicies(body.Policies).concat(
|
body.Policies = normalizePolicies(body.Policies)
|
||||||
normalizeServiceIdentities(body.ServiceIdentities)
|
.concat(
|
||||||
);
|
normalizeIdentities(
|
||||||
|
body.ServiceIdentities,
|
||||||
|
'service-identity',
|
||||||
|
'ServiceName',
|
||||||
|
'Datacenters'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.concat(
|
||||||
|
normalizeIdentities(body.NodeIdentities, 'node-identity', 'NodeName', 'Datacenter')
|
||||||
|
);
|
||||||
return cb(headers, body);
|
return cb(headers, body);
|
||||||
});
|
});
|
||||||
}, query);
|
}, query);
|
||||||
|
@ -64,9 +73,18 @@ export default Mixin.create({
|
||||||
return cb(
|
return cb(
|
||||||
headers,
|
headers,
|
||||||
body.map(function(item) {
|
body.map(function(item) {
|
||||||
item.Policies = normalizePolicies(item.Policies).concat(
|
item.Policies = normalizePolicies(item.Policies)
|
||||||
normalizeServiceIdentities(item.ServiceIdentities)
|
.concat(
|
||||||
);
|
normalizeIdentities(
|
||||||
|
item.ServiceIdentities,
|
||||||
|
'service-identity',
|
||||||
|
'ServiceName',
|
||||||
|
'Datacenters'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.concat(
|
||||||
|
normalizeIdentities(item.NodeIdentities, 'node-identity', 'NodeName', 'Datacenter')
|
||||||
|
);
|
||||||
return item;
|
return item;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -75,7 +93,18 @@ export default Mixin.create({
|
||||||
},
|
},
|
||||||
serialize: function(snapshot, options) {
|
serialize: function(snapshot, options) {
|
||||||
const data = this._super(...arguments);
|
const data = this._super(...arguments);
|
||||||
data.ServiceIdentities = serializeServiceIdentities(data.Policies);
|
data.ServiceIdentities = serializeIdentities(
|
||||||
|
data.Policies,
|
||||||
|
'service-identity',
|
||||||
|
'ServiceName',
|
||||||
|
'Datacenters'
|
||||||
|
);
|
||||||
|
data.NodeIdentities = serializeIdentities(
|
||||||
|
data.Policies,
|
||||||
|
'node-identity',
|
||||||
|
'NodeName',
|
||||||
|
'Datacenter'
|
||||||
|
);
|
||||||
data.Policies = minimizeModel(serializePolicies(data.Policies));
|
data.Policies = minimizeModel(serializePolicies(data.Policies));
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,11 @@ export default Model.extend({
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
NodeIdentities: attr({
|
||||||
|
defaultValue: function() {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
}),
|
||||||
// frontend only for ordering where CreateIndex can't be used
|
// frontend only for ordering where CreateIndex can't be used
|
||||||
CreateTime: attr('date'),
|
CreateTime: attr('date'),
|
||||||
//
|
//
|
||||||
|
|
|
@ -39,6 +39,11 @@ export default Model.extend({
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
NodeIdentities: attr({
|
||||||
|
defaultValue: function() {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
}),
|
||||||
CreateTime: attr('date'),
|
CreateTime: attr('date'),
|
||||||
Hash: attr('string'),
|
Hash: attr('string'),
|
||||||
CreateIndex: attr('number'),
|
CreateIndex: attr('number'),
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
}
|
}
|
||||||
%radio-group label > span {
|
%radio-group label > span {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
margin-top: 0.2em;
|
|
||||||
}
|
}
|
||||||
%radio-group label,
|
%radio-group label,
|
||||||
%radio-group label > span {
|
%radio-group label > span {
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
.consul-token-list > ul > li:not(:first-child) {
|
.consul-token-list > ul > li:not(:first-child) {
|
||||||
@extend %with-composite-row-intent;
|
@extend %with-composite-row-intent;
|
||||||
}
|
}
|
||||||
|
/*TODO: This hides the icons-less dt's in the below lists as */
|
||||||
|
/* they don't have tooltips */
|
||||||
|
.consul-token-list > ul > li:not(:first-child) dt {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
/* TODO: the service list has a 1px offset */
|
/* TODO: the service list has a 1px offset */
|
||||||
.consul-service-list li > div:first-child > dl:first-child dd {
|
.consul-service-list li > div:first-child > dl:first-child dd {
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
|
|
|
@ -20,6 +20,7 @@ label span {
|
||||||
@extend %form-row;
|
@extend %form-row;
|
||||||
}
|
}
|
||||||
%radio-group label,
|
%radio-group label,
|
||||||
|
%main-content .type-select,
|
||||||
%main-content .type-password,
|
%main-content .type-password,
|
||||||
%main-content .type-text {
|
%main-content .type-text {
|
||||||
@extend %form-element;
|
@extend %form-element;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<p>
|
<p>
|
||||||
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.
|
||||||
</p>
|
</p>
|
||||||
<PolicySelector @dc={{dc}} @nspace="default" @allowServiceIdentity={{false}} @items={{item.ACLs.PolicyDefaults}} />
|
<PolicySelector @dc={{dc}} @nspace="default" @allowIdentity={{false}} @items={{item.ACLs.PolicyDefaults}} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -6,6 +6,7 @@ Feature: dc / acls / policies / as many / add existing: Add existing policy
|
||||||
---
|
---
|
||||||
Policies: ~
|
Policies: ~
|
||||||
ServiceIdentities: ~
|
ServiceIdentities: ~
|
||||||
|
NodeIdentities: ~
|
||||||
---
|
---
|
||||||
And 2 policy models from yaml
|
And 2 policy models from yaml
|
||||||
---
|
---
|
||||||
|
|
|
@ -6,6 +6,7 @@ Feature: dc / acls / policies / as many / add new: Add new policy
|
||||||
---
|
---
|
||||||
Policies: ~
|
Policies: ~
|
||||||
ServiceIdentities: ~
|
ServiceIdentities: ~
|
||||||
|
NodeIdentities: ~
|
||||||
---
|
---
|
||||||
When I visit the [Model] page for yaml
|
When I visit the [Model] page for yaml
|
||||||
---
|
---
|
||||||
|
@ -52,7 +53,6 @@ Feature: dc / acls / policies / as many / add new: Add new policy
|
||||||
Then I fill in the policies.form with yaml
|
Then I fill in the policies.form with yaml
|
||||||
---
|
---
|
||||||
Name: New-Service-Identity
|
Name: New-Service-Identity
|
||||||
Description: New Service Identity Description
|
|
||||||
---
|
---
|
||||||
And I click serviceIdentity on the policies.form
|
And I click serviceIdentity on the policies.form
|
||||||
And I click submit on the policies.form
|
And I click submit on the policies.form
|
||||||
|
@ -73,6 +73,31 @@ Feature: dc / acls / policies / as many / add new: Add new policy
|
||||||
| token |
|
| token |
|
||||||
| role |
|
| role |
|
||||||
-------------
|
-------------
|
||||||
|
Scenario: Adding a new node identity as a child of [Model]
|
||||||
|
Then I fill in the policies.form with yaml
|
||||||
|
---
|
||||||
|
Name: New-Node-Identity
|
||||||
|
---
|
||||||
|
And I click nodeIdentity on the policies.form
|
||||||
|
And I click submit on the policies.form
|
||||||
|
And I submit
|
||||||
|
Then a PUT request was made to "/v1/acl/[Model]/key?dc=datacenter" from yaml
|
||||||
|
---
|
||||||
|
body:
|
||||||
|
Namespace: @namespace
|
||||||
|
NodeIdentities:
|
||||||
|
- NodeName: New-Node-Identity
|
||||||
|
Datacenter: datacenter
|
||||||
|
---
|
||||||
|
Then the url should be /datacenter/acls/[Model]s
|
||||||
|
And "[data-notification]" has the "notification-update" class
|
||||||
|
And "[data-notification]" has the "success" class
|
||||||
|
Where:
|
||||||
|
-------------
|
||||||
|
| Model |
|
||||||
|
| token |
|
||||||
|
| role |
|
||||||
|
-------------
|
||||||
Scenario: Adding a new policy as a child of [Model] and getting an error
|
Scenario: Adding a new policy as a child of [Model] and getting an error
|
||||||
Given the url "/v1/acl/policy" responds with from yaml
|
Given the url "/v1/acl/policy" responds with from yaml
|
||||||
---
|
---
|
||||||
|
@ -113,3 +138,15 @@ Feature: dc / acls / policies / as many / add new: Add new policy
|
||||||
| token |
|
| token |
|
||||||
| role |
|
| role |
|
||||||
-------------
|
-------------
|
||||||
|
Scenario: Try to edit the Node Identity using the code editor
|
||||||
|
And I click nodeIdentity on the policies.form
|
||||||
|
Then I can't fill in the policies.form with yaml
|
||||||
|
---
|
||||||
|
Rules: key {}
|
||||||
|
---
|
||||||
|
Where:
|
||||||
|
-------------
|
||||||
|
| Model |
|
||||||
|
| token |
|
||||||
|
| role |
|
||||||
|
-------------
|
||||||
|
|
|
@ -6,8 +6,8 @@ Feature: dc / acls / policies / as many / list: List
|
||||||
---
|
---
|
||||||
ServiceIdentities:
|
ServiceIdentities:
|
||||||
- ServiceName: Service-Identity
|
- ServiceName: Service-Identity
|
||||||
- ServiceName: Service-Identity 2
|
NodeIdentities:
|
||||||
- ServiceName: Service-Identity 3
|
- NodeName: Node-Identity
|
||||||
Policies:
|
Policies:
|
||||||
- Name: Policy
|
- Name: Policy
|
||||||
ID: 0000
|
ID: 0000
|
||||||
|
@ -22,8 +22,8 @@ Feature: dc / acls / policies / as many / list: List
|
||||||
[Model]: key
|
[Model]: key
|
||||||
---
|
---
|
||||||
Then the url should be /datacenter/acls/[Model]s/key
|
Then the url should be /datacenter/acls/[Model]s/key
|
||||||
# ServiceIdentities turn into policies
|
# Identities turn into policies
|
||||||
Then I see 6 policy models on the policies component
|
Then I see 5 policy models on the policies component
|
||||||
Where:
|
Where:
|
||||||
-------------
|
-------------
|
||||||
| Model |
|
| Model |
|
||||||
|
|
|
@ -5,6 +5,7 @@ Feature: dc / acls / policies / as many / remove: Remove
|
||||||
And 1 [Model] model from yaml
|
And 1 [Model] model from yaml
|
||||||
---
|
---
|
||||||
ServiceIdentities: ~
|
ServiceIdentities: ~
|
||||||
|
NodeIdentities: ~
|
||||||
Policies:
|
Policies:
|
||||||
- Name: Policy
|
- Name: Policy
|
||||||
ID: 00000000-0000-0000-0000-000000000001
|
ID: 00000000-0000-0000-0000-000000000001
|
||||||
|
|
|
@ -6,6 +6,7 @@ Feature: dc / acls / tokens / clone: Cloning an ACL token
|
||||||
---
|
---
|
||||||
AccessorID: token
|
AccessorID: token
|
||||||
SecretID: ee52203d-989f-4f7a-ab5a-2bef004164ca
|
SecretID: ee52203d-989f-4f7a-ab5a-2bef004164ca
|
||||||
|
Legacy: ~
|
||||||
---
|
---
|
||||||
Scenario: Cloning an ACL token from the listing page
|
Scenario: Cloning an ACL token from the listing page
|
||||||
When I visit the tokens page for yaml
|
When I visit the tokens page for yaml
|
||||||
|
|
|
@ -4,16 +4,27 @@ export const createPolicies = function(item) {
|
||||||
template: '',
|
template: '',
|
||||||
...item,
|
...item,
|
||||||
};
|
};
|
||||||
}).concat(
|
})
|
||||||
item.ServiceIdentities.map(function(item) {
|
.concat(
|
||||||
const policy = {
|
item.ServiceIdentities.map(function(item) {
|
||||||
template: 'service-identity',
|
const policy = {
|
||||||
Name: item.ServiceName,
|
template: 'service-identity',
|
||||||
};
|
Name: item.ServiceName,
|
||||||
if (typeof item.Datacenters !== 'undefined') {
|
};
|
||||||
policy.Datacenters = item.Datacenters;
|
if (typeof item.Datacenters !== 'undefined') {
|
||||||
}
|
policy.Datacenters = item.Datacenters;
|
||||||
return policy;
|
}
|
||||||
})
|
return policy;
|
||||||
);
|
})
|
||||||
|
)
|
||||||
|
.concat(
|
||||||
|
item.NodeIdentities.map(function(item) {
|
||||||
|
const policy = {
|
||||||
|
template: 'node-identity',
|
||||||
|
Name: item.NodeName,
|
||||||
|
Datacenter: item.Datacenter,
|
||||||
|
};
|
||||||
|
return policy;
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1211,9 +1211,9 @@
|
||||||
js-yaml "^3.13.1"
|
js-yaml "^3.13.1"
|
||||||
|
|
||||||
"@hashicorp/consul-api-double@^3.0.0":
|
"@hashicorp/consul-api-double@^3.0.0":
|
||||||
version "3.0.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@hashicorp/consul-api-double/-/consul-api-double-3.0.0.tgz#a1ad94f33e006d01cebf2b22d1f87efef1756ece"
|
resolved "https://registry.yarnpkg.com/@hashicorp/consul-api-double/-/consul-api-double-3.1.0.tgz#6f0cfc32d99b6f0c876d473ff8fdc489b7403904"
|
||||||
integrity sha512-wB1YgDBN3eOvNWRzSOc2k0eVE7C8YHFC5rJEdNWWTzjOokj6zDr40g2yLiaDMXl21XQs5LE8kNstEe8pf2+JUQ==
|
integrity sha512-TsRvkBJTzMaXlSyaFT4HU+Phhk+7K2kWPmnuM41cqkHsCLfoTllQ37avQyLYGM/57yfd0ajbI4M6IKoYJnQUWg==
|
||||||
|
|
||||||
"@hashicorp/ember-cli-api-double@^3.1.0":
|
"@hashicorp/ember-cli-api-double@^3.1.0":
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
|
|
Loading…
Reference in New Issue