diff --git a/addons/api/addon/abilities/collection.js b/addons/api/addon/abilities/collection.js index ad52afd18..92f0e4342 100644 --- a/addons/api/addon/abilities/collection.js +++ b/addons/api/addon/abilities/collection.js @@ -29,7 +29,8 @@ export default class CollectionAbility extends Ability { * @return {boolean} */ hasAuthorizedCollectionAction(action) { - const { authorized_collection_actions } = this.model; + const authorized_collection_actions = + (this.model || {}).authorized_collection_actions || {}; const collection = this.collection || {}; return authorized_collection_actions[collection]?.includes(action); } diff --git a/addons/api/addon/models/base.js b/addons/api/addon/models/base.js index f99e0351a..5ce5d3a8c 100644 --- a/addons/api/addon/models/base.js +++ b/addons/api/addon/models/base.js @@ -42,6 +42,11 @@ export default class BaseModel extends Model { }) authorized_actions; + @attr({ + readOnly: true, + }) + authorized_collection_actions; + set scopeModel(model) { if (model) { const json = model.serialize(); @@ -52,7 +57,7 @@ export default class BaseModel extends Model { /** * Convenience for getting and setting the parent scope ID. - * @type {string + * @type {string} */ @computed('scope.scope_id') get scopeID() { diff --git a/addons/api/mirage/factories/scope.js b/addons/api/mirage/factories/scope.js index fe41f3866..186d40205 100644 --- a/addons/api/mirage/factories/scope.js +++ b/addons/api/mirage/factories/scope.js @@ -4,6 +4,19 @@ import { trait } from 'ember-cli-mirage'; export default factory.extend({ type: 'global', + authorized_collection_actions: () => { + return { + users: ['create', 'list'], + sessions: ['list'], + groups: ['create', 'list'], + roles: ['create', 'list'], + targets: ['create', 'list'], + 'credential-stores': ['create', 'list'], + 'auth-methods': ['create', 'list'], + 'host-catalogs': ['create', 'list'], + }; + }, + /** * Generates realistic-ish IDs while still being deterministic. */ diff --git a/addons/api/package.json b/addons/api/package.json index be04185ab..5094a68e2 100644 --- a/addons/api/package.json +++ b/addons/api/package.json @@ -41,7 +41,7 @@ "broccoli-asset-rev": "^3.0.0", "doctoc": "^2.0.0", "ember-auto-import": "^1.10.1", - "ember-cli": "~3.27.0", + "ember-cli": "~3.28.0", "ember-cli-dependency-checker": "^3.2.0", "ember-cli-inject-live-reload": "^2.1.0", "ember-cli-sri": "^2.1.1", diff --git a/addons/auth/package.json b/addons/auth/package.json index f656717be..0418515dc 100644 --- a/addons/auth/package.json +++ b/addons/auth/package.json @@ -35,7 +35,7 @@ "core": "*", "doctoc": "^2.0.0", "ember-auto-import": "^1.10.1", - "ember-cli": "~3.27.0", + "ember-cli": "~3.28.0", "ember-cli-dependency-checker": "^3.2.0", "ember-cli-inject-live-reload": "^2.1.0", "ember-cli-sri": "^2.1.1", diff --git a/addons/core/addon/components/doc-link/index.hbs b/addons/core/addon/components/doc-link/index.hbs index e654aac4a..664e9d215 100644 --- a/addons/core/addon/components/doc-link/index.hbs +++ b/addons/core/addon/components/doc-link/index.hbs @@ -4,5 +4,5 @@ target="_blank" rel="noreferrer noopener" title={{t "actions.get-topic-help"}}> - + diff --git a/addons/core/addon/components/error/message/index.js b/addons/core/addon/components/error/message/index.js index 22c587595..9d9e435db 100644 --- a/addons/core/addon/components/error/message/index.js +++ b/addons/core/addon/components/error/message/index.js @@ -27,13 +27,12 @@ export default class ErrorMessageComponent extends MessageComponent { @computed('args.status') get icon() { switch (this.args.status) { + case '404': + return 'flight-icons/help-16'; case '401': case '403': - return 'disabled'; - case '404': - return 'help-circle-outline'; default: - return 'alert-circle-outline'; + return 'flight-icons/alert-circle-16'; } } diff --git a/addons/core/index.js b/addons/core/index.js index fa6be2662..3646d4641 100644 --- a/addons/core/index.js +++ b/addons/core/index.js @@ -1,4 +1,41 @@ 'use strict'; + +var path = require('path'); + module.exports = { name: require('./package').name, + + included(app) { + this._super.included.apply(this, arguments); + this.includePublic(app); + this.setupSVGO(app); + }, + + /** + * Finds the public folder and includes it into the ember-inline-svg addon. + */ + includePublic(app) { + const publicPath = path.resolve('public'); + const dummyPublicPath = path.resolve('tests/dummy/public'); + + app.options.svg = app.options.svg || {}; + app.options.svg.paths = app.options.svg.paths || []; + + app.options.svg.paths.push(publicPath); + if (this.isDevelopingAddon()) app.options.svg.paths.push(dummyPublicPath); + + this.addons.forEach((addon) => { + if (addon.name === 'ember-inline-svg') addon.included(app); + }); + }, + + /** + * Adjust SVG optimizer defaults (used by ember-inline-svg). + */ + setupSVGO(app) { + app.options.svg = app.options.svg || {}; + app.options.svg.optimize = app.options.svg.optimize || {}; + app.options.svg.optimize.plugins = app.options.svg.optimize.plugins || []; + app.options.svg.optimize.plugins.push({ removeViewBox: false }); + }, }; diff --git a/addons/core/package.json b/addons/core/package.json index 4ede3ce38..3b92f32c1 100644 --- a/addons/core/package.json +++ b/addons/core/package.json @@ -50,7 +50,7 @@ "broccoli-asset-rev": "^3.0.0", "doctoc": "^2.0.0", "ember-auto-import": "^1.10.1", - "ember-cli": "~3.27.0", + "ember-cli": "~3.28.0", "ember-cli-dependency-checker": "^3.2.0", "ember-cli-inject-live-reload": "^2.1.0", "ember-cli-sri": "^2.1.1", diff --git a/addons/core/public/app-icons/global.svg b/addons/core/public/app-icons/global.svg index 0e5b84d47..0c5298171 100644 --- a/addons/core/public/app-icons/global.svg +++ b/addons/core/public/app-icons/global.svg @@ -1,3 +1,5 @@ - - - + + + + + \ No newline at end of file diff --git a/addons/core/public/app-icons/org.svg b/addons/core/public/app-icons/org.svg index 238cc8435..213323766 100644 --- a/addons/core/public/app-icons/org.svg +++ b/addons/core/public/app-icons/org.svg @@ -1,3 +1,12 @@ - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/core/public/app-icons/project.svg b/addons/core/public/app-icons/project.svg index 5b9515d08..b65333af2 100644 --- a/addons/core/public/app-icons/project.svg +++ b/addons/core/public/app-icons/project.svg @@ -1,3 +1,8 @@ - - - + + + + + + + + \ No newline at end of file diff --git a/addons/core/translations/en-us.yaml b/addons/core/translations/en-us.yaml index 5370c7e75..8f98f633c 100644 --- a/addons/core/translations/en-us.yaml +++ b/addons/core/translations/en-us.yaml @@ -32,6 +32,8 @@ titles: descriptions: empty-set: There are no items to display yet. You may be able to add items or try back later. origin-initialization: To get started, please enter your origin URL + create-but-not-list: You do not have permission to list {resource}, but you can create new instances. + neither-list-nor-create: You do not have permission to list or create {resource}. questions: delete-confirm: Are you sure you want to delete this resource? remove-confirm: Are you sure you want to remove this association? diff --git a/addons/rose/addon/components/rose/badge/index.stories.mdx b/addons/rose/addon/components/rose/badge/index.stories.mdx index 1f91c7beb..d109810c6 100644 --- a/addons/rose/addon/components/rose/badge/index.stories.mdx +++ b/addons/rose/addon/components/rose/badge/index.stories.mdx @@ -13,7 +13,7 @@ When style definition isn't supplied, a default style will be supplied. Styles: outline, dark, informational, informational-outline, success, success-outline, error, error-outline, warning, warning-outline, alert, alert-outline ```html -Badge +Badge ``` @@ -43,11 +43,9 @@ Styles: outline, dark, informational, informational-outline, success, success-ou 'none' ), icon: select('icon', { - 'user-organization': 'user-organization', - 'partner': 'partner', - 'gift-fill': 'gift-fill', + 'flight-icons/org-16': 'flight-icons/org-16', }, - 'user-organization' + 'flight-icons/org-16' ), } }} @@ -58,7 +56,7 @@ Styles: outline, dark, informational, informational-outline, success, success-ou template: hbs` default style outline - default style with icon + default style with icon dark informational informational-outline diff --git a/addons/rose/addon/components/rose/button/index.stories.mdx b/addons/rose/addon/components/rose/button/index.stories.mdx index 7617f0ba3..18235d3ce 100644 --- a/addons/rose/addon/components/rose/button/index.stories.mdx +++ b/addons/rose/addon/components/rose/button/index.stories.mdx @@ -12,7 +12,7 @@ to trigger actions or to submit forms. Avoid using buttons as simple links to other routes. For accessibility, use links instead. ```htmlbars - + Action ``` @@ -49,23 +49,18 @@ other routes. For accessibility, use links instead. iconLeft: select( 'iconLeft', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'check-circle-outline' + 'flight-icons/check-circle-16' ), iconRight: select( 'iconRight', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'chevron-right', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'chevron-right' + 'flight-icons/clipboard-copy-16' ), onClick: action('clicked'), }, @@ -86,12 +81,10 @@ button in this case for accessibility. iconOnly: select( 'iconOnly', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'check-circle-outline' + 'flight-icons/check-circle-16' ), }, }} diff --git a/addons/rose/addon/components/rose/card/link/index.stories.mdx b/addons/rose/addon/components/rose/card/link/index.stories.mdx index 57171eaf6..eaaa20293 100644 --- a/addons/rose/addon/components/rose/card/link/index.stories.mdx +++ b/addons/rose/addon/components/rose/card/link/index.stories.mdx @@ -13,7 +13,7 @@ Card link component wraps content with `LinkTo` component. Supports title and de @title='Card title' @description='Card description' @id='resource_id_1234' - @icon='user-organization' + @icon='flight-icons/org-16' @route='about'/> ``` @@ -32,11 +32,9 @@ Card link component wraps content with `LinkTo` component. Supports title and de description: text('description', 'Card description'), id: text('id', 'resource_id_1234'), icon: select('icon', { - 'user-organization': 'user-organization', - 'partner': 'partner', - 'gift-fill': 'gift-fill', + 'flight-icons/org-16': 'flight-icons/org-16', }, - 'user-organization' + 'flight-icons/org-16' ), }, }} diff --git a/addons/rose/addon/components/rose/cards/index.stories.mdx b/addons/rose/addon/components/rose/cards/index.stories.mdx index 166d8fd83..bb2471b84 100644 --- a/addons/rose/addon/components/rose/cards/index.stories.mdx +++ b/addons/rose/addon/components/rose/cards/index.stories.mdx @@ -18,35 +18,35 @@ A set of cards arranged side-by-side. @title="Card Title" @description="Description" @id="resource_id_1234" - @icon="user-organization" + @icon="flight-icons/org-16" /> `, @@ -62,14 +62,14 @@ A set of cards arranged side-by-side. @title="Card Title" @description="Description" @id="resource_id_1234" - @icon="user-organization" + @icon="flight-icons/org-16" /> ``` diff --git a/addons/rose/addon/components/rose/dialog/index.hbs b/addons/rose/addon/components/rose/dialog/index.hbs index aa03d38de..4f762c6bc 100644 --- a/addons/rose/addon/components/rose/dialog/index.hbs +++ b/addons/rose/addon/components/rose/dialog/index.hbs @@ -27,7 +27,7 @@ title={{@dismissButtonText}} {{on "click" (fn this.dismiss @dismiss)}} > - + @@ -62,7 +62,7 @@ title={{@dismissButtonText}} {{on "click" (fn this.dismiss @dismiss)}} > - + diff --git a/addons/rose/addon/components/rose/dialog/index.stories.mdx b/addons/rose/addon/components/rose/dialog/index.stories.mdx index 9ea81df93..d5d05be52 100644 --- a/addons/rose/addon/components/rose/dialog/index.stories.mdx +++ b/addons/rose/addon/components/rose/dialog/index.stories.mdx @@ -36,12 +36,10 @@ A dialog component with optional modal capabilities. icon: select( 'icon', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less' + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'check-circle-outline' + 'flight-icons/check-circle-16' ), style: select( 'style', @@ -60,7 +58,7 @@ A dialog component with optional modal capabilities. diff --git a/addons/rose/addon/components/rose/dropdown/index.stories.mdx b/addons/rose/addon/components/rose/dropdown/index.stories.mdx index 58a0575bf..fae413044 100644 --- a/addons/rose/addon/components/rose/dropdown/index.stories.mdx +++ b/addons/rose/addon/components/rose/dropdown/index.stories.mdx @@ -11,7 +11,7 @@ A simple dropdown component with support for links and buttons. {{ template: hbs` - + Menu item Menu item @@ -31,7 +31,7 @@ A simple dropdown component with support for links and buttons. {{ template: hbs` - + Menu item Menu item @@ -117,7 +117,7 @@ Dropdown supports `danger` styling through `style` attribute. Dropdown indicator can be hidden using `showCaret` attribute. ```html - + Menu item Button menu item diff --git a/addons/rose/addon/components/rose/form/errors/message/index.hbs b/addons/rose/addon/components/rose/form/errors/message/index.hbs index fb4b2ebe0..eb2246b04 100644 --- a/addons/rose/addon/components/rose/form/errors/message/index.hbs +++ b/addons/rose/addon/components/rose/form/errors/message/index.hbs @@ -1,4 +1,4 @@

- + {{yield}}

diff --git a/addons/rose/addon/components/rose/form/radio/group/index.stories.mdx b/addons/rose/addon/components/rose/form/radio/group/index.stories.mdx index 515c7ca35..026b9526c 100644 --- a/addons/rose/addon/components/rose/form/radio/group/index.stories.mdx +++ b/addons/rose/addon/components/rose/form/radio/group/index.stories.mdx @@ -68,12 +68,10 @@ Renders a form radiofield group. firstFieldIcon: select( 'first icon', { - 'user-organization': 'user-organization', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/org-16': 'flight-icons/org-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'user-organization' + 'flight-icons/org-16' ), secondFieldLabel: text('second label', 'Maybe'), secondFieldValue: text('second value', 'maybe'), diff --git a/addons/rose/addon/components/rose/form/radio/radio/index.stories.mdx b/addons/rose/addon/components/rose/form/radio/radio/index.stories.mdx index 4d6a4153e..a5540499b 100644 --- a/addons/rose/addon/components/rose/form/radio/radio/index.stories.mdx +++ b/addons/rose/addon/components/rose/form/radio/radio/index.stories.mdx @@ -44,10 +44,8 @@ Renders a form radiofield. 'icon', { 'none': null, - 'user-organization': 'user-organization', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/org-16': 'flight-icons/org-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, null ), @@ -111,14 +109,12 @@ Renders a form radiofield. 'icon', { 'none': null, - 'user-organization': 'user-organization', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/org-16': 'flight-icons/org-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, null ), inline: boolean('inline', false) } }}
-
\ No newline at end of file +
diff --git a/addons/rose/addon/components/rose/header/index.stories.mdx b/addons/rose/addon/components/rose/header/index.stories.mdx index bffd410b7..e1990b552 100644 --- a/addons/rose/addon/components/rose/header/index.stories.mdx +++ b/addons/rose/addon/components/rose/header/index.stories.mdx @@ -27,7 +27,7 @@ A header component that allows three distinct sections to be configured: brand, Menu item Menu item @@ -69,13 +69,11 @@ A header component that allows three distinct sections to be configured: brand, dropdownIcon: select( 'dropdownIcon', { - 'user-square-fill': 'user-square-fill', - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/user-circle-16': 'flight-icons/user-circle-16', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'user-square-fill' + 'flight-icons/user-circle-16' ), }, }} diff --git a/addons/rose/addon/components/rose/icon/index.stories.mdx b/addons/rose/addon/components/rose/icon/index.stories.mdx index ffb0e32ca..946b7d1cf 100644 --- a/addons/rose/addon/components/rose/icon/index.stories.mdx +++ b/addons/rose/addon/components/rose/icon/index.stories.mdx @@ -7,9 +7,7 @@ import { text, boolean, select } from '@storybook/addon-knobs'; # Icon -Renders a simple icon from [Structure Icons][structure-icons]. - -[structure-icons]: https://github.com/hashicorp/structure-icons +Renders a simple icon. ```htmlbars @@ -24,12 +22,10 @@ Renders a simple icon from [Structure Icons][structure-icons]. name: select( 'name', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', - 'unfold-less': 'unfold-less', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'check-circle-outline' + 'flight-icons/check-circle-16' ), } }} diff --git a/addons/rose/addon/components/rose/link-button/index.stories.mdx b/addons/rose/addon/components/rose/link-button/index.stories.mdx index 0ca00a2ee..9b952f6b9 100644 --- a/addons/rose/addon/components/rose/link-button/index.stories.mdx +++ b/addons/rose/addon/components/rose/link-button/index.stories.mdx @@ -12,7 +12,7 @@ Styles supported: primary, secondary, warning, and ghost. Disabling link button is not supported as it is an action on form components only. ```html - + Content ``` @@ -45,21 +45,18 @@ Disabling link button is not supported as it is an action on form components onl iconLeft: select( 'iconLeft', { - 'check-circle-outline': 'check-circle-outline', - 'copy-action': 'copy-action', - 'unfold-more': 'unfold-more', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'copy-action' + 'flight-icons/clipboard-copy-16' ), iconRight: select( 'iconRight', { - 'check-circle-outline': 'check-circle-outline', - 'chevron-right': 'chevron-right', - 'copy-action': 'copy-action', - 'search': 'search', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/clipboard-copy-16': 'flight-icons/clipboard-copy-16', }, - 'chevron-right' + 'flight-icons/clipboard-copy-16' ), }, }} @@ -68,7 +65,7 @@ Disabling link button is not supported as it is an action on form components onl Similar to `Rose::Button`, icon only link button is supported. ```html - + ``` @@ -91,12 +88,10 @@ Similar to `Rose::Button`, icon only link button is supported. iconOnly: select( 'iconOnly', { - 'check-circle-outline': 'check-circle-outline', - 'help-circle-outline': 'help-circle-outline', - 'plus-circle-fill': 'plus-circle-fill', - 'user-square-outline': 'user-square-outline', + 'flight-icons/check-circle-16': 'flight-icons/check-circle-16', + 'flight-icons/help-16': 'flight-icons/help-16', }, - 'help-circle-outline' + 'flight-icons/help-16' ), }, }} diff --git a/addons/rose/addon/components/rose/list/key-value/index.stories.mdx b/addons/rose/addon/components/rose/list/key-value/index.stories.mdx index b37e554ff..74d65375f 100644 --- a/addons/rose/addon/components/rose/list/key-value/index.stories.mdx +++ b/addons/rose/addon/components/rose/list/key-value/index.stories.mdx @@ -46,7 +46,7 @@ A simple key/value list with support for embedded form fields and buttons. - Remove + Remove @@ -94,7 +94,7 @@ A simple key/value list with support for embedded form fields and buttons. - Remove + Remove diff --git a/addons/rose/addon/components/rose/message/index.stories.mdx b/addons/rose/addon/components/rose/message/index.stories.mdx index 89447aca1..aeb5e042b 100644 --- a/addons/rose/addon/components/rose/message/index.stories.mdx +++ b/addons/rose/addon/components/rose/message/index.stories.mdx @@ -18,7 +18,7 @@ Title can be configured with optional icon and subtitle. {{description}} - + Go back @@ -33,24 +33,23 @@ Title can be configured with optional icon and subtitle. icon: select( 'icon', { - 'alert-circle-outline': 'alert-circle-outline', - 'help-circle-outline': 'help-circle-outline', - 'disabled': 'disabled', + 'flight-icons/alert-circle-16': 'flight-icons/alert-circle-16', + 'flight-icons/help-16': 'flight-icons/help-16', }, - 'help-circle-outline' + 'flight-icons/help-16' ), }, }} ```html - + You must be granted permissions to view this data. Ask your administrator if you think you should have access. - + Go back Need help? diff --git a/addons/rose/addon/components/rose/notification/index.hbs b/addons/rose/addon/components/rose/notification/index.hbs index 04d60df5f..fc0acf33f 100644 --- a/addons/rose/addon/components/rose/notification/index.hbs +++ b/addons/rose/addon/components/rose/notification/index.hbs @@ -26,7 +26,7 @@ {{on "click" @dismiss}} > {{@dismissText}} diff --git a/addons/rose/addon/components/rose/notification/index.js b/addons/rose/addon/components/rose/notification/index.js index 881d11355..b036bec5d 100644 --- a/addons/rose/addon/components/rose/notification/index.js +++ b/addons/rose/addon/components/rose/notification/index.js @@ -8,17 +8,17 @@ export default class RoseNotificationComponent extends Component { */ @computed('style') get icon() { - let icon = 'info-circle-fill'; + let icon = 'flight-icons/info-16'; switch (this.style) { case 'error': - icon = 'cancel-square-fill'; + icon = 'flight-icons/x-square-16'; break; case 'success': - icon = 'check-circle-fill'; + icon = 'flight-icons/check-circle-16'; break; case 'warning': - icon = 'alert-triangle'; + icon = 'flight-icons/alert-triangle-16'; break; } diff --git a/addons/rose/addon/components/rose/table/index.stories.mdx b/addons/rose/addon/components/rose/table/index.stories.mdx index 444419be4..2b56d4242 100644 --- a/addons/rose/addon/components/rose/table/index.stories.mdx +++ b/addons/rose/addon/components/rose/table/index.stories.mdx @@ -122,7 +122,7 @@ Cell shrink should be applied to all the cells in a row. Otherwise the bigger ce - Remove + Remove diff --git a/addons/rose/index.js b/addons/rose/index.js index 6de73c3ca..ebc5a2673 100644 --- a/addons/rose/index.js +++ b/addons/rose/index.js @@ -10,7 +10,7 @@ module.exports = { this._super.included.apply(this, arguments); this.includeStyles(app); - this.includeIcons(app); + this.includeFlightIcons(app); this.includePublic(app); this.setupSVGO(app); }, @@ -45,8 +45,10 @@ module.exports = { * Finds the structure-icons folder and includes it into the * ember-inline-svg addon. */ - includeIcons(app) { - const iconPackagePath = require.resolve('@hashicorp/structure-icons'); + includeFlightIcons(app) { + const iconPackagePath = path.resolve( + '../../node_modules/@hashicorp/flight-icons' + ); const iconsPath = path.resolve(iconPackagePath, '..'); app.options.svg = app.options.svg || {}; diff --git a/addons/rose/package.json b/addons/rose/package.json index 6e1f5fadb..0e71bbe11 100644 --- a/addons/rose/package.json +++ b/addons/rose/package.json @@ -43,7 +43,7 @@ "@ember/test-helpers": "^2.2.8", "@glimmer/component": "^1.0.3", "@glimmer/tracking": "^1.0.3", - "@hashicorp/structure-icons": "^1.9.0-0", + "@hashicorp/flight-icons": "0.0.6-beta", "@storybook/addon-actions": "^6.3.1", "@storybook/addon-docs": "^6.3.1", "@storybook/addon-knobs": "^6.3.0", @@ -53,7 +53,7 @@ "broccoli-asset-rev": "^3.0.0", "doctoc": "^2.0.0", "ember-auto-import": "^1.10.1", - "ember-cli": "~3.27.0", + "ember-cli": "~3.28.0", "ember-cli-dependency-checker": "^3.2.0", "ember-cli-inject-live-reload": "^2.1.0", "ember-cli-sass": "^10.0.1", diff --git a/addons/rose/tests/dummy/app/templates/playground.hbs b/addons/rose/tests/dummy/app/templates/playground.hbs index e9ace3c02..33694bdca 100644 --- a/addons/rose/tests/dummy/app/templates/playground.hbs +++ b/addons/rose/tests/dummy/app/templates/playground.hbs @@ -19,7 +19,7 @@ Menu item Menu item @@ -82,7 +82,7 @@ - Remove + Remove diff --git a/addons/rose/tests/integration/components/rose/badge-test.js b/addons/rose/tests/integration/components/rose/badge-test.js index 8665085e7..f52964bba 100644 --- a/addons/rose/tests/integration/components/rose/badge-test.js +++ b/addons/rose/tests/integration/components/rose/badge-test.js @@ -17,7 +17,7 @@ module('Integration | Component | rose/badge', function (hooks) { }); test('it renders an icon using @icon', async function (assert) { - await render(hbs``); + await render(hbs``); assert.ok(find('.rose-icon')); }); diff --git a/addons/rose/tests/integration/components/rose/button-test.js b/addons/rose/tests/integration/components/rose/button-test.js index d313e9b0a..cebdc50c3 100644 --- a/addons/rose/tests/integration/components/rose/button-test.js +++ b/addons/rose/tests/integration/components/rose/button-test.js @@ -34,14 +34,20 @@ module('Integration | Component | rose/button', function (hooks) { }); test('it supports left and right icons', async function (assert) { - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('.has-icon-left .rose-icon')); - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('.has-icon-right .rose-icon')); }); test('it supports an icon-only type', async function (assert) { - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('.has-icon-only .rose-icon')); }); }); diff --git a/addons/rose/tests/integration/components/rose/card/link-test.js b/addons/rose/tests/integration/components/rose/card/link-test.js index af9003ef3..fdbfb31ac 100644 --- a/addons/rose/tests/integration/components/rose/card/link-test.js +++ b/addons/rose/tests/integration/components/rose/card/link-test.js @@ -42,7 +42,7 @@ module('Integration | Component | rose/card/link', function (hooks) { test('it renders with @icon', async function (assert) { await render( - hbs`` + hbs`` ); assert.ok(find('.rose-icon')); }); diff --git a/addons/rose/tests/integration/components/rose/dropdown-test.js b/addons/rose/tests/integration/components/rose/dropdown-test.js index 24d4d7758..e94b1f09d 100644 --- a/addons/rose/tests/integration/components/rose/dropdown-test.js +++ b/addons/rose/tests/integration/components/rose/dropdown-test.js @@ -24,7 +24,7 @@ module('Integration | Component | rose/dropdown', function (hooks) { }); test('it supports an icon', async function (assert) { - await render(hbs``); + await render(hbs``); assert.ok(find('svg')); }); diff --git a/addons/rose/tests/integration/components/rose/dropdown/button-test.js b/addons/rose/tests/integration/components/rose/dropdown/button-test.js index 971e378d6..3b1bc1193 100644 --- a/addons/rose/tests/integration/components/rose/dropdown/button-test.js +++ b/addons/rose/tests/integration/components/rose/dropdown/button-test.js @@ -32,7 +32,9 @@ module('Integration | Component | rose/dropdown/button', function (hooks) { }); test('it supports an icon-only type', async function (assert) { - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('.has-icon-only .rose-icon')); }); }); diff --git a/addons/rose/tests/integration/components/rose/form/radio/radio-test.js b/addons/rose/tests/integration/components/rose/form/radio/radio-test.js index 9f1677571..c7117a1e7 100644 --- a/addons/rose/tests/integration/components/rose/form/radio/radio-test.js +++ b/addons/rose/tests/integration/components/rose/form/radio/radio-test.js @@ -18,7 +18,9 @@ module('Integration | Component | rose/form/radio/radio', function (hooks) { }); test('it supports an icon', async function (assert) { - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('svg')); }); diff --git a/addons/rose/tests/integration/components/rose/icon-test.js b/addons/rose/tests/integration/components/rose/icon-test.js index 43a429077..c51b16587 100644 --- a/addons/rose/tests/integration/components/rose/icon-test.js +++ b/addons/rose/tests/integration/components/rose/icon-test.js @@ -7,12 +7,14 @@ module('Integration | Component | rose/icon', function (hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { - await render(hbs``); + await render(hbs``); assert.ok(find('svg')); }); test('it supports optional @size', async function (assert) { - await render(hbs``); + await render( + hbs`` + ); assert.ok(find('.small')); }); }); diff --git a/addons/rose/tests/integration/components/rose/link-button-test.js b/addons/rose/tests/integration/components/rose/link-button-test.js index ac2be94aa..b5d3dbb2f 100644 --- a/addons/rose/tests/integration/components/rose/link-button-test.js +++ b/addons/rose/tests/integration/components/rose/link-button-test.js @@ -35,7 +35,7 @@ module('Integration | Component | rose/link-button', function (hooks) { test('it supports left icon with @iconLeft', async function (assert) { await render( - hbs`` + hbs`` ); assert.ok(find('.rose-icon')); assert.ok(find('.has-icon-left')); @@ -43,7 +43,7 @@ module('Integration | Component | rose/link-button', function (hooks) { test('it supports left icon with @iconRight', async function (assert) { await render( - hbs`` + hbs`` ); assert.ok(find('.rose-icon')); assert.ok(find('.has-icon-right')); @@ -51,7 +51,7 @@ module('Integration | Component | rose/link-button', function (hooks) { test('it supports only icon with @iconOnly', async function (assert) { await render( - hbs`` + hbs`` ); assert.ok(find('.rose-icon')); assert.ok(find('.has-icon-only')); diff --git a/package.json b/package.json index a96317204..d5070c4b8 100755 --- a/package.json +++ b/package.json @@ -76,8 +76,7 @@ "minimist": "^1.2.3", "normalize-url": "^4.5.1", "glob-parent": "^5.1.2", - "tar": "^6.1.2", - "xmldom": "github:xmldom/xmldom#0.7.0", + "tar": "^6.1.9", "path-parse": "^1.0.7" }, "config": { diff --git a/ui/admin/app/components/copyable/index.js b/ui/admin/app/components/copyable/index.js index 09da77365..0957798fe 100644 --- a/ui/admin/app/components/copyable/index.js +++ b/ui/admin/app/components/copyable/index.js @@ -12,8 +12,8 @@ export default class CopyableComponent extends Component { id = generateComponentID(); copyableButtonId = `copyable-button-${this.id}`; - actionIcon = 'copy-action'; - successIcon = 'copy-success'; + actionIcon = 'flight-icons/clipboard-copy-16'; + successIcon = 'flight-icons/clipboard-checked-16'; actionText = this.args.buttonText; successText = this.args.acknowledgeText; diff --git a/ui/admin/app/components/form/auth-method/oidc/index.hbs b/ui/admin/app/components/form/auth-method/oidc/index.hbs index 08c5e87de..cb1707456 100644 --- a/ui/admin/app/components/form/auth-method/oidc/index.hbs +++ b/ui/admin/app/components/form/auth-method/oidc/index.hbs @@ -177,7 +177,7 @@ - + {{t 'actions.back'}} diff --git a/ui/admin/app/components/form/host-set/add-hosts/index.hbs b/ui/admin/app/components/form/host-set/add-hosts/index.hbs index 7c851e376..72adf0902 100644 --- a/ui/admin/app/components/form/host-set/add-hosts/index.hbs +++ b/ui/admin/app/components/form/host-set/add-hosts/index.hbs @@ -55,7 +55,7 @@ - + {{t 'actions.back'}} diff --git a/ui/admin/app/components/form/role/add-principals/index.hbs b/ui/admin/app/components/form/role/add-principals/index.hbs index dc6ad4f5a..1c60623be 100644 --- a/ui/admin/app/components/form/role/add-principals/index.hbs +++ b/ui/admin/app/components/form/role/add-principals/index.hbs @@ -58,7 +58,7 @@ {{t 'resources.role.principal.messages.none.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/components/form/role/grants/index.hbs b/ui/admin/app/components/form/role/grants/index.hbs index 18f1837b9..f3a9e2f1e 100644 --- a/ui/admin/app/components/form/role/grants/index.hbs +++ b/ui/admin/app/components/form/role/grants/index.hbs @@ -74,7 +74,7 @@ diff --git a/ui/admin/app/components/form/role/index.hbs b/ui/admin/app/components/form/role/index.hbs index 725cdc0bf..6bd2cc647 100644 --- a/ui/admin/app/components/form/role/index.hbs +++ b/ui/admin/app/components/form/role/index.hbs @@ -69,9 +69,11 @@ @text={{this.selectedGrantScope.displayName}} @icon={{if this.selectedGrantScope.isProject - 'app-icons/project' + 'flight-icons/grid-16' (if - this.selectedGrantScope.isOrg 'app-icons/org' 'app-icons/global' + this.selectedGrantScope.isOrg + 'flight-icons/org-16' + 'flight-icons/globe-16' ) }} as |dropdown| diff --git a/ui/admin/app/components/form/target/add-credential-libraries/index.hbs b/ui/admin/app/components/form/target/add-credential-libraries/index.hbs index f7f05cf42..628bed983 100644 --- a/ui/admin/app/components/form/target/add-credential-libraries/index.hbs +++ b/ui/admin/app/components/form/target/add-credential-libraries/index.hbs @@ -55,7 +55,7 @@ {{t 'resources.target.credential-library.messages.none.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/components/form/target/add-host-sets/index.hbs b/ui/admin/app/components/form/target/add-host-sets/index.hbs index 0ad80f766..ade5297a6 100644 --- a/ui/admin/app/components/form/target/add-host-sets/index.hbs +++ b/ui/admin/app/components/form/target/add-host-sets/index.hbs @@ -59,7 +59,7 @@ {{t 'resources.target.host-set.messages.none.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/components/form/user/add-accounts/index.hbs b/ui/admin/app/components/form/user/add-accounts/index.hbs index ac93847f7..778fa7993 100644 --- a/ui/admin/app/components/form/user/add-accounts/index.hbs +++ b/ui/admin/app/components/form/user/add-accounts/index.hbs @@ -59,7 +59,7 @@ {{t 'resources.user.messages.no-accounts.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/routes/scopes/scope/auth-methods.js b/ui/admin/app/routes/scopes/scope/auth-methods.js index 31c0778a5..938ce6d16 100644 --- a/ui/admin/app/routes/scopes/scope/auth-methods.js +++ b/ui/admin/app/routes/scopes/scope/auth-methods.js @@ -11,6 +11,7 @@ export default class ScopesScopeAuthMethodsRoute extends Route { @service intl; @service notify; @service session; + @service can; // =methods @@ -26,8 +27,13 @@ export default class ScopesScopeAuthMethodsRoute extends Route { * @return {Promise[AuthMethodModel]} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('auth-method', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if ( + this.can.can('list collection', scope, { collection: 'auth-methods' }) + ) { + return this.store.query('auth-method', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/credential-stores.js b/ui/admin/app/routes/scopes/scope/credential-stores.js index 8bfce1b1d..d49379fcf 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores.js @@ -1,4 +1,5 @@ import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import loading from 'ember-loading/decorator'; import { confirm } from 'core/decorators/confirm'; @@ -6,14 +7,21 @@ import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeCredentialStoresRoute extends Route { // =methods - + @service can; /** * Load all credential stores under current scope * @returns {Promise[CredentialStoreModel]} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('credential-store', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if ( + this.can.can('list collection', scope, { + collection: 'credential-stores', + }) + ) { + return this.store.query('credential-store', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/index.js b/ui/admin/app/routes/scopes/scope/credential-stores/index.js index 99ced4658..57fea4b74 100644 --- a/ui/admin/app/routes/scopes/scope/credential-stores/index.js +++ b/ui/admin/app/routes/scopes/scope/credential-stores/index.js @@ -1,3 +1,10 @@ import Route from '@ember/routing/route'; +export default class ScopesScopeCredentialStoresIndexRoute extends Route { + // =methods -export default class ScopesScopeCredentialStoresIndexRoute extends Route {} + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/routes/scopes/scope/groups.js b/ui/admin/app/routes/scopes/scope/groups.js index 7fa556182..1784799cc 100644 --- a/ui/admin/app/routes/scopes/scope/groups.js +++ b/ui/admin/app/routes/scopes/scope/groups.js @@ -11,7 +11,7 @@ export default class ScopesScopeGroupsRoute extends Route { @service intl; @service notify; @service session; - + @service can; // =methods /** @@ -26,8 +26,11 @@ export default class ScopesScopeGroupsRoute extends Route { * @return {Promise[GroupModel]} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('group', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if (this.can.can('list collection', scope, { collection: 'groups' })) { + return this.store.query('group', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/groups/index.js b/ui/admin/app/routes/scopes/scope/groups/index.js index 7d2a20fb0..22e3d3593 100644 --- a/ui/admin/app/routes/scopes/scope/groups/index.js +++ b/ui/admin/app/routes/scopes/scope/groups/index.js @@ -1,3 +1,10 @@ import Route from '@ember/routing/route'; +export default class ScopesScopeGroupsIndexRoute extends Route { + // =methods -export default class ScopesScopeGroupsIndexRoute extends Route {} + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/routes/scopes/scope/host-catalogs.js b/ui/admin/app/routes/scopes/scope/host-catalogs.js index 53fd92f7a..65da4edc1 100644 --- a/ui/admin/app/routes/scopes/scope/host-catalogs.js +++ b/ui/admin/app/routes/scopes/scope/host-catalogs.js @@ -11,7 +11,7 @@ export default class ScopesScopeHostCatalogsRoute extends Route { @service intl; @service notify; @service session; - + @service can; // =methods /** @@ -26,8 +26,13 @@ export default class ScopesScopeHostCatalogsRoute extends Route { * @return {Promise{[HostCatalogModel]}} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('host-catalog', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if ( + this.can.can('list collection', scope, { collection: 'host-catalogs' }) + ) { + return this.store.query('host-catalog', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/host-catalogs/index.js b/ui/admin/app/routes/scopes/scope/host-catalogs/index.js index 90fba54e3..9261d003a 100644 --- a/ui/admin/app/routes/scopes/scope/host-catalogs/index.js +++ b/ui/admin/app/routes/scopes/scope/host-catalogs/index.js @@ -1,3 +1,9 @@ import Route from '@ember/routing/route'; -export default class ScopesScopeHostCatalogsIndexRoute extends Route {} +export default class ScopesScopeHostCatalogsIndexRoute extends Route { + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/routes/scopes/scope/roles.js b/ui/admin/app/routes/scopes/scope/roles.js index 88d05373b..cbc1dfcc5 100644 --- a/ui/admin/app/routes/scopes/scope/roles.js +++ b/ui/admin/app/routes/scopes/scope/roles.js @@ -11,6 +11,7 @@ export default class ScopesScopeRolesRoute extends Route { @service intl; @service notify; @service session; + @service can; // =methods @@ -26,8 +27,11 @@ export default class ScopesScopeRolesRoute extends Route { * @return {Promise{[RoleModel]}} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('role', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if (this.can.can('list collection', scope, { collection: 'roles' })) { + return this.store.query('role', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/roles/index.js b/ui/admin/app/routes/scopes/scope/roles/index.js index f2a8d7af1..56c143beb 100644 --- a/ui/admin/app/routes/scopes/scope/roles/index.js +++ b/ui/admin/app/routes/scopes/scope/roles/index.js @@ -1,3 +1,10 @@ import Route from '@ember/routing/route'; +export default class ScopesScopeRolesIndexRoute extends Route { + // =methods -export default class ScopesScopeRolesIndexRoute extends Route {} + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/routes/scopes/scope/targets.js b/ui/admin/app/routes/scopes/scope/targets.js index 40cd811bb..2adb5ca84 100644 --- a/ui/admin/app/routes/scopes/scope/targets.js +++ b/ui/admin/app/routes/scopes/scope/targets.js @@ -11,6 +11,7 @@ export default class ScopesScopeTargetsRoute extends Route { @service intl; @service notify; @service session; + @service can; // =methods @@ -26,8 +27,11 @@ export default class ScopesScopeTargetsRoute extends Route { * @return {Promise{[TargetModel]}} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('target', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if (this.can.can('list collection', scope, { collection: 'targets' })) { + return this.store.query('target', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/targets/index.js b/ui/admin/app/routes/scopes/scope/targets/index.js index 2b4412f53..8e92f73d5 100644 --- a/ui/admin/app/routes/scopes/scope/targets/index.js +++ b/ui/admin/app/routes/scopes/scope/targets/index.js @@ -1,3 +1,10 @@ import Route from '@ember/routing/route'; +export default class ScopesScopeTargetsIndexRoute extends Route { + // =methods -export default class ScopesScopeTargetsIndexRoute extends Route {} + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/routes/scopes/scope/users.js b/ui/admin/app/routes/scopes/scope/users.js index 42f9c8832..aa3dde96a 100644 --- a/ui/admin/app/routes/scopes/scope/users.js +++ b/ui/admin/app/routes/scopes/scope/users.js @@ -11,6 +11,7 @@ export default class ScopesScopeUsersRoute extends Route { @service intl; @service notify; @service session; + @service can; // =methods @@ -26,8 +27,11 @@ export default class ScopesScopeUsersRoute extends Route { * @return {Promise{[UserModel]}} */ async model() { - const { id: scope_id } = this.modelFor('scopes.scope'); - return this.store.query('user', { scope_id }); + const scope = this.modelFor('scopes.scope'); + const { id: scope_id } = scope; + if (this.can.can('list collection', scope, { collection: 'users' })) { + return this.store.query('user', { scope_id }); + } } // =actions diff --git a/ui/admin/app/routes/scopes/scope/users/index.js b/ui/admin/app/routes/scopes/scope/users/index.js index f59170106..2e92b693d 100644 --- a/ui/admin/app/routes/scopes/scope/users/index.js +++ b/ui/admin/app/routes/scopes/scope/users/index.js @@ -1,3 +1,11 @@ import Route from '@ember/routing/route'; -export default class ScopesScopeUsersIndexRoute extends Route {} +export default class ScopesScopeUsersIndexRoute extends Route { + // =methods + + setupController(controller) { + const scope = this.modelFor('scopes.scope'); + super.setupController(...arguments); + controller.setProperties({ scope }); + } +} diff --git a/ui/admin/app/styles/app.scss b/ui/admin/app/styles/app.scss index 45d9b4bdc..e8f3d4987 100644 --- a/ui/admin/app/styles/app.scss +++ b/ui/admin/app/styles/app.scss @@ -189,14 +189,6 @@ } } -.doc-link { - .large { - svg { - transform: scale(0.8); - } - } -} - [class*='session-status-'] { color: var(--ui-gray-subtler-2); } diff --git a/ui/admin/app/templates/application.hbs b/ui/admin/app/templates/application.hbs index 9408904ce..daa6f8737 100644 --- a/ui/admin/app/templates/application.hbs +++ b/ui/admin/app/templates/application.hbs @@ -16,7 +16,7 @@ @@ -100,7 +100,7 @@ diff --git a/ui/admin/app/templates/scopes/scope.hbs b/ui/admin/app/templates/scopes/scope.hbs index 65e456c51..ea4ad5347 100644 --- a/ui/admin/app/templates/scopes/scope.hbs +++ b/ui/admin/app/templates/scopes/scope.hbs @@ -18,7 +18,7 @@ {{#if @model.isGlobal}} - + {{t 'resources.org.title_plural'}} @@ -28,12 +28,12 @@ {{#if this.session.data.authenticated.isGlobal}} - + {{t 'resources.org.title_plural'}} {{/if}} - + {{t 'resources.project.title_plural'}} @@ -43,12 +43,12 @@ {{#if this.session.data.authenticated.isGlobal}} - + {{t 'resources.org.title_plural'}} {{/if}} - + {{t 'resources.project.title_plural'}} @@ -58,58 +58,79 @@ {{t "resources.group.title_plural"}} {{t "resources.role.title_plural"}} --}} - - - {{t 'resources.session.title_plural'}} - - - - {{t 'resources.target.title_plural'}} - - - - {{t 'resources.host-catalog.title_plural'}} - - {{#if (feature-flag 'credential-store')}} - - - {{t 'resources.credential-store.title_plural'}} + {{#if (can 'navigate collection' @model collection='sessions')}} + + + {{t 'resources.session.title_plural'}} {{/if}} + {{#if (can 'navigate collection' @model collection='targets')}} + + + {{t 'resources.target.title_plural'}} + + {{/if}} + {{#if (can 'navigate collection' @model collection='host-catalogs')}} + + + {{t 'resources.host-catalog.title_plural'}} + + {{/if}} + {{#if + (can 'navigate collection' @model collection='credential-stores') + }} + {{#if (feature-flag 'credential-store')}} + + + {{t 'resources.credential-store.title_plural'}} + + {{/if}} + {{/if}} {{/if}} {{#unless @model.isProject}} - - - {{t 'resources.user.title_plural'}} - - - - {{t 'resources.group.title_plural'}} - - - - {{t 'resources.role.title_plural'}} - - - - {{t 'resources.auth-method.title_plural'}} - + {{#if (can 'navigate collection' @model collection='users')}} + + + {{t 'resources.user.title_plural'}} + + {{/if}} + {{#if (can 'navigate collection' @model collection='groups')}} + + + {{t 'resources.group.title_plural'}} + + {{/if}} + {{#if (can 'navigate collection' @model collection='roles')}} + + + {{t 'resources.role.title_plural'}} + + {{/if}} + {{#if (can 'navigate collection' @model collection='auth-methods')}} + + + {{t 'resources.auth-method.title_plural'}} + + {{/if}} {{/unless}} diff --git a/ui/admin/app/templates/scopes/scope/-header-nav.hbs b/ui/admin/app/templates/scopes/scope/-header-nav.hbs index ebfc3ffad..cd84e45cc 100644 --- a/ui/admin/app/templates/scopes/scope/-header-nav.hbs +++ b/ui/admin/app/templates/scopes/scope/-header-nav.hbs @@ -2,8 +2,8 @@ @text={{this.scopes.selectedOrg.displayName}} @icon={{if this.scopes.selectedOrg.isGlobal - 'app-icons/global' - 'app-icons/org' + 'flight-icons/globe-16' + 'flight-icons/org-16' }} as |dropdown| > @@ -23,7 +23,7 @@ {{#if this.scopes.selectedProject}} {{#each this.scopes.projects as |scope|}} diff --git a/ui/admin/app/templates/scopes/scope/-sidebar.hbs b/ui/admin/app/templates/scopes/scope/-sidebar.hbs index 3b06e303e..08d4b6b46 100644 --- a/ui/admin/app/templates/scopes/scope/-sidebar.hbs +++ b/ui/admin/app/templates/scopes/scope/-sidebar.hbs @@ -1,18 +1,18 @@ - + {{t 'resources.user.title_plural'}} - + {{t 'resources.group.title_plural'}} - + {{t 'resources.role.title_plural'}} - + {{t 'resources.auth-method.title_plural'}} \ No newline at end of file diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs index cef459d7f..e1e15ecf3 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/-actions.hbs @@ -3,8 +3,10 @@ @text={{t (concat 'states.' @model.attributes.state)}} @icon={{if @model.isInactive - 'disabled' - (if @model.isPrivate 'lock-closed-outline' 'check-circle-outline') + 'flight-icons/x-circle-16' + (if + @model.isPrivate 'flight-icons/lock-16' 'flight-icons/check-circle-16' + ) }} @dropdownRight={{true}} as |dropdown| diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs index c35071bf7..2006e7f52 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/auth-method/accounts/index.hbs @@ -115,7 +115,7 @@ {{t 'resources.account.messages.welcome.description'}} - + {{t 'resources.account.actions.create'}} diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs index 4bd1bd2a4..9297cfd32 100644 --- a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs +++ b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs @@ -12,25 +12,28 @@ - {{#if @model}} - - - {{t 'resources.auth-method.types.password'}} - - - {{t 'resources.auth-method.types.oidc'}} - - + + {{t 'resources.auth-method.types.password'}} + + + {{t 'resources.auth-method.types.oidc'}} + + + {{/if}} {{/if}} @@ -129,7 +132,7 @@ @dropdownRight={{true}} @iconOnly={{true}} @showCaret={{false}} - @icon='more-horizontal' + @icon='flight-icons/more-horizontal-16' as |dropdown| > {{#unless authMethod.isPrimary}} @@ -165,15 +168,38 @@ as |message| > - {{t 'resources.auth-method.messages.welcome.description'}} + {{#if (can 'list collection' this.scope collection='auth-methods')}} + {{! can list (at least): show default welcome message}} + {{t 'resources.auth-method.messages.welcome.description'}} + {{else if (can + 'create collection' this.scope collection='auth-methods' + )}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.auth-method.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.auth-method.title_plural') + }} + {{/if}} - + {{t 'titles.new'}} + {{#if (can 'create collection' this.scope collection='auth-methods')}} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/authenticate.hbs b/ui/admin/app/templates/scopes/scope/authenticate.hbs index 55977a188..bf7f33f0a 100644 --- a/ui/admin/app/templates/scopes/scope/authenticate.hbs +++ b/ui/admin/app/templates/scopes/scope/authenticate.hbs @@ -16,7 +16,7 @@ }}

@@ -79,7 +79,7 @@ diff --git a/ui/admin/app/templates/scopes/scope/authenticate/index.hbs b/ui/admin/app/templates/scopes/scope/authenticate/index.hbs index b8dbc824f..fa5633bb1 100644 --- a/ui/admin/app/templates/scopes/scope/authenticate/index.hbs +++ b/ui/admin/app/templates/scopes/scope/authenticate/index.hbs @@ -2,7 +2,7 @@ diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/credential-libraries/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/credential-libraries/index.hbs index 2bb3101c2..56d73cdcb 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/credential-libraries/index.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/credential-store/credential-libraries/index.hbs @@ -58,7 +58,7 @@ - + {{t 'titles.new'}} diff --git a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs index faa489b0b..8c7a002d0 100644 --- a/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs +++ b/ui/admin/app/templates/scopes/scope/credential-stores/index.hbs @@ -14,13 +14,16 @@ - {{#if @model}} - - {{t 'titles.new'}} - + + {{#if (can 'create collection' this.scope collection='credential-stores')}} + {{#if @model}} + + {{t 'titles.new'}} + + {{/if}} {{/if}} @@ -79,12 +82,35 @@ as |message| > - {{t 'resources.credential-store.description'}} + {{#if + (can 'list collection' this.scope collection='credential-stores') + }} + {{! can list (at least): show default welcome message}} + {{t 'resources.credential-store.description'}} + {{else if (can + 'create collection' this.scope collection='credential-stores' + )}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.credential-store.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.user.title_plural') + }} + {{/if}} - - - {{t 'titles.new'}} - + {{#if + (can 'create collection' this.scope collection='credential-stores') + }} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/groups/group/members.hbs b/ui/admin/app/templates/scopes/scope/groups/group/members.hbs index a6512ef59..3979e762a 100644 --- a/ui/admin/app/templates/scopes/scope/groups/group/members.hbs +++ b/ui/admin/app/templates/scopes/scope/groups/group/members.hbs @@ -27,7 +27,7 @@ - + {{t 'resources.group.actions.add-members'}} diff --git a/ui/admin/app/templates/scopes/scope/groups/index.hbs b/ui/admin/app/templates/scopes/scope/groups/index.hbs index cb59fde2e..1e5f038db 100644 --- a/ui/admin/app/templates/scopes/scope/groups/index.hbs +++ b/ui/admin/app/templates/scopes/scope/groups/index.hbs @@ -13,10 +13,12 @@ - {{#if @model}} - {{t - 'titles.new' - }} + {{#if (can 'create collection' this.scope collection='groups')}} + {{#if @model}} + {{t + 'titles.new' + }} + {{/if}} {{/if}} @@ -70,11 +72,29 @@ > {{t 'resources.group.description'}} + {{#if (can 'list collection' this.scope collection='groups')}} + {{! can list (at least): show default welcome message}} + {{t 'resources.group.description'}} + {{else if (can 'create collection' this.scope collection='groups')}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.group.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.group.title_plural') + }} + {{/if}} - - - {{t 'titles.new'}} - + {{#if (can 'create collection' this.scope collection='groups')}} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs index c4a93ee5c..351fb19d7 100644 --- a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs +++ b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/host-set/hosts.hbs @@ -37,7 +37,7 @@ {{!-- - + {{t "resources.host-set.actions.create-and-add-host"}} --}} diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs index 735dd94e4..1b0a18cb8 100644 --- a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs +++ b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/host-sets/index.hbs @@ -56,7 +56,7 @@ - + {{t 'titles.new'}} diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs index 262a32a79..6687cbf76 100644 --- a/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs +++ b/ui/admin/app/templates/scopes/scope/host-catalogs/host-catalog/hosts/index.hbs @@ -58,7 +58,7 @@ {{t 'resources.host.description'}} - + {{t 'titles.new'}} diff --git a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs index 734825303..11e065743 100644 --- a/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs +++ b/ui/admin/app/templates/scopes/scope/host-catalogs/index.hbs @@ -15,13 +15,15 @@ - {{#if @model}} - - {{t 'titles.new'}} - + {{#if (can 'create collection' this.scope collection='host-catalogs')}} + {{#if @model}} + + {{t 'titles.new'}} + + {{/if}} {{/if}} @@ -82,12 +84,35 @@ as |message| > - {{t 'resources.host-catalog.description'}} + {{#if + (can 'list collection' this.scope collection='host-catalogs') + }} + {{! can list (at least): show default welcome message}} + {{t 'resources.host-catalog.description'}} + {{else if (can + 'create collection' this.scope collection='host-catalogs' + )}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.host-catalog.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.host-catalog.title_plural') + }} + {{/if}} - - - {{t 'titles.new'}} - + {{#if + (can 'create collection' this.scope collection='host-catalogs') + }} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/roles/index.hbs b/ui/admin/app/templates/scopes/scope/roles/index.hbs index d69351c8e..241093ea4 100644 --- a/ui/admin/app/templates/scopes/scope/roles/index.hbs +++ b/ui/admin/app/templates/scopes/scope/roles/index.hbs @@ -15,10 +15,12 @@ - {{#if @model}} - {{t - 'titles.new' - }} + {{#if (can 'create collection' this.scope collection='roles')}} + {{#if @model}} + {{t + 'titles.new' + }} + {{/if}} {{/if}} @@ -68,12 +70,29 @@ as |message| > - {{t 'resources.role.description'}} + {{#if (can 'list collection' this.scope collection='roles')}} + {{! can list (at least): show default welcome message}} + {{t 'resources.roles.description'}} + {{else if (can 'create collection' this.scope collection='roles')}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.role.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.role.title_plural') + }} + {{/if}} - - - {{t 'titles.new'}} - + {{#if (can 'create collection' this.scope collection='roles')}} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/roles/role/principals.hbs b/ui/admin/app/templates/scopes/scope/roles/role/principals.hbs index 03d497c2a..5086502f0 100644 --- a/ui/admin/app/templates/scopes/scope/roles/role/principals.hbs +++ b/ui/admin/app/templates/scopes/scope/roles/role/principals.hbs @@ -31,7 +31,7 @@ - + {{t 'resources.role.principal.actions.add-principals'}} diff --git a/ui/admin/app/templates/scopes/scope/scopes/index.hbs b/ui/admin/app/templates/scopes/scope/scopes/index.hbs index 93df2c2cd..19a4168d5 100644 --- a/ui/admin/app/templates/scopes/scope/scopes/index.hbs +++ b/ui/admin/app/templates/scopes/scope/scopes/index.hbs @@ -43,7 +43,11 @@ @title={{scope.name}} @description={{scope.description}} @id={{scope.id}} - @icon={{if scope.isOrg 'app-icons/org' 'app-icons/project'}} + @icon={{if + scope.isOrg + 'flight-icons/org-16' + 'flight-icons/grid-16' + }} @route='scopes.scope' @model={{scope.id}} /> @@ -62,7 +66,7 @@ {{t 'resources.org.description'}} - + {{t 'titles.new'}} @@ -79,7 +83,7 @@ {{t 'resources.project.description'}} - + {{t 'titles.new'}} diff --git a/ui/admin/app/templates/scopes/scope/sessions/index.hbs b/ui/admin/app/templates/scopes/scope/sessions/index.hbs index d97fc2fd0..4e00d0eff 100644 --- a/ui/admin/app/templates/scopes/scope/sessions/index.hbs +++ b/ui/admin/app/templates/scopes/scope/sessions/index.hbs @@ -36,7 +36,7 @@ 'session-status-' sessionAggregate.session.status }} - @name='app-icons/action-session' + @name='flight-icons/entry-point-16' @size='medium' /> - {{#if @model}} - - {{t 'titles.new'}} - + {{#if (can 'create collection' this.scope collection='targets')}} + {{#if @model}} + {{t + 'titles.new' + }} + {{/if}} {{/if}} - {{#if @model}} @@ -79,12 +80,34 @@ as |message| > - {{t 'resources.target.description'}} + + {{#if (can 'list collection' this.scope collection='targets')}} + {{! can list (at least): show default welcome message}} + {{t 'resources.target.description'}} + {{else if (can + 'create collection' this.scope collection='targets' + )}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.target.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.target.title_plural') + }} + + {{/if}} - - - {{t 'titles.new'}} - + + {{#if (can 'create collection' this.scope collection='targets')}} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/add-credential-libraries.hbs b/ui/admin/app/templates/scopes/scope/targets/target/add-credential-libraries.hbs index e4573894c..a4188a78e 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/add-credential-libraries.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/add-credential-libraries.hbs @@ -19,7 +19,7 @@ {{t 'resources.target.credential-library.messages.none.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/add-host-sets.hbs b/ui/admin/app/templates/scopes/scope/targets/target/add-host-sets.hbs index ddf08b109..af5d5921a 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/add-host-sets.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/add-host-sets.hbs @@ -20,7 +20,7 @@ {{t 'resources.target.host-set.messages.none.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs b/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs index 14d0b4d90..87284cafe 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/credential-libraries.hbs @@ -44,7 +44,7 @@ - + {{t 'resources.target.actions.add-credential-libraries'}} diff --git a/ui/admin/app/templates/scopes/scope/targets/target/host-sets.hbs b/ui/admin/app/templates/scopes/scope/targets/target/host-sets.hbs index ad9f10154..b123d74d3 100644 --- a/ui/admin/app/templates/scopes/scope/targets/target/host-sets.hbs +++ b/ui/admin/app/templates/scopes/scope/targets/target/host-sets.hbs @@ -34,7 +34,7 @@ - + {{t 'resources.target.actions.add-host-sets'}} diff --git a/ui/admin/app/templates/scopes/scope/users/index.hbs b/ui/admin/app/templates/scopes/scope/users/index.hbs index ab31bc1cf..fdc93dbb3 100644 --- a/ui/admin/app/templates/scopes/scope/users/index.hbs +++ b/ui/admin/app/templates/scopes/scope/users/index.hbs @@ -15,10 +15,12 @@ - {{#if @model}} - {{t - 'titles.new' - }} + {{#if (can 'create collection' this.scope collection='users')}} + {{#if @model}} + {{t + 'titles.new' + }} + {{/if}} {{/if}} @@ -68,12 +70,29 @@ as |message| > - {{t 'resources.user.description'}} + {{#if (can 'list collection' this.scope collection='users')}} + {{! can list (at least): show default welcome message}} + {{t 'resources.user.description'}} + {{else if (can 'create collection' this.scope collection='users')}} + {{! can create (only): show create-but-not-list welcome message}} + {{t + 'descriptions.create-but-not-list' + resource=(t 'resources.user.title_plural') + }} + {{else}} + {{! can neither list nor create }} + {{t + 'descriptions.neither-list-nor-create' + resource=(t 'resources.user.title_plural') + }} + {{/if}} - - - {{t 'titles.new'}} - + {{#if (can 'create collection' this.scope collection='users')}} + + + {{t 'titles.new'}} + + {{/if}} diff --git a/ui/admin/app/templates/scopes/scope/users/user/accounts.hbs b/ui/admin/app/templates/scopes/scope/users/user/accounts.hbs index ed9f6cd24..369e3c08b 100644 --- a/ui/admin/app/templates/scopes/scope/users/user/accounts.hbs +++ b/ui/admin/app/templates/scopes/scope/users/user/accounts.hbs @@ -34,7 +34,7 @@ - + {{t 'resources.user.actions.add-accounts'}} diff --git a/ui/admin/app/templates/scopes/scope/users/user/add-accounts.hbs b/ui/admin/app/templates/scopes/scope/users/user/add-accounts.hbs index 5d79b28c8..3ded8d49b 100644 --- a/ui/admin/app/templates/scopes/scope/users/user/add-accounts.hbs +++ b/ui/admin/app/templates/scopes/scope/users/user/add-accounts.hbs @@ -20,7 +20,7 @@ {{t 'resources.user.messages.no-accounts.description'}} - + {{t 'actions.back'}} diff --git a/ui/admin/package.json b/ui/admin/package.json index bc9e5b2b6..22cddb938 100644 --- a/ui/admin/package.json +++ b/ui/admin/package.json @@ -50,7 +50,7 @@ "ember-a11y-testing": "^4.0.7", "ember-auto-import": "^1.10.1", "ember-breadcrumbs": "^0.2.3", - "ember-cli": "~3.27.0", + "ember-cli": "~3.28.0", "ember-cli-app-version": "^5.0.0", "ember-cli-babel": "^7.23.0", "ember-cli-code-coverage": "^1.0.2", diff --git a/ui/admin/tests/acceptance/auth-methods-test.js b/ui/admin/tests/acceptance/auth-methods/create-test.js similarity index 68% rename from ui/admin/tests/acceptance/auth-methods-test.js rename to ui/admin/tests/acceptance/auth-methods/create-test.js index 61d8071a3..684984999 100644 --- a/ui/admin/tests/acceptance/auth-methods-test.js +++ b/ui/admin/tests/acceptance/auth-methods/create-test.js @@ -2,7 +2,6 @@ import { module, test } from 'qunit'; import { visit, currentURL, click, find, fillIn } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; -import a11yAudit from 'ember-a11y-testing/test-support/audit'; import { Response } from 'miragejs'; import { authenticateSession, @@ -12,7 +11,7 @@ import { } from 'ember-simple-auth/test-support'; import { enableFeature } from 'ember-feature-flags/test-support'; -module('Acceptance | auth methods', function (hooks) { +module('Acceptance | auth-methods | create ', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -20,9 +19,12 @@ module('Acceptance | auth methods', function (hooks) { scopes: { global: null, org: null, + project: null, }, authMethod: null, + orgScope: null, }; + const urls = { orgScope: null, authMethods: null, @@ -31,58 +33,33 @@ module('Acceptance | auth methods', function (hooks) { }; hooks.beforeEach(function () { - // Setup Mirage mock resources for this test authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.orgScope.id, type: instances.orgScope.type }, }); + instances.authMethod = this.server.create('auth-method', { - scope: instances.scopes.org, + scope: instances.orgScope, }); // Generate route URLs for resources - urls.orgScope = `/scopes/${instances.scopes.org.id}`; + urls.orgScope = `/scopes/${instances.orgScope.id}`; urls.authMethods = `${urls.orgScope}/auth-methods`; urls.newAuthMethod = `${urls.authMethods}/new?type=password`; urls.authMethod = `${urls.authMethods}/${instances.authMethod.id}`; }); - test('visiting auth methods', async function (assert) { - assert.expect(1); - await visit(urls.authMethods); - await a11yAudit(); - assert.equal(currentURL(), urls.authMethods); - }); - - test('can navigate to an auth method form', async function (assert) { - assert.expect(1); - await visit(urls.authMethods); - await click('main tbody .rose-table-header-cell:nth-child(1) a'); - await a11yAudit(); - assert.equal(currentURL(), urls.authMethod); - }); - - test('can update an auth method and save changes', async function (assert) { - assert.expect(1); - await visit(urls.authMethod); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'update name'); - await click('form [type="submit"]:not(:disabled)'); - assert.equal(this.server.db.authMethods[0].name, 'update name'); - }); - - test('can update an auth method and cancel changes', async function (assert) { - assert.expect(1); - await visit(urls.authMethod); - await click('form [type="button"]', 'Activate edit mode'); - await fillIn('[name="name"]', 'update name'); - await click('form button:not([type="submit"])'); - assert.notEqual(this.server.db.authMethods[0].name, 'update name'); - }); - - test('can create new auth method', async function (assert) { + test('Users can create new auth method', async function (assert) { assert.expect(1); const authMethodsCount = this.server.db.authMethods.length; await visit(urls.newAuthMethod); @@ -92,6 +69,33 @@ module('Acceptance | auth methods', function (hooks) { assert.equal(this.server.db.authMethods.length, authMethodsCount + 1); }); + test('Users can navigate to new auth-methods route with proper authorization', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions['auth-methods'] = [ + 'create', + 'list', + ]; + await visit(urls.orgScope); + assert.ok( + instances.orgScope.authorized_collection_actions['auth-methods'].includes( + 'create' + ) + ); + assert.ok(find(`[href="${urls.authMethods}"]`)); + }); + + test('Users cannot navigate to new auth-methods route without proper authorization', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions['auth-methods'] = []; + await visit(urls.orgScope); + assert.notOk( + instances.orgScope.authorized_collection_actions['auth-methods'].includes( + 'create' + ) + ); + assert.notOk(find(`[href="${urls.authMethods}"]`)); + }); + test('can cancel new auth method creation', async function (assert) { assert.expect(2); const authMethodsCount = this.server.db.authMethods.length; @@ -106,7 +110,7 @@ module('Acceptance | auth methods', function (hooks) { test('user can make primary an auth method', async function (assert) { assert.expect(2); assert.notOk( - instances.scopes.org.primaryAuthMethodId, + instances.orgScope.primaryAuthMethodId, 'Primary auth method is not yet set.' ); enableFeature('primary-auth-method'); @@ -114,7 +118,7 @@ module('Acceptance | auth methods', function (hooks) { await click( '.rose-layout-page-actions .rose-dropdown-content [type="button"]:first-child' ); - const scope = this.server.schema.scopes.find(instances.scopes.org.id); + const scope = this.server.schema.scopes.find(instances.orgScope.id); assert.equal( scope.primaryAuthMethodId, instances.authMethod.id, @@ -136,7 +140,7 @@ module('Acceptance | auth methods', function (hooks) { ); }); assert.notOk( - instances.scopes.org.primaryAuthMethodId, + instances.orgScope.primaryAuthMethodId, 'Primary auth method is not yet set.' ); enableFeature('primary-auth-method'); @@ -149,11 +153,11 @@ module('Acceptance | auth methods', function (hooks) { test('user can remove as primary an auth method', async function (assert) { assert.expect(2); - instances.scopes.org.update({ + instances.orgScope.update({ primaryAuthMethodId: instances.authMethod.id, }); assert.ok( - instances.scopes.org.primaryAuthMethodId, + instances.orgScope.primaryAuthMethodId, 'Primary auth method is set.' ); enableFeature('primary-auth-method'); @@ -161,7 +165,7 @@ module('Acceptance | auth methods', function (hooks) { await click( '.rose-layout-page-actions .rose-dropdown-content [type="button"]:first-child' ); - const scope = this.server.schema.scopes.find(instances.scopes.org.id); + const scope = this.server.schema.scopes.find(instances.orgScope.id); assert.notOk(scope.primaryAuthMethodId, 'Primary auth method is unset.'); }); @@ -178,11 +182,11 @@ module('Acceptance | auth methods', function (hooks) { } ); }); - instances.scopes.org.update({ + instances.orgScope.update({ primaryAuthMethodId: instances.authMethod.id, }); assert.ok( - instances.scopes.org.primaryAuthMethodId, + instances.orgScope.primaryAuthMethodId, 'Primary auth method is set.' ); enableFeature('primary-auth-method'); @@ -196,7 +200,7 @@ module('Acceptance | auth methods', function (hooks) { test('user can make and remove primary auth methods from index', async function (assert) { assert.expect(3); assert.notOk( - instances.scopes.org.primaryAuthMethodId, + instances.orgScope.primaryAuthMethodId, 'Primary auth method is not yet set.' ); enableFeature('primary-auth-method'); @@ -204,7 +208,7 @@ module('Acceptance | auth methods', function (hooks) { await click( '.rose-table-body .rose-table-row:first-child .rose-dropdown-content [type="button"]:first-child' ); - let scope = this.server.schema.scopes.find(instances.scopes.org.id); + let scope = this.server.schema.scopes.find(instances.orgScope.id); assert.equal( scope.primaryAuthMethodId, instances.authMethod.id, @@ -213,7 +217,7 @@ module('Acceptance | auth methods', function (hooks) { await click( '.rose-table-body .rose-table-row:first-child .rose-dropdown-content [type="button"]:first-child' ); - scope = this.server.schema.scopes.find(instances.scopes.org.id); + scope = this.server.schema.scopes.find(instances.orgScope.id); assert.notOk(scope.primaryAuthMethodId, 'Primary auth method is unset.'); }); }); diff --git a/ui/admin/tests/acceptance/auth-methods/list-test.js b/ui/admin/tests/acceptance/auth-methods/list-test.js new file mode 100644 index 000000000..385c8cb1a --- /dev/null +++ b/ui/admin/tests/acceptance/auth-methods/list-test.js @@ -0,0 +1,79 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | auth-methods | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + }, + authMethods: null, + orgScope: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + + urls.orgScope = `/scopes/${instances.orgScope.id}`; + urls.authMethods = `/scopes/${instances.orgScope.id}/auth-methods`; + authenticateSession({}); + }); + + test('Users can navigate to auth methods with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.orgScope); + assert.ok( + instances.orgScope.authorized_collection_actions['auth-methods'].includes( + 'list' + ) + ); + assert.ok(find(`[href="${urls.authMethods}"]`)); + }); + + test('Users cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions['auth-methods'] = []; + await visit(urls.orgScope); + assert.notOk( + instances.orgScope.authorized_collection_actions['auth-methods'].includes( + 'list' + ) + ); + assert.notOk(find(`[href="${urls.authMethods}"]`)); + }); + + test('User can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.orgScope.authorized_collection_actions['auth-methods'] = [ + 'create', + ]; + await visit(urls.orgScope); + assert.ok(find(`[href="${urls.authMethods}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/credential-stores-test.js b/ui/admin/tests/acceptance/credential-store/create-test.js similarity index 82% rename from ui/admin/tests/acceptance/credential-stores-test.js rename to ui/admin/tests/acceptance/credential-store/create-test.js index 54764b5a3..e651a641b 100644 --- a/ui/admin/tests/acceptance/credential-stores-test.js +++ b/ui/admin/tests/acceptance/credential-store/create-test.js @@ -5,7 +5,7 @@ import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; import { authenticateSession } from 'ember-simple-auth/test-support'; import { Response } from 'miragejs'; -module('Acceptance | credential-stores', function (hooks) { +module('Acceptance | credential-stores | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -21,7 +21,6 @@ module('Acceptance | credential-stores', function (hooks) { const urls = { globalScope: null, - orgScope: null, projectScope: null, credentialStores: null, credentialStore: null, @@ -45,7 +44,6 @@ module('Acceptance | credential-stores', function (hooks) { }); // Generate route URLs for resources urls.globalScope = `/scopes/global/scopes`; - urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; urls.projectScope = `/scopes/${instances.scopes.project.id}`; urls.credentialStores = `${urls.projectScope}/credential-stores`; urls.credentialStore = `${urls.credentialStores}/${instances.credentialStore.id}`; @@ -58,7 +56,7 @@ module('Acceptance | credential-stores', function (hooks) { authenticateSession({}); }); - test('can create a new credential stores', async function (assert) { + test('Users can create a new credential stores', async function (assert) { assert.expect(1); const count = getCredentialStoresCount(); await visit(urls.newCredentialStore); @@ -67,7 +65,7 @@ module('Acceptance | credential-stores', function (hooks) { assert.equal(getCredentialStoresCount(), count + 1); }); - test('can cancel create new credential stores', async function (assert) { + test('Users can cancel create new credential stores', async function (assert) { assert.expect(2); const count = getCredentialStoresCount(); await visit(urls.newCredentialStore); @@ -77,6 +75,20 @@ module('Acceptance | credential-stores', function (hooks) { assert.equal(getCredentialStoresCount(), count); }); + test('Users cannot navigate to new credential stores route without proper authorization', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ] = []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ].includes('create') + ); + assert.notOk(find(`[href="${urls.credentialStores}"]`)); + }); + test('saving a new credential store with invalid fields displays error messages', async function (assert) { assert.expect(2); this.server.post('/credential-stores', () => { diff --git a/ui/admin/tests/acceptance/credential-store/list-test.js b/ui/admin/tests/acceptance/credential-store/list-test.js new file mode 100644 index 000000000..e4d6cda15 --- /dev/null +++ b/ui/admin/tests/acceptance/credential-store/list-test.js @@ -0,0 +1,84 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | credential-stores | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + }; + + const urls = { + scopes: { + org: null, + }, + projectScope: null, + credentialStores: null, + credentialStore: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.credentialStore = this.server.create('credential-store', { + scope: instances.scopes.project, + }); + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.credentialStores = `${urls.projectScope}/credential-stores`; + authenticateSession({}); + }); + + test('Users can navigate to credential-stores with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + assert.ok( + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ].includes('list') + ); + assert.ok(find(`[href="${urls.credentialStores}"]`)); + }); + + test('Users cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ] = []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ].includes('list') + ); + assert.notOk(find(`[href="${urls.credentialStores}"]`)); + }); + + test('Users can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.scopes.project.authorized_collection_actions[ + 'credential-stores' + ] = ['create']; + await visit(urls.projectScope); + assert.ok(find(`[href="${urls.credentialStores}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/groups-test.js b/ui/admin/tests/acceptance/groups/create-test.js similarity index 71% rename from ui/admin/tests/acceptance/groups-test.js rename to ui/admin/tests/acceptance/groups/create-test.js index 38b95d60d..815e4a760 100644 --- a/ui/admin/tests/acceptance/groups-test.js +++ b/ui/admin/tests/acceptance/groups/create-test.js @@ -10,9 +10,10 @@ import { //invalidateSession, } from 'ember-simple-auth/test-support'; -module('Acceptance | groups', function (hooks) { +module('Acceptance | groups | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); + let orgURL; const instances = { scopes: { @@ -20,9 +21,9 @@ module('Acceptance | groups', function (hooks) { org: null, }, group: null, + orgScope: null, }; const urls = { - orgScope: null, groups: null, group: null, newGroup: null, @@ -30,17 +31,21 @@ module('Acceptance | groups', function (hooks) { hooks.beforeEach(function () { authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); instances.group = this.server.create('group', { - scope: instances.scopes.org, + scope: instances.orgScope, }); - urls.groups = `/scopes/${instances.scopes.org.id}/groups`; + urls.groups = `/scopes/${instances.orgScope.id}/groups`; urls.group = `${urls.groups}/${instances.group.id}`; urls.newGroup = `${urls.groups}/new`; + orgURL = `/scopes/${instances.orgScope.id}`; }); test('can create new group', async function (assert) { @@ -52,6 +57,24 @@ module('Acceptance | groups', function (hooks) { assert.equal(this.server.db.groups.length, groupsCount + 1); }); + test('can navigate to new groups route with proper authorization', async function (assert) { + assert.expect(2); + await visit(orgURL); + assert.ok( + instances.orgScope.authorized_collection_actions.groups.includes('create') + ); + assert.ok(find(`[href="${urls.groups}"]`)); + }); + + test('cannot navigate to new groups route without proper authorization', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions.groups = []; + await visit(orgURL); + assert.notOk( + instances.orgScope.authorized_collection_actions.groups.includes('create') + ); + assert.notOk(find(`[href="${urls.groups}"]`)); + }); test('can cancel new group creation', async function (assert) { assert.expect(2); const groupsCount = this.server.db.groups.length; diff --git a/ui/admin/tests/acceptance/groups/list-test.js b/ui/admin/tests/acceptance/groups/list-test.js new file mode 100644 index 000000000..f9229c19d --- /dev/null +++ b/ui/admin/tests/acceptance/groups/list-test.js @@ -0,0 +1,76 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | groups | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + let orgURL; + + const instances = { + scopes: { + global: null, + org: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + }, + groups: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + instances.group = this.server.create('group', { + scope: instances.orgScope, + }); + orgURL = `/scopes/${instances.orgScope.id}`; + + urls.groups = `/scopes/${instances.orgScope.id}/groups`; + authenticateSession({}); + }); + + test('can navigate to groups with proper authorization', async function (assert) { + assert.expect(2); + await visit(orgURL); + assert.ok( + instances.orgScope.authorized_collection_actions.groups.includes('list') + ); + assert.ok(find(`[href="${urls.groups}"]`)); + }); + + test('User cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions.groups = []; + await visit(orgURL); + assert.notOk( + instances.orgScope.authorized_collection_actions.groups.includes('list') + ); + assert.notOk(find(`[href="${urls.groups}"]`)); + }); + + test('User can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.orgScope.authorized_collection_actions.groups = ['create']; + await visit(orgURL); + assert.ok(find(`[href="${urls.groups}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/host-catalogs-test.js b/ui/admin/tests/acceptance/host-catalogs/create-test.js similarity index 71% rename from ui/admin/tests/acceptance/host-catalogs-test.js rename to ui/admin/tests/acceptance/host-catalogs/create-test.js index fea885978..e95ecbde0 100644 --- a/ui/admin/tests/acceptance/host-catalogs-test.js +++ b/ui/admin/tests/acceptance/host-catalogs/create-test.js @@ -10,7 +10,7 @@ import { //invalidateSession, } from 'ember-simple-auth/test-support'; -module('Acceptance | host-catalogs', function (hooks) { +module('Acceptance | host-catalogs | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -22,6 +22,7 @@ module('Acceptance | host-catalogs', function (hooks) { org: null, project: null, }, + orgScope: null, }; const urls = { globalScope: null, @@ -35,6 +36,14 @@ module('Acceptance | host-catalogs', function (hooks) { hooks.beforeEach(function () { // Generate resources instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); instances.scopes.org = this.server.create('scope', { type: 'org', scope: { id: 'global', type: 'global' }, @@ -46,21 +55,23 @@ module('Acceptance | host-catalogs', function (hooks) { instances.hostCatalog = this.server.create('host-catalog', { scope: instances.scopes.project, }); + // Generate route URLs for resources urls.globalScope = `/scopes/global/scopes`; - urls.orgScope = `/scopes/${instances.scopes.org.id}/scopes`; + urls.orgScope = `/scopes/${instances.orgScope.id}/scopes`; urls.projectScope = `/scopes/${instances.scopes.project.id}`; urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; - urls.unknownHostCatalog = `${urls.hostCatalogs}/foo`; urls.newHostCatalog = `${urls.hostCatalogs}/new`; // Generate resource couner gethostCatalogCount = () => this.server.schema.hostCatalogs.all().models.length; + authenticateSession({}); }); - test('can create new host catalogs', async function (assert) { + test('Users can create new host catalogs', async function (assert) { assert.expect(1); const count = gethostCatalogCount(); await visit(urls.newHostCatalog); @@ -69,7 +80,7 @@ module('Acceptance | host-catalogs', function (hooks) { assert.equal(gethostCatalogCount(), count + 1); }); - test('can cancel create new host catalogs', async function (assert) { + test('Users can cancel create new host catalogs', async function (assert) { assert.expect(2); const count = gethostCatalogCount(); await visit(urls.newHostCatalog); @@ -79,6 +90,30 @@ module('Acceptance | host-catalogs', function (hooks) { assert.equal(gethostCatalogCount(), count); }); + test('Users can navigate to new host catalogs route with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + assert.ok( + instances.scopes.project.authorized_collection_actions[ + 'host-catalogs' + ].includes('create') + ); + assert.ok(find(`[href="${urls.hostCatalogs}"]`)); + }); + + test('Users cannot navigate to new host catalogs route without proper authorization', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions['host-catalogs'] = + []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions[ + 'host-catalogs' + ].includes('create') + ); + assert.notOk(find(`[href="${urls.hostCatalogs}"]`)); + }); + test('saving a new host catalog with invalid fields displays error messages', async function (assert) { assert.expect(2); this.server.post('/host-catalogs', () => { diff --git a/ui/admin/tests/acceptance/host-catalogs/list-test.js b/ui/admin/tests/acceptance/host-catalogs/list-test.js new file mode 100644 index 000000000..6cf508e20 --- /dev/null +++ b/ui/admin/tests/acceptance/host-catalogs/list-test.js @@ -0,0 +1,97 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | host-catalogs | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + project: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + }, + projectScope: null, + hostCatalogs: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + instances.scopes.org = this.server.create('scope', { + type: 'org', + scope: { id: 'global', type: 'global' }, + }); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.scopes.org.id, type: 'org' }, + }); + instances.hostCatalog = this.server.create('host-catalog', { + scope: instances.scopes.project, + }); + + urls.hostCatalogs = `/scopes/${instances.orgScope.id}/host-catalogs`; + urls.globalScope = `/scopes/global/scopes`; + urls.orgScope = `/scopes/${instances.orgScope.id}/scopes`; + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.hostCatalogs = `${urls.projectScope}/host-catalogs`; + + urls.hostCatalog = `${urls.hostCatalogs}/${instances.hostCatalog.id}`; + authenticateSession({}); + }); + + test('Users can navigate to host catalogs with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + assert.ok( + instances.scopes.project.authorized_collection_actions[ + 'host-catalogs' + ].includes('list') + ); + assert.ok(find(`[href="${urls.hostCatalogs}"]`)); + }); + + test('User cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions['host-catalogs'] = + []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions[ + 'host-catalogs' + ].includes('list') + ); + assert.notOk(find(`[href="${urls.hostCatalogs}"]`)); + }); + + test('User can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.scopes.project.authorized_collection_actions['host-catalogs'] = [ + 'create', + ]; + await visit(urls.projectScope); + assert.ok(find(`[href="${urls.hostCatalogs}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/roles-test.js b/ui/admin/tests/acceptance/roles/create-test.js similarity index 70% rename from ui/admin/tests/acceptance/roles-test.js rename to ui/admin/tests/acceptance/roles/create-test.js index 77b971f46..a0564f67d 100644 --- a/ui/admin/tests/acceptance/roles-test.js +++ b/ui/admin/tests/acceptance/roles/create-test.js @@ -11,7 +11,7 @@ import { //invalidateSession, } from 'ember-simple-auth/test-support'; -module('Acceptance | roles', function (hooks) { +module('Acceptance | roles | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -22,38 +22,44 @@ module('Acceptance | roles', function (hooks) { project: null, }, role: null, + orgScope: null, }; const urls = { - orgScope: null, roles: null, role: null, newRole: null, + orgScope: null, }; hooks.beforeEach(function () { authenticateSession({}); - instances.scopes.global = this.server.create('scope', { id: 'global' }); - instances.scopes.org = this.server.create('scope', { - type: 'org', - scope: { id: 'global', type: 'global' }, - }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + // The project scope is not yet used for role tests (though it will be // in the future). This is created simply to test the grant scope loading // mechanism. instances.scopes.project = this.server.create('scope', { type: 'project', - scope: { id: instances.scopes.org.id, type: instances.scopes.org.type }, + scope: { id: instances.orgScope.id, type: instances.orgScope.type }, }); instances.role = this.server.create( 'role', { - scope: instances.scopes.org, + scope: instances.orgScope, }, 'withPrincipals' ); - urls.roles = `/scopes/${instances.scopes.org.id}/roles`; + urls.roles = `/scopes/${instances.orgScope.id}/roles`; urls.role = `${urls.roles}/${instances.role.id}`; urls.newRole = `${urls.roles}/new`; + urls.orgScope = `/scopes/${instances.orgScope.id}`; }); test('can create new role', async function (assert) { @@ -65,6 +71,25 @@ module('Acceptance | roles', function (hooks) { assert.equal(this.server.db.roles.length, rolesCount + 1); }); + test('Users can navigate to new roles route with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.orgScope); + assert.ok( + instances.orgScope.authorized_collection_actions.roles.includes('create') + ); + assert.ok(find(`[href="${urls.roles}"]`)); + }); + + test('Users cannot navigate to new roles route without proper authorization', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions.roles = []; + await visit(urls.orgScope); + assert.notOk( + instances.orgScope.authorized_collection_actions.roles.includes('create') + ); + assert.notOk(find(`[href="${urls.roles}"]`)); + }); + test('can cancel new role creation', async function (assert) { assert.expect(2); const rolesCount = this.server.db.roles.length; diff --git a/ui/admin/tests/acceptance/roles/list-test.js b/ui/admin/tests/acceptance/roles/list-test.js new file mode 100644 index 000000000..ff170aeb7 --- /dev/null +++ b/ui/admin/tests/acceptance/roles/list-test.js @@ -0,0 +1,75 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | roles | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + }, + roles: null, + orgScope: null, + }; + + hooks.beforeEach(function () { + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + instances.role = this.server.create('role', { + scope: instances.orgScope, + }); + urls.orgScope = `/scopes/${instances.orgScope.id}`; + + urls.roles = `/scopes/${instances.orgScope.id}/roles`; + authenticateSession({}); + }); + + test('Users can navigate to roles with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.orgScope); + assert.ok( + instances.orgScope.authorized_collection_actions.roles.includes('list') + ); + assert.ok(find(`[href="${urls.roles}"]`)); + }); + + test('Users cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions.roles = []; + await visit(urls.orgScope); + assert.notOk( + instances.orgScope.authorized_collection_actions.roles.includes('list') + ); + assert.notOk(find(`[href="${urls.roles}"]`)); + }); + + test('Users can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.orgScope.authorized_collection_actions.roles = ['create']; + await visit(urls.orgScope); + assert.ok(find(`[href="${urls.roles}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/sessions-test.js b/ui/admin/tests/acceptance/sessions-test.js index d5f68ffeb..a5dfa25ff 100644 --- a/ui/admin/tests/acceptance/sessions-test.js +++ b/ui/admin/tests/acceptance/sessions-test.js @@ -15,13 +15,13 @@ import { module('Acceptance | sessions', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); - const instances = { scopes: { global: null, org: null, }, sessions: null, + orgScope: null, }; const urls = { orgScope: null, @@ -31,6 +31,14 @@ module('Acceptance | sessions', function (hooks) { hooks.beforeEach(function () { authenticateSession({}); instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); instances.scopes.org = this.server.create('scope', { type: 'org', scope: { id: 'global', type: 'global' }, @@ -66,6 +74,7 @@ module('Acceptance | sessions', function (hooks) { }, 'withAssociations' ); + urls.orgScope = `/scopes/${instances.scopes.project.id}`; urls.sessions = `/scopes/${instances.scopes.project.id}/sessions`; }); @@ -81,6 +90,38 @@ module('Acceptance | sessions', function (hooks) { await visit(urls.sessions); }); + test('Users cannot navigate to sessions without proper authorization', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions.sessions = []; + authenticateSession({}); + later(async () => { + run.cancelTimers(); + assert.notOk( + instances.scopes.project.authorized_collection_actions.sessions.includes( + 'list' + ) + ); + assert.notOk(find(`[href="${urls.sessions}"]`)); + }, 750); + await visit(urls.orgScope); + }); + + test('Users can navigate to sessions with proper authorization', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions.sessions = ['list']; + authenticateSession({}); + later(async () => { + run.cancelTimers(); + assert.ok( + instances.scopes.project.authorized_collection_actions.sessions.includes( + 'list' + ) + ); + assert.ok(find(`[href="${urls.sessions}"]`)); + }, 750); + await visit(urls.orgScope); + }); + test('visiting sessions without users or targets is OK', async function (assert) { assert.expect(2); instances.sessions[0].update({ diff --git a/ui/admin/tests/acceptance/targets-test.js b/ui/admin/tests/acceptance/targets/create-test.js similarity index 80% rename from ui/admin/tests/acceptance/targets-test.js rename to ui/admin/tests/acceptance/targets/create-test.js index cf202c049..16215cb7a 100644 --- a/ui/admin/tests/acceptance/targets-test.js +++ b/ui/admin/tests/acceptance/targets/create-test.js @@ -10,7 +10,7 @@ import { //invalidateSession, } from 'ember-simple-auth/test-support'; -module('Acceptance | targets', function (hooks) { +module('Acceptance | targets | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); @@ -33,7 +33,6 @@ module('Acceptance | targets', function (hooks) { }; hooks.beforeEach(function () { - // Generate resources instances.scopes.global = this.server.create('scope', { id: 'global' }); instances.scopes.org = this.server.create('scope', { type: 'org', @@ -68,6 +67,29 @@ module('Acceptance | targets', function (hooks) { assert.equal(getTargetCount(), count + 1); }); + test('can navigate to new targets route with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + assert.ok( + instances.scopes.project.authorized_collection_actions.targets.includes( + 'create' + ) + ); + assert.ok(find(`[href="${urls.targets}"]`)); + }); + + test('cannot navigate to new targets route without proper authorization', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions.targets = []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions.targets.includes( + 'create' + ) + ); + assert.notOk(find(`[href="${urls.targets}"]`)); + }); + test('can cancel create new targets', async function (assert) { assert.expect(2); const count = getTargetCount(); diff --git a/ui/admin/tests/acceptance/targets/list-test.js b/ui/admin/tests/acceptance/targets/list-test.js new file mode 100644 index 000000000..19bd4ee64 --- /dev/null +++ b/ui/admin/tests/acceptance/targets/list-test.js @@ -0,0 +1,84 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | targets | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + + const instances = { + scopes: { + global: null, + org: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + project: null, + }, + targets: null, + projectScope: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + instances.scopes.project = this.server.create('scope', { + type: 'project', + scope: { id: instances.orgScope.id, type: 'org' }, + }); + instances.target = this.server.create('target', { + scope: instances.scopes.project, + }); + urls.projectScope = `/scopes/${instances.scopes.project.id}`; + urls.targets = `${urls.projectScope}/targets`; + authenticateSession({}); + }); + + test('can navigate to targets with proper authorization', async function (assert) { + assert.expect(2); + await visit(urls.projectScope); + assert.ok( + instances.scopes.project.authorized_collection_actions.targets.includes( + 'list' + ) + ); + assert.ok(find(`[href="${urls.targets}"]`)); + }); + + test('User cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.scopes.project.authorized_collection_actions.targets = []; + await visit(urls.projectScope); + assert.notOk( + instances.scopes.project.authorized_collection_actions.targets.includes( + 'list' + ) + ); + assert.notOk(find(`[href="${urls.targets}"]`)); + }); + + test('User can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.scopes.project.authorized_collection_actions.targets = ['create']; + await visit(urls.projectScope); + assert.ok(find(`[href="${urls.targets}"]`)); + }); +}); diff --git a/ui/admin/tests/acceptance/users-test.js b/ui/admin/tests/acceptance/users/create-test.js similarity index 75% rename from ui/admin/tests/acceptance/users-test.js rename to ui/admin/tests/acceptance/users/create-test.js index b047a0d2a..99b715b9b 100644 --- a/ui/admin/tests/acceptance/users-test.js +++ b/ui/admin/tests/acceptance/users/create-test.js @@ -10,11 +10,12 @@ import { //invalidateSession, } from 'ember-simple-auth/test-support'; -module('Acceptance | users', function (hooks) { +module('Acceptance | users | create', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); let orgScope; + let orgURL; let usersURL; let newUserURL; @@ -23,10 +24,12 @@ module('Acceptance | users', function (hooks) { 'scope', { type: 'org', + scope: { id: 'global', type: 'global' }, }, 'withChildren' ); + orgURL = `/scopes/${orgScope.id}`; usersURL = `/scopes/${orgScope.id}/users`; newUserURL = `${usersURL}/new`; @@ -42,6 +45,23 @@ module('Acceptance | users', function (hooks) { assert.equal(this.server.db.users.length, usersCount + 1); }); + test('Users can navigate to new users route with proper authorization', async function (assert) { + assert.expect(2); + await visit(orgURL); + assert.ok(orgScope.authorized_collection_actions.users.includes('create')); + assert.ok(find(`[href="${orgURL}/users"]`)); + }); + + test('Users cannot navigate to new users route without proper authorization', async function (assert) { + assert.expect(2); + orgScope.authorized_collection_actions.users = []; + await visit(orgURL); + assert.notOk( + orgScope.authorized_collection_actions.users.includes('create') + ); + assert.notOk(find(`[href="${orgURL}/users"]`)); + }); + test('can cancel creation of a new user', async function (assert) { assert.expect(2); const usersCount = this.server.db.users.length; diff --git a/ui/admin/tests/acceptance/users/list-test.js b/ui/admin/tests/acceptance/users/list-test.js new file mode 100644 index 000000000..d453e5b04 --- /dev/null +++ b/ui/admin/tests/acceptance/users/list-test.js @@ -0,0 +1,75 @@ +import { module, test } from 'qunit'; +import { visit, find } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; +import { + authenticateSession, + // These are left here intentionally for future reference. + //currentSession, + //invalidateSession, +} from 'ember-simple-auth/test-support'; + +module('Acceptance | users | list', function (hooks) { + setupApplicationTest(hooks); + setupMirage(hooks); + let orgURL; + + const instances = { + scopes: { + global: null, + org: null, + }, + orgScope: null, + }; + + const urls = { + scopes: { + org: null, + }, + users: null, + }; + + hooks.beforeEach(function () { + instances.scopes.global = this.server.create('scope', { id: 'global' }); + instances.orgScope = this.server.create( + 'scope', + { + type: 'org', + scope: { id: 'global', type: 'global' }, + }, + 'withChildren' + ); + instances.user = this.server.create('user', { + scope: instances.orgScope, + }); + orgURL = `/scopes/${instances.orgScope.id}`; + urls.users = `/scopes/${instances.orgScope.id}/users`; + authenticateSession({}); + }); + + test('Users can navigate to users with proper authorization', async function (assert) { + assert.expect(2); + await visit(orgURL); + assert.ok( + instances.orgScope.authorized_collection_actions.users.includes('list') + ); + assert.ok(find(`[href="${urls.users}"]`)); + }); + + test('User cannot navigate to index without either list or create actions', async function (assert) { + assert.expect(2); + instances.orgScope.authorized_collection_actions.users = []; + await visit(orgURL); + assert.notOk( + instances.orgScope.authorized_collection_actions.users.includes('list') + ); + assert.notOk(find(`[href="${urls.users}"]`)); + }); + + test('User can navigate to index with only create action', async function (assert) { + assert.expect(1); + instances.orgScope.authorized_collection_actions.users = ['create']; + await visit(orgURL); + assert.ok(find(`[href="${urls.users}"]`)); + }); +}); diff --git a/ui/desktop/app/components/copyable/index.js b/ui/desktop/app/components/copyable/index.js index a30ff3aca..6168b8c97 100644 --- a/ui/desktop/app/components/copyable/index.js +++ b/ui/desktop/app/components/copyable/index.js @@ -13,8 +13,8 @@ export default class CopyableComponent extends Component { id = generateComponentID(); copyableButtonId = `copyable-button-${this.id}`; - actionIcon = 'copy-action'; - successIcon = 'copy-success'; + actionIcon = 'flight-icons/clipboard-copy-16'; + successIcon = 'flight-icons/clipboard-checked-16'; actionText = this.args.buttonText; successText = this.args.acknowledgeText; diff --git a/ui/desktop/app/components/hidden-secret/index.hbs b/ui/desktop/app/components/hidden-secret/index.hbs index 6660a77e5..a3181b9a6 100644 --- a/ui/desktop/app/components/hidden-secret/index.hbs +++ b/ui/desktop/app/components/hidden-secret/index.hbs @@ -1,7 +1,11 @@
{{t 'actions.toggle-secret'}} diff --git a/ui/desktop/app/styles/app.scss b/ui/desktop/app/styles/app.scss index 617f09ea5..d4dcdb408 100644 --- a/ui/desktop/app/styles/app.scss +++ b/ui/desktop/app/styles/app.scss @@ -233,14 +233,6 @@ } } -.doc-link { - .large { - svg { - transform: scale(0.8); - } - } -} - [class*='session-status-'] { color: var(--ui-gray-subtler-2); } diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 2e8d01b51..9ab80e5b8 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -21,7 +21,7 @@ {{#if this.showFrameActions}} @@ -107,7 +107,7 @@ diff --git a/ui/desktop/app/templates/scopes/scope/authenticate.hbs b/ui/desktop/app/templates/scopes/scope/authenticate.hbs index 60ccaefa0..2c48baf83 100644 --- a/ui/desktop/app/templates/scopes/scope/authenticate.hbs +++ b/ui/desktop/app/templates/scopes/scope/authenticate.hbs @@ -11,7 +11,7 @@ @@ -67,7 +67,7 @@ diff --git a/ui/desktop/app/templates/scopes/scope/authenticate/index.hbs b/ui/desktop/app/templates/scopes/scope/authenticate/index.hbs index b8dbc824f..fa5633bb1 100644 --- a/ui/desktop/app/templates/scopes/scope/authenticate/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/authenticate/index.hbs @@ -2,7 +2,7 @@ diff --git a/ui/desktop/app/templates/scopes/scope/projects.hbs b/ui/desktop/app/templates/scopes/scope/projects.hbs index 4c68c45ca..7df14ea99 100644 --- a/ui/desktop/app/templates/scopes/scope/projects.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects.hbs @@ -2,12 +2,12 @@ - + {{t 'resources.target.title_plural'}} - + {{t 'resources.session.title_plural'}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs index 58abacbc3..6c1fb5636 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs @@ -29,7 +29,7 @@ <:header> + @icon='flight-icons/key-16'> <:header> <:body> <:footer> diff --git a/yarn.lock b/yarn.lock index e356bc3d3..436f898c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2066,10 +2066,10 @@ resolved "https://registry.yarnpkg.com/@handlebars/parser/-/parser-1.1.0.tgz#d6dbc7574774b238114582410e8fee0dc3532bdf" integrity sha512-rR7tJoSwJ2eooOpYGxGGW95sLq6GXUaS1UtWvN7pei6n2/okYvCGld9vsUTvkl2migxbkszsycwtMf/GEc1k1A== -"@hashicorp/structure-icons@^1.9.0-0": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.9.2.tgz#c75f955b2eec414ecb92f3926c79b4ca01731d3c" - integrity sha512-AffJv0V9npr1EWlM1XrpaKPG9PzddV48OE+jspqy7aRoFZB5++oNnPx4MZQKmFInOljnzNwfktVRkJiQHy7haw== +"@hashicorp/flight-icons@0.0.6-beta": + version "0.0.6-beta" + resolved "https://registry.yarnpkg.com/@hashicorp/flight-icons/-/flight-icons-0.0.6-beta.tgz#49da48d4966c13ef0636a9853dc208fccc8d5c88" + integrity sha512-GJHFPig7n26mMyMDPuUiD2Szp8wEskkcLKxWGAx0wyCGASYotLgAYHAGfa4uLlUOsIkibxKjc/7Y/0ttQeN9hQ== "@humanwhocodes/config-array@^0.5.0": version "0.5.0" @@ -5604,7 +5604,7 @@ broccoli-funnel@^1.0.1: symlink-or-copy "^1.0.0" walk-sync "^0.3.1" -broccoli-funnel@^3.0.3, broccoli-funnel@^3.0.8: +broccoli-funnel@^3.0.3, broccoli-funnel@^3.0.5, broccoli-funnel@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/broccoli-funnel/-/broccoli-funnel-3.0.8.tgz#f5b62e2763c3918026a15a3c833edc889971279b" integrity sha512-ng4eIhPYiXqMw6SyGoxPHR3YAwEd2lr9FgBI1CyTbspl4txZovOsmzFkMkGAlu88xyvYXJqHiM2crfLa65T1BQ== @@ -8787,10 +8787,10 @@ ember-cli-version-checker@^5.0.1, ember-cli-version-checker@^5.1.1, ember-cli-ve semver "^7.3.4" silent-error "^1.1.1" -ember-cli@~3.27.0: - version "3.27.0" - resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-3.27.0.tgz#8ccf9db51d7b462f86210b853d086a4543605c34" - integrity sha512-vFLPFkplXn5v005fattHdOcs5AbSp7RG4w1wpHDWHzOSYpl2Dr+5zzZtqLS7V5IVaLf3XK4l24XwhSW9HpMfsQ== +ember-cli@~3.28.0: + version "3.28.0" + resolved "https://registry.yarnpkg.com/ember-cli/-/ember-cli-3.28.0.tgz#0a0374c9a1d08386ddf56e8098a38b71dd4453bc" + integrity sha512-CrMs5edFQ2ingO2xfT33T4nUEl8SlvBQ7q+XO9L/GFTvFU07slHxYSvGur0cwgQfOiLnkSTnIaVF1oqBnEmfPQ== dependencies: "@babel/core" "^7.13.8" "@babel/plugin-transform-modules-amd" "^7.12.1" @@ -8806,7 +8806,7 @@ ember-cli@~3.27.0: broccoli-config-loader "^1.0.1" broccoli-config-replace "^1.1.2" broccoli-debug "^0.6.5" - broccoli-funnel "^2.0.2" + broccoli-funnel "^3.0.5" broccoli-funnel-reducer "^1.0.0" broccoli-merge-trees "^3.0.2" broccoli-middleware "^2.1.1" @@ -8872,7 +8872,7 @@ ember-cli@~3.27.0: sane "^4.1.0" semver "^7.3.4" silent-error "^1.1.1" - sort-package-json "^1.48.0" + sort-package-json "^1.49.0" symlink-or-copy "^1.3.1" temp "0.9.4" testem "^3.2.0" @@ -8881,7 +8881,7 @@ ember-cli@~3.27.0: uuid "^8.3.2" walk-sync "^2.2.0" watch-detector "^1.0.0" - workerpool "^6.0.3" + workerpool "^6.1.4" yam "^1.0.0" ember-compatibility-helpers@^1.1.1, ember-compatibility-helpers@^1.1.2, ember-compatibility-helpers@^1.2.0, ember-compatibility-helpers@^1.2.1, ember-compatibility-helpers@^1.2.4: @@ -19184,7 +19184,7 @@ sort-object-keys@^1.1.3: resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== -sort-package-json@^1.48.0: +sort-package-json@^1.49.0: version "1.50.0" resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.50.0.tgz#19fc109fe23bd157bd03c8e572fa3251a52467d8" integrity sha512-qZpqhMU9XTntebgAgc4hv/D6Fzhh7kFnwvV6a7+q8y8J5JoaDqPYQnvXPf7BBqG95tdE8X6JVNo7/jDzcbdfUg== @@ -20015,10 +20015,10 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.15, tar@^5.0.5, tar@^6.0.2, tar@^6.0.5, tar@^6.1.0, tar@^6.1.2: - version "6.1.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.8.tgz#4fc50cfe56511c538ce15b71e05eebe66530cbd4" - integrity sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A== +tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.15, tar@^5.0.5, tar@^6.0.2, tar@^6.0.5, tar@^6.1.0, tar@^6.1.9: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -21580,7 +21580,7 @@ workerpool@^3.1.1: object-assign "4.1.1" rsvp "^4.8.4" -workerpool@^6.0.0, workerpool@^6.0.3, workerpool@^6.1.4: +workerpool@^6.0.0, workerpool@^6.1.4: version "6.1.5" resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== @@ -21696,9 +21696,10 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmldom@^0.6.0, "xmldom@github:xmldom/xmldom#0.7.0": - version "0.7.0" - resolved "https://codeload.github.com/xmldom/xmldom/tar.gz/c568938641cc1f121cef5b4df80fcfda1e489b6e" +xmldom@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.6.0.tgz#43a96ecb8beece991cef382c08397d82d4d0c46f" + integrity sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg== xmlhttprequest-ssl@^1.6.2: version "1.6.3"