ui: Adds ability to search by policy, role or service ident names (#5811)

This commit is contained in:
John Cowen 2019-06-05 09:25:32 +01:00 committed by GitHub
parent af8de66be4
commit 92bff1bbb3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 318 additions and 13 deletions

View file

@ -8,7 +8,13 @@ export default function(filterable) {
.indexOf(sLower) !== -1 ||
get(item, 'Description')
.toLowerCase()
.indexOf(sLower) !== -1
.indexOf(sLower) !== -1 ||
(get(item, 'Policies') || []).some(function(item) {
return item.Name.toLowerCase().indexOf(sLower) !== -1;
}) ||
(get(item, 'ServiceIdentities') || []).some(function(item) {
return item.ServiceName.toLowerCase().indexOf(sLower) !== -1;
})
);
});
}

View file

@ -15,6 +15,12 @@ export default function(filterable) {
.indexOf(sLower) !== -1 ||
(get(item, 'Policies') || []).some(function(item) {
return item.Name.toLowerCase().indexOf(sLower) !== -1;
}) ||
(get(item, 'ServiceIdentities') || []).some(function(item) {
return item.ServiceName.toLowerCase().indexOf(sLower) !== -1;
}) ||
(get(item, 'Roles') || []).some(function(item) {
return item.Name.toLowerCase().indexOf(sLower) !== -1;
})
);
});

View file

@ -42,7 +42,7 @@
<td>
{{join ', ' (policy/datacenters item)}}
</td>
<td>
<td data-test-description>
{{item.Description}}
</td>
{{/block-slot}}

View file

@ -39,12 +39,12 @@
<td data-test-role="{{item.Name}}">
<a href={{href-to 'dc.acls.roles.edit' item.ID}}>{{item.Name}}</a>
</td>
<td>
<td data-test-description>
{{item.Description}}
</td>
<td>
{{#each item.Policies as |item|}}
<strong class={{policy/typeof item}}>{{item.Name}}</strong>
<strong data-test-policy class={{policy/typeof item}}>{{item.Name}}</strong>
{{/each}}
</td>
{{/block-slot}}

View file

@ -47,7 +47,7 @@
<td>
{{if item.Local 'local' 'global' }}
</td>
<td>
<td data-test-description>
{{default item.Description item.Name}}
</td>
<td colspan={{if (not-eq item.AccessorID token.AccessorID) '2' }}>
@ -55,7 +55,7 @@
Legacy tokens have embedded rules.
{{ else }}
{{#each (append item.Policies item.Roles) as |item|}}
<strong class={{policy/typeof item}}>{{item.Name}}</strong>
<strong data-test-policy class={{policy/typeof item}}>{{item.Name}}</strong>
{{/each}}
{{/if}}
</td>

View file

@ -10,6 +10,26 @@ Feature: dc / acls / policies / index: ACL Policy List
---
Then the url should be /dc-1/acls/policies
Then I see 3 policy models
Scenario: Searching the policies
Given 1 datacenter model with the value "dc-1"
And 3 policy models from yaml
---
- Description: Find me
- Description: Not in search
- Description: Not in search either
---
When I visit the policies page for yaml
---
dc: dc-1
---
Then the url should be /dc-1/acls/policies
Then I see 3 policy models
Then I fill in with yaml
---
s: Find me
---
And I see 1 policy model
And I see 1 policy model with the description "Find me"
@ignore
Scenario: The global-managment policy can't be deleted
And I click actions on the policies

View file

@ -10,3 +10,47 @@ Feature: dc / acls / roles / index: ACL Roles List
---
Then the url should be /dc-1/acls/roles
Then I see 3 role models
Scenario: Searching the roles
Given 1 datacenter model with the value "dc-1"
And 3 role models from yaml
---
- Description: Description Search
Policies:
- Name: not-in-Polsearch
ServiceIdentities:
- ServiceName: not-in-sisearch
- Description: Not in descsearch
Policies:
- Name: Policy-Search
ServiceIdentities:
- ServiceName: not-in-sisearch
- Description: Not in descsearch either
Policies:
- Name: not-in-Polsearch-either
ServiceIdentities:
- ServiceName: Si-Search
---
When I visit the roles page for yaml
---
dc: dc-1
---
Then the url should be /dc-1/acls/roles
Then I see 3 role models
Then I fill in with yaml
---
s: Description
---
And I see 1 role model
And I see 1 role model with the description "Description Search"
Then I fill in with yaml
---
s: Policy-Search
---
And I see 1 role model
And I see 1 role model with the policy "Policy-Search"
Then I fill in with yaml
---
s: Si-Search
---
And I see 1 role model
And I see 1 role model with the serviceIdentity "Si-Search"

View file

@ -10,6 +10,73 @@ Feature: dc / acls / tokens / index: ACL Token List
---
Then the url should be /dc-1/acls/tokens
Then I see 3 token models
Scenario: Searching the tokens
Given 1 datacenter model with the value "dc-1"
And 4 token models from yaml
---
- Description: Description Search
Legacy: false
ServiceIdentities:
- ServiceName: not-in-sisearch
Policies:
- Name: not-in-Polsearch
Roles:
- Name: not-in-rolesearch
- Description: Not in descsearch
Legacy: false
ServiceIdentities:
- ServiceName: not-in-sisearch
Policies:
- Name: Policy-Search
Roles:
- Name: not-in-rolesearch-either
- Description: Not in descsearch either
Legacy: false
ServiceIdentities:
- ServiceName: not-in-sisearch
Policies:
- Name: not-int-Polsearch-either
Roles:
- Name: Role-Search
- Description: Not in descsearch either
Legacy: false
ServiceIdentities:
- ServiceName: Si-Search
Policies:
- Name: not-int-Polsearch-either
Roles:
- Name: not-in-rolesearch-either
---
When I visit the tokens page for yaml
---
dc: dc-1
---
Then the url should be /dc-1/acls/tokens
Then I see 4 token models
Then I fill in with yaml
---
s: Description
---
And I see 1 token model
And I see 1 token model with the description "Description Search"
Then I fill in with yaml
---
s: Policy-Search
---
And I see 1 token model
And I see 1 token model with the policy "Policy-Search"
Then I fill in with yaml
---
s: Role-Search
---
And I see 1 token model
And I see 1 token model with the role "Role-Search"
Then I fill in with yaml
---
s: Si-Search
---
And I see 1 token model
And I see 1 token model with the serviceIdentity "Si-Search"
Scenario: I see the legacy message if I have one legacy token
Given 1 datacenter model with the value "dc-1"
And 3 token models from yaml

View file

@ -67,11 +67,20 @@ export default {
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
acl: create(acl(visitable, submitable, deletable, cancelable, clickable)),
policies: create(
policies(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter)
policies(
visitable,
deletable,
creatable,
clickable,
attribute,
collection,
text,
freetextFilter
)
),
policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)),
roles: create(
roles(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter)
roles(visitable, deletable, creatable, clickable, attribute, collection, text, freetextFilter)
),
// TODO: This needs a policyList
role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)),

View file

@ -1,10 +1,20 @@
export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) {
export default function(
visitable,
deletable,
creatable,
clickable,
attribute,
collection,
text,
filter
) {
return creatable({
visit: visitable('/:dc/acls/policies'),
policies: collection(
'[data-test-tabular-row]',
deletable({
name: attribute('data-test-policy', '[data-test-policy]'),
description: text('[data-test-description]'),
policy: clickable('a'),
actions: clickable('label'),
})

View file

@ -1,11 +1,22 @@
export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) {
export default function(
visitable,
deletable,
creatable,
clickable,
attribute,
collection,
text,
filter
) {
return creatable({
visit: visitable('/:dc/acls/roles'),
roles: collection(
'[data-test-tabular-row]',
deletable({
name: attribute('data-test-role', '[data-test-role]'),
policy: clickable('a'),
description: text('[data-test-description]'),
policy: text('[data-test-policy].policy', { multiple: true }),
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
actions: clickable('label'),
})
),

View file

@ -17,6 +17,10 @@ export default function(
'[data-test-tabular-row]',
deletable({
id: attribute('data-test-token', '[data-test-token]'),
description: text('[data-test-description]'),
policy: text('[data-test-policy].policy', { multiple: true }),
role: text('[data-test-policy].role', { multiple: true }),
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
token: clickable('a'),
actions: clickable('label'),
use: clickable('[data-test-use]'),

View file

@ -39,7 +39,15 @@ export default function(scenario, assert, find, currentPage, pauseUntil, plurali
value
) {
const len = currentPage()[pluralize(model)].filter(function(item) {
return item.isVisible && item[property] == value;
if (item.isVisible) {
let prop = item[property];
// cope with pageObjects that can have a multiple: true
if (!Array.isArray(prop)) {
prop = [prop];
}
return prop.includes(value);
}
return false;
}).length;
assert.equal(
len,

View file

@ -0,0 +1,89 @@
import getFilter from 'consul-ui/search/filters/role';
import { module, test } from 'qunit';
module('Unit | Search | Filter | role');
const filter = getFilter(cb => cb);
test('items are found by properties', function(assert) {
[
{
Name: 'name-HIT',
Description: 'description',
Policies: [],
},
{
Name: 'name',
Description: 'desc-HIT-ription',
Policies: [],
},
{
Name: 'name',
Description: 'description',
Policies: [{ Name: 'policy' }, { Name: 'policy-HIT' }],
},
{
Name: 'name',
Description: 'description',
ServiceIdentities: [
{ ServiceName: 'service-identity' },
{ ServiceName: 'service-identity-HIT' },
],
},
].forEach(function(item) {
const actual = filter(item, {
s: 'hit',
});
assert.ok(actual);
});
});
test('items are not found', function(assert) {
[
{
Name: 'name',
Description: 'description',
Policies: [],
},
{
Name: 'name',
Description: 'description',
Policies: [{ Name: 'policy' }, { Name: 'policy-second' }],
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }],
},
].forEach(function(item) {
const actual = filter(item, {
s: 'hit',
});
assert.notOk(actual);
});
});
test('arraylike things can be empty', function(assert) {
[
{
Name: 'name',
Description: 'description',
},
{
Name: 'name',
Description: 'description',
Policies: null,
ServiceIdentities: null,
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
Policies: [],
ServiceIdentities: [],
},
].forEach(function(item) {
const actual = filter(item, {
s: 'hit',
});
assert.notOk(actual);
});
});

View file

@ -30,6 +30,21 @@ test('items are found by properties', function(assert) {
Description: 'description',
Policies: [{ Name: 'policy' }, { Name: 'policy-HIT' }],
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
Roles: [{ Name: 'role' }, { Name: 'role-HIT' }],
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
ServiceIdentities: [
{ ServiceName: 'service-identity' },
{ ServiceName: 'service-identity-HIT' },
],
},
].forEach(function(item) {
const actual = filter(item, {
s: 'hit',
@ -51,6 +66,18 @@ test('items are not found', function(assert) {
Description: 'description',
Policies: [{ Name: 'policy' }, { Name: 'policy-second' }],
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
Roles: [{ Name: 'role' }, { Name: 'role-second' }],
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }],
},
].forEach(function(item) {
const actual = filter(item, {
s: 'hit',
@ -58,7 +85,7 @@ test('items are not found', function(assert) {
assert.notOk(actual);
});
});
test('policies can be empty', function(assert) {
test('arraylike things can be empty', function(assert) {
[
{
AccessorID: 'id',
@ -70,12 +97,16 @@ test('policies can be empty', function(assert) {
Name: 'name',
Description: 'description',
Policies: null,
Roles: null,
ServiceIdentities: null,
},
{
AccessorID: 'id',
Name: 'name',
Description: 'description',
Policies: [],
Roles: [],
ServiceIdentities: [],
},
].forEach(function(item) {
const actual = filter(item, {