From 0b8550c136b8d296f432fd329bb70775cd5d88ad Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Wed, 10 Feb 2021 13:19:24 -0500 Subject: [PATCH 01/11] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20use=20recrusiv?= =?UTF-8?q?e=20listing=20for=20desktop=20queries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and add mock rescursive support for scopes, targets, and sessions --- addons/api/addon/models/session.js | 8 ++++ addons/api/addon/models/target.js | 8 ++++ addons/api/mirage/config.js | 39 +++++++++++++---- .../scopes/scope/projects/sessions/index.js | 27 ++++++++++++ ui/desktop/app/routes/scopes/scope.js | 20 ++++----- .../app/routes/scopes/scope/projects.js | 7 ++-- .../routes/scopes/scope/projects/sessions.js | 42 ++----------------- .../routes/scopes/scope/projects/targets.js | 29 +++---------- .../scopes/scope/projects/sessions/index.hbs | 30 ++++++------- .../scopes/scope/projects/targets/index.hbs | 20 ++++----- .../scope/projects/sessions/index-test.js | 12 ++++++ 11 files changed, 132 insertions(+), 110 deletions(-) create mode 100644 ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js create mode 100644 ui/desktop/tests/unit/controllers/scopes/scope/projects/sessions/index-test.js diff --git a/addons/api/addon/models/session.js b/addons/api/addon/models/session.js index 5ab2e3c39..dd27cd9c6 100644 --- a/addons/api/addon/models/session.js +++ b/addons/api/addon/models/session.js @@ -32,6 +32,14 @@ export default class SessionModel extends GeneratedSessionModel { : null; } + /** + * The target associated with this session (if loaded). + * @type {TargetModel} + */ + get target() { + return this.store.peekRecord('target', this.target_id); + } + // =methods /** diff --git a/addons/api/addon/models/target.js b/addons/api/addon/models/target.js index 8924ffbb4..6c5e1cfe8 100644 --- a/addons/api/addon/models/target.js +++ b/addons/api/addon/models/target.js @@ -45,6 +45,14 @@ export default class TargetModel extends GeneratedTargetModel { .filter(s => s && (s.target_id === this.id)); } + /** + * The project associated with this target (if already loaded). + * @type {ScopeModel} + */ + get project() { + return this.store.peekRecord('scope', this.scopeID); + } + /** * True if any sessions associated with this target are active or pending. * @type {boolean} diff --git a/addons/api/mirage/config.js b/addons/api/mirage/config.js index 5ae912f69..8f6503319 100644 --- a/addons/api/mirage/config.js +++ b/addons/api/mirage/config.js @@ -23,13 +23,16 @@ export default function() { // Scope resources - this.get('/scopes', ({ scopes }, { queryParams: { scope_id } }) => { + this.get('/scopes', ({ scopes }, { queryParams: { scope_id, recursive } }) => { // Default parent scope is global if (!scope_id) scope_id = 'global'; - const results = scopes.where(scope => { - return scope.scope ? scope.scope.id === scope_id : false - }); - return results; + if (recursive && scope_id === 'global') { + return scopes.all(); + } else { + return scopes.where(scope => { + return scope.scope ? scope.scope.id === scope_id : false + }); + } }); this.post('/scopes', function ({ scopes }) { // Parent scope comes through the payload via `scope_id`, but this needs @@ -287,7 +290,16 @@ export default function() { // target - this.get('/targets', function ({ targets }, { queryParams: { scope_id } }) { + this.get('/targets', function ({ targets }, { queryParams: { scope_id, recursive } }) { + if (recursive && scope_id === 'global') { + return targets.all(); + } else if (recursive) { + return targets.where(target => { + const targetModel = targets.find(target.id); + return (target.scopeId === scope_id) + || (targetModel?.scope?.scope?.id === scope_id) + }); + } return targets.where(target => target.scopeId === scope_id); }); this.post('/targets', function ({ targets }) { @@ -325,7 +337,7 @@ export default function() { // session - this.get('/sessions', function ({ sessions }, { queryParams: { scope_id } }) { + this.get('/sessions', function ({ sessions }, { queryParams: { scope_id, recursive } }) { // To simulate changes to `session.status` that may occur in the backend, // we quietly randomize the value of the field on GET. // To populate sessions for logged in user, @@ -333,7 +345,7 @@ export default function() { // But only if not in testing mode. // In tests, we need deterministic statuses. if (!Ember.testing) { - sessions.where(session => session.scopeId === scope_id) + sessions.all() .models .forEach(session => { session.update({ @@ -344,7 +356,16 @@ export default function() { }); }); } - return sessions.where(session => session.scopeId === scope_id) + if (recursive && scope_id === 'global') { + return sessions.all(); + } else if (recursive) { + return sessions.where(session => { + const sessionModel = sessions.find(session.id); + return (session.scopeId === scope_id) + || (sessionModel?.scope?.scope?.id === scope_id) + }); + } + return sessions.where(session => session.scopeId === scope_id); }); this.get('/sessions/:id', function ({ sessions }, { params: { id } }) { const session = sessions.find(id); diff --git a/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js b/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js new file mode 100644 index 000000000..dc54b63f0 --- /dev/null +++ b/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js @@ -0,0 +1,27 @@ +import Controller from '@ember/controller'; +import { computed } from '@ember/object'; +import { inject as service } from '@ember/service'; + +export default class ScopesScopeProjectsSessionsIndexController extends Controller { + + // =sessions + + @service session; + + // =attributes + + @computed('model.@each.{created_time,active}', 'session.data.authenticated.user_id') + get sorted() { + const userId = this.session.data.authenticated.user_id; + const sessions = this.model; + const sortedSessions = sessions + .filter(session => session.user_id === userId) + .sortBy('session.created_time').reverse(); + // Then move active sessions to the top... + return [ + ...sortedSessions.filter((session) => session.isCancelable), + ...sortedSessions.filter((session) => !session.isCancelable), + ]; + } + +} diff --git a/ui/desktop/app/routes/scopes/scope.js b/ui/desktop/app/routes/scopes/scope.js index 914aa2904..14e36f5e1 100644 --- a/ui/desktop/app/routes/scopes/scope.js +++ b/ui/desktop/app/routes/scopes/scope.js @@ -89,14 +89,14 @@ export default class ScopesScopeRoute extends Route { }); } - /** - * In global scope, redirect to first org on authentication. - */ - redirect(model) { - const { isAuthenticated } = this.session; - const { isGlobal } = model; - if (isAuthenticated && isGlobal && this.scopes.orgs?.length) { - this.replaceWith('scopes.scope', this.scopes.orgs.firstObject.id); - } - } + // /** + // * In global scope, redirect to first org on authentication. + // */ + // redirect(model) { + // const { isAuthenticated } = this.session; + // const { isGlobal } = model; + // if (isAuthenticated && isGlobal && this.scopes.orgs?.length) { + // this.replaceWith('scopes.scope', this.scopes.orgs.firstObject.id); + // } + // } } diff --git a/ui/desktop/app/routes/scopes/scope/projects.js b/ui/desktop/app/routes/scopes/scope/projects.js index 0d7ada97c..b1aacf256 100644 --- a/ui/desktop/app/routes/scopes/scope/projects.js +++ b/ui/desktop/app/routes/scopes/scope/projects.js @@ -20,10 +20,9 @@ export default class ScopesScopeProjectsRoute extends Route { * @return {Promise */ model() { - const currentScope = this.modelFor('scopes.scope'); - return this.store.query('scope', { - scope_id: currentScope.id, - }); + return this.store + .query('scope', { recursive: true, scope_id: 'global' }) + .filter(({ isProject }) => isProject); } } diff --git a/ui/desktop/app/routes/scopes/scope/projects/sessions.js b/ui/desktop/app/routes/scopes/scope/projects/sessions.js index 1c0f133ef..149aedb7f 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/sessions.js +++ b/ui/desktop/app/routes/scopes/scope/projects/sessions.js @@ -1,8 +1,6 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { all, hash } from 'rsvp'; import { task, timeout } from 'ember-concurrency'; -import { A } from '@ember/array'; import config from '../../../../config/environment'; import { action } from '@ember/object'; import { notifySuccess, notifyError } from 'core/decorators/notify'; @@ -49,43 +47,9 @@ export default class ScopesScopeProjectsSessionsRoute extends Route { * @return {Promise{[{session: SessionModel, target: TargetModel}]}} */ async model() { - const projects = this.modelFor('scopes.scope.projects'); - const userId = this.session.data.authenticated.user_id; - let projectSessions = await all( - projects.map(({ id: scope_id }) => - this.store.query('session', { scope_id }) - ) - ); - - // Filter sessions to current user - let sessions = projectSessions.map( - sessions => sessions.filter( - session => session.user_id === userId - ) - ).flat(); - - const sessionAggregates = await all( - sessions.map(session => hash({ - session, - target: session.target_id - ? ( - this.store.peekRecord('target', session.target_id) || - this.store.findRecord('target', session.target_id) - ) - : null, - })) - ); - - // Sort sessions by time created... - let sortedSessionAggregates = - A(sessionAggregates).sortBy('session.created_time').reverse(); - // Then move active sessions to the top... - sortedSessionAggregates = [ - ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status === 'active'), - ...sortedSessionAggregates.filter((aggregate) => aggregate.session.status !== 'active'), - ]; - - return sortedSessionAggregates; + const { id: scope_id } = this.modelFor('scopes.scope'); + await this.store.query('target', { recursive: true, scope_id }); + return await this.store.query('session', { recursive: true, scope_id }); } /** diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets.js b/ui/desktop/app/routes/scopes/scope/projects/targets.js index f02dd4f0f..32a804074 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets.js @@ -1,6 +1,5 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { all } from 'rsvp'; import { action } from '@ember/object'; import { task, timeout } from 'ember-concurrency'; import { later } from '@ember/runloop'; @@ -33,7 +32,7 @@ export default class ScopesScopeProjectsTargetsRoute extends Route { @task(function * () { while(true) { yield timeout(POLL_TIMEOUT_SECONDS * 1000); - yield this.refreshSessions(); + //yield this.refreshSessions(); } }).drop() poller; @@ -51,20 +50,9 @@ export default class ScopesScopeProjectsTargetsRoute extends Route { * @return {Promise{[TargetModel]}} */ async model() { - const projects = this.modelFor('scopes.scope.projects'); - let projectTargets = await all( - projects.map(({ id: scope_id }) => - this.store.query('target', { scope_id }) - ) - ); - let targets = projectTargets.map((target) => target.toArray()).flat(); + const { id: scope_id } = this.modelFor('scopes.scope'); await this.refreshSessions(); - return targets.map((target) => { - return { - target, - project: this.store.peekRecord('scope', target.scopeID), - }; - }); + return this.store.query('target', { recursive: true, scope_id }); } /** @@ -73,13 +61,8 @@ export default class ScopesScopeProjectsTargetsRoute extends Route { * TODO: query only for sessions associated with the current user. */ async refreshSessions() { - const projects = this.modelFor('scopes.scope.projects'); - //const userId = this.session.data.authenticated.user_id; - await all( - projects.map(({ id: scope_id }) => - this.store.query('session', { scope_id }) - ) - ); + const { id: scope_id } = this.modelFor('scopes.scope'); + await this.store.query('session', { recursive: true, scope_id }); } /** @@ -115,7 +98,7 @@ export default class ScopesScopeProjectsTargetsRoute extends Route { target_id: model.id, token: this.session.data.authenticated.token }; - + if (host) options.host_id = host.id; // Create target session 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 35c53bb63..3f6dccb72 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs @@ -6,7 +6,7 @@ - {{#if @model}} + {{#if this.sorted}} @@ -20,22 +20,22 @@ - {{#each @model as |sessionAggregate|}} + {{#each this.sorted as |model|}} - {{sessionAggregate.session.id}} + {{model.id}} - {{sessionAggregate.target.displayName}} + {{model.target.displayName}} {{!-- Two if's here because: @@ -48,29 +48,29 @@ from other devices (or even another tab), in which case we won't have the local proxy info available here. --}} - {{#if sessionAggregate.session.isCancelable}} - {{#if sessionAggregate.session.proxy}} + {{#if model.isCancelable}} + {{#if model.proxy}} - {{sessionAggregate.session.proxy}} + {{model.proxy}} {{/if}} {{/if}} - - {{sessionAggregate.session.status}} + {{model.status}} - {{#if sessionAggregate.session.isCancelable}} - + {{#if model.isCancelable}} + {{t "actions.cancel"}} {{/if}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs index b816ced05..61f61178c 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs @@ -22,32 +22,32 @@ - {{model.target.displayName}} + {{model.displayName}} -

{{model.target.description}}

+

{{model.description}}

- {{model.target.id}} + {{model.id}} - {{#if model.target.type}} + {{#if model.type}} - {{t (concat "resources.target.types." model.target.type)}} + {{t (concat "resources.target.types." model.type)}} {{/if}} @@ -66,7 +66,7 @@
- + {{t "resources.session.actions.connect"}} diff --git a/ui/desktop/tests/unit/controllers/scopes/scope/projects/sessions/index-test.js b/ui/desktop/tests/unit/controllers/scopes/scope/projects/sessions/index-test.js new file mode 100644 index 000000000..1a9f45f78 --- /dev/null +++ b/ui/desktop/tests/unit/controllers/scopes/scope/projects/sessions/index-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | scopes/scope/projects/sessions/index', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:scopes/scope/projects/sessions/index'); + assert.ok(controller); + }); +}); From 3f3e21e60c92b09404879504d2cd72a7e104d498 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 10 Feb 2021 16:19:29 -0500 Subject: [PATCH 02/11] refactor: Sort and filter active sessions in a target --- .../scope/projects/targets/target/sessions.js | 36 +++++++++++++++++++ .../scopes/scope/projects/targets/target.js | 27 +++----------- .../scope/projects/targets/target/hosts.js | 2 +- .../scope/projects/targets/target/sessions.js | 10 ++++++ .../projects/targets/target/-actions.hbs | 2 +- .../scope/projects/targets/target/-header.hbs | 10 +++--- .../projects/targets/target/sessions.hbs | 6 +--- .../projects/targets/target/sessions-test.js | 12 +++++++ 8 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 ui/desktop/app/controllers/scopes/scope/projects/targets/target/sessions.js create mode 100644 ui/desktop/tests/unit/controllers/scopes/scope/projects/targets/target/sessions-test.js diff --git a/ui/desktop/app/controllers/scopes/scope/projects/targets/target/sessions.js b/ui/desktop/app/controllers/scopes/scope/projects/targets/target/sessions.js new file mode 100644 index 000000000..dfab20739 --- /dev/null +++ b/ui/desktop/app/controllers/scopes/scope/projects/targets/target/sessions.js @@ -0,0 +1,36 @@ +import Controller from '@ember/controller'; +import { computed } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { A } from '@ember/array'; + +export default class ScopesScopeProjectsTargetsTargetSessionsController extends Controller { + // =services + + @service session; + + /** + * Sort and filter to active sessions of current user + * @param {[SessionModel]} model + * @param {object} session + * @type {[SessionModel]} + */ + @computed('model.@each.{created_time,active}', 'session.data.authenticated.user_id') + get selfActiveSessions() { + const sessions = this.model; + const userId = this.session.data.authenticated.user_id; + const filteredSessions = + sessions.filter(session => + session.isCancelable && + session.user_id === userId + ); + + // Sort sessions + const sortedSessions = A(filteredSessions).sortBy('created_time').reverse(); + + // Move active sessions to top + return [ + ...sortedSessions.filter(session => session.isActive), + ...sortedSessions.filter(session => !session.isActive) + ] + } +} diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/target.js b/ui/desktop/app/routes/scopes/scope/projects/targets/target.js index 0bcdbd2ec..3cf2343fe 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets/target.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/target.js @@ -1,36 +1,17 @@ import Route from '@ember/routing/route'; -import { inject as service } from '@ember/service'; -import { A } from '@ember/array'; export default class ScopesScopeProjectsTargetsTargetRoute extends Route { - // =services - - @service session; - // =methods /** - * Load a target and it's active sessions + * Load a target * @param {object} params * @param {string} params.target_id - * @return {{TargetModel, [SessionModel]}} + * @return {TargetModel} */ - async model({ target_id }) { - const userId = this.session.data.authenticated.user_id; - const target = await this.store.findRecord('target', target_id, { reload: true }); - const sessions = await this.store.query('session', { scope_id: target.scopeID }); - - // Filter to current user, current target, and active state - const filteredSessions = sessions.filter( - session => session.user_id === userId && - session.target_id === target.id && - session.isCancelable - ) - // Sort sessions by time created - const sortedSessions = - A(filteredSessions).sortBy('session.created_time').reverse(); - return { target, sessions: sortedSessions }; + model({ target_id }) { + return this.store.findRecord('target', target_id, { reload: true }); } /** diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/target/hosts.js b/ui/desktop/app/routes/scopes/scope/projects/targets/target/hosts.js index 0362726f5..ef2f5a8ab 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets/target/hosts.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/target/hosts.js @@ -18,7 +18,7 @@ export default class ScopesScopeProjectsTargetsTargetHostsRoute extends Route { * @return {Promise{[HostModel]}} */ async model() { - const { target } = this.modelFor('scopes.scope.projects.targets.target'); + const target = this.modelFor('scopes.scope.projects.targets.target'); // Load all host-sets const hostSets = await all( target.host_sets.map(({ host_set_id }) => diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/target/sessions.js b/ui/desktop/app/routes/scopes/scope/projects/targets/target/sessions.js index 4f0281e2f..203b74d62 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets/target/sessions.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/target/sessions.js @@ -3,6 +3,16 @@ import { action } from '@ember/object'; import { notifySuccess, notifyError } from 'core/decorators/notify'; export default class ScopesScopeProjectsTargetsTargetSessionsRoute extends Route { + + // =methods + + /** + * @return {[SessionModel]} + */ + model() { + return this.modelFor('scopes.scope.projects.targets.target').sessions; + } + // =actions /** diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/target/-actions.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/target/-actions.hbs index e59af9f97..b82595c94 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/target/-actions.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/target/-actions.hbs @@ -1,3 +1,3 @@ - + {{t "resources.session.actions.connect"}} diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/target/-header.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/target/-header.hbs index 8677dadd4..938169518 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/target/-header.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/target/-header.hbs @@ -1,18 +1,18 @@

- {{@model.target.displayName}} - {{#if @model.target.isActive}} + {{@model.displayName}} + {{#if @model.isActive}} {{t "states.active"}} {{/if}}

-

{{@model.target.description}}

+

{{@model.description}}

- {{@model.target.id}} + {{@model.id}}

diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/target/sessions.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/target/sessions.hbs index e273d7058..008e5dfb0 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/target/sessions.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/target/sessions.hbs @@ -1,10 +1,6 @@ - {{!-- - TODO: sort these via the controller so that active and pending appear first - similar to the way the sessions routes are sorted. - --}} - {{#each @model.target.sessions as |session|}} + {{#each this.selfActiveSessions as |session|}} Date: Wed, 10 Feb 2021 16:32:24 -0500 Subject: [PATCH 03/11] chore: Add missing origin validation message --- addons/core/translations/errors/en-us.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/core/translations/errors/en-us.yaml b/addons/core/translations/errors/en-us.yaml index 0e2239e72..a151a4ba9 100644 --- a/addons/core/translations/errors/en-us.yaml +++ b/addons/core/translations/errors/en-us.yaml @@ -17,3 +17,5 @@ generic: title: Error authentication-failed: title: Authentication Failed +origin-verification-failed: + description: Could not validate the provided origin URL as Boundary URL. Please check origin URL and try again. From f31cd4315b32538fa69b798b04435ec74ede82bc Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 10 Feb 2021 21:26:30 -0500 Subject: [PATCH 04/11] style: Fix auth border expanding to bottom of screen --- .../templates/scopes/scope/authenticate.hbs | 105 ++++++++---------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/ui/desktop/app/templates/scopes/scope/authenticate.hbs b/ui/desktop/app/templates/scopes/scope/authenticate.hbs index b01ed3a31..3d7d834bd 100644 --- a/ui/desktop/app/templates/scopes/scope/authenticate.hbs +++ b/ui/desktop/app/templates/scopes/scope/authenticate.hbs @@ -1,65 +1,58 @@ {{page-title (t "actions.authenticate")}} -{{!-- - -Change --}} - +
+ - - - {{t "titles.global"}} - - {{#each this.sortedScopes as |scope|}} - - {{scope.displayName}} + + + {{t "titles.global"}} - {{/each}} - + {{#each this.sortedScopes as |scope|}} + + {{scope.displayName}} + + {{/each}} + - - {{#each @model.authMethods as |authMethod|}} - - {{t (concat "resources.auth-method.types." authMethod.type)}} - - {{/each}} - + + {{#each @model.authMethods as |authMethod|}} + + {{t (concat "resources.auth-method.types." authMethod.type)}} + + {{/each}} + - {{#if @model.authMethods}} - {{outlet}} + {{#if @model.authMethods}} + {{outlet}} -

- {{t "origin.connected-to"}}: - {{this.origin}} -
- - {{t "actions.change-origin"}} - -

+

+ {{t "origin.connected-to"}}: + {{this.origin}} +
+ + {{t "actions.change-origin"}} + +

- {{/if}} - {{#unless @model.authMethods}} - - - - {{t "resources.auth-method.messages.none.description"}} - - - - {{/unless}} + {{/if}} + {{#unless @model.authMethods}} + + + + {{t "resources.auth-method.messages.none.description"}} + + + + {{/unless}} -
+ +
From 34511f1a0123ffa0a257fae0f8da699e24d2465c Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Wed, 10 Feb 2021 23:12:15 -0500 Subject: [PATCH 05/11] chore: Remove spaces from dmg filename --- ui/desktop/electron-app/config/forge.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/desktop/electron-app/config/forge.config.js b/ui/desktop/electron-app/config/forge.config.js index 2c7b5f4a6..612c4d733 100644 --- a/ui/desktop/electron-app/config/forge.config.js +++ b/ui/desktop/electron-app/config/forge.config.js @@ -34,7 +34,8 @@ module.exports = { { name: "@electron-forge/maker-dmg", config: { - name: "Boundary Desktop" + name: "boundary-desktop", + title: "Boundary Desktop" } } ] From 8ab7785915c22ca8495611b0a91b64b100eaf798 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 11 Feb 2021 09:08:32 -0500 Subject: [PATCH 06/11] refactor: Wordsmith origin error message --- addons/core/translations/errors/en-us.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/core/translations/errors/en-us.yaml b/addons/core/translations/errors/en-us.yaml index a151a4ba9..c814611d0 100644 --- a/addons/core/translations/errors/en-us.yaml +++ b/addons/core/translations/errors/en-us.yaml @@ -18,4 +18,4 @@ generic: authentication-failed: title: Authentication Failed origin-verification-failed: - description: Could not validate the provided origin URL as Boundary URL. Please check origin URL and try again. + description: Unable to connect to the specified origin. Please check the URL and try again. From 8e43f3aef614080c4716246fb9d11f71b77d6513 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 11 Feb 2021 10:44:48 -0500 Subject: [PATCH 07/11] =?UTF-8?q?chore:=20=F0=9F=A4=96=20PR=20feedback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scopes/scope/projects/sessions/index.js | 10 +++++++++- ui/desktop/app/routes/scopes/scope.js | 11 ----------- ui/desktop/app/routes/scopes/scope/projects.js | 18 ++++++++++++++++-- .../routes/scopes/scope/projects/targets.js | 2 +- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js b/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js index dc54b63f0..babe28f5f 100644 --- a/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js +++ b/ui/desktop/app/controllers/scopes/scope/projects/sessions/index.js @@ -10,16 +10,24 @@ export default class ScopesScopeProjectsSessionsIndexController extends Controll // =attributes + /** + * A list of sessions filtered to the current user and sorted by created time, + * and active/pending. + * @type {SessionModel[]} + */ @computed('model.@each.{created_time,active}', 'session.data.authenticated.user_id') get sorted() { const userId = this.session.data.authenticated.user_id; const sessions = this.model; const sortedSessions = sessions + // filter sessions by current user .filter(session => session.user_id === userId) + // sort by created time .sortBy('session.created_time').reverse(); - // Then move active sessions to the top... return [ + // then move active sessions to the top ...sortedSessions.filter((session) => session.isCancelable), + // and all others to the end ...sortedSessions.filter((session) => !session.isCancelable), ]; } diff --git a/ui/desktop/app/routes/scopes/scope.js b/ui/desktop/app/routes/scopes/scope.js index 14e36f5e1..a0b817037 100644 --- a/ui/desktop/app/routes/scopes/scope.js +++ b/ui/desktop/app/routes/scopes/scope.js @@ -88,15 +88,4 @@ export default class ScopesScopeRoute extends Route { outlet: 'header-nav', }); } - - // /** - // * In global scope, redirect to first org on authentication. - // */ - // redirect(model) { - // const { isAuthenticated } = this.session; - // const { isGlobal } = model; - // if (isAuthenticated && isGlobal && this.scopes.orgs?.length) { - // this.replaceWith('scopes.scope', this.scopes.orgs.firstObject.id); - // } - // } } diff --git a/ui/desktop/app/routes/scopes/scope/projects.js b/ui/desktop/app/routes/scopes/scope/projects.js index b1aacf256..e579d7efb 100644 --- a/ui/desktop/app/routes/scopes/scope/projects.js +++ b/ui/desktop/app/routes/scopes/scope/projects.js @@ -1,6 +1,20 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +/** + * TODO: This route is now vestigial. Desktop does not provide project-based + * navigation. This route formerly provided a way to aggregate + * all project scopes, which was necessary to then aggregate targets and + * sessions under those projects. Since the API now provides recursive listing, + * it's possible to load all targets and sessions with a single call, no client- + * side aggregation required. + * + * However, it _is_ necessary to prime the store with all project scopes. + * This allows the UI to display project names on associated resources. + * + * The priming function of this route could be moved to scopes or scopes/scope. + * It no longer makes sense as a dedicated route. + */ export default class ScopesScopeProjectsRoute extends Route { // =services @@ -16,8 +30,8 @@ export default class ScopesScopeProjectsRoute extends Route { } /** - * Loads project scopes for the current scope. - * @return {Promise + * Primes the store with _all project scopes_ under global. + * @return {Promise{ScopeModel}} */ model() { return this.store diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets.js b/ui/desktop/app/routes/scopes/scope/projects/targets.js index 32a804074..867011648 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets.js @@ -32,7 +32,7 @@ export default class ScopesScopeProjectsTargetsRoute extends Route { @task(function * () { while(true) { yield timeout(POLL_TIMEOUT_SECONDS * 1000); - //yield this.refreshSessions(); + yield this.refreshSessions(); } }).drop() poller; From 2eb4dc03e8c81ad68d12a9a68cc5d9d586790b38 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Thu, 11 Feb 2021 10:50:47 -0500 Subject: [PATCH 08/11] fix: Close icon in dialog header will dismiss dialog --- ui/desktop/app/templates/application.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs index 7101dd522..3bca4c490 100644 --- a/ui/desktop/app/templates/application.hbs +++ b/ui/desktop/app/templates/application.hbs @@ -77,7 +77,7 @@ @icon="check-circle-fill" @style="success" @modal={{true}} - @dismiss={{accept}} + @dismiss={{deny}} as |dialog|> @@ -107,7 +107,7 @@ @icon="cancel-square-fill" @style="error" @modal={{true}} - @dismiss={{accept}} + @dismiss={{deny}} as |dialog|>

From 275a535d0b9e83785467b2abed56eaed011cb917 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 11 Feb 2021 12:22:35 -0500 Subject: [PATCH 09/11] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20app=20versi?= =?UTF-8?q?on=20and=20commit=20and=20tweak=20dialog=20whitespace?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/desktop/electron-app/config/forge.config.js | 11 ++++++++++- ui/desktop/electron-app/src/boundary-cli.js | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ui/desktop/electron-app/config/forge.config.js b/ui/desktop/electron-app/config/forge.config.js index 612c4d733..aab636b03 100644 --- a/ui/desktop/electron-app/config/forge.config.js +++ b/ui/desktop/electron-app/config/forge.config.js @@ -3,6 +3,15 @@ const { version } = require('../src/boundary-cli.js'); const formattedCLIVersion = version().formatted; +const appVersion = process.env.VERSION + ? `Version: ${process.env.VERSION}\n` + : ''; +const appCommit = process.env.COMMIT + ? `Commit: ${process.env.COMMIT}\n` + : ''; + +const formattedAppVersion = `${appVersion}${appCommit}`; + module.exports = { hooks: { prePackage: () => { @@ -19,7 +28,7 @@ module.exports = { name: "Boundary Desktop", appBundleId: "com.electron.boundary", // TODO: where should the client version number come from? - appVersion: `1.0.0 ${formattedCLIVersion}`, + appVersion: `${formattedAppVersion}${formattedCLIVersion}\n`, appCopyright: "Copyright © 2021 HashiCorp, Inc.", icon: "./config/macos/icon.icns", osxSign: { diff --git a/ui/desktop/electron-app/src/boundary-cli.js b/ui/desktop/electron-app/src/boundary-cli.js index 241f288fc..36797d023 100644 --- a/ui/desktop/electron-app/src/boundary-cli.js +++ b/ui/desktop/electron-app/src/boundary-cli.js @@ -49,8 +49,8 @@ module.exports = { if (gitRevision) gitRevision = gitRevision.groups.rev; if (versionNumber) versionNumber = versionNumber.groups.ver; const formatted = versionNumber - ? `CLI Version ${versionNumber}; CLI Git Rev ${gitRevision}` - : `CLI Git Rev ${gitRevision}`; + ? `CLI Version: ${versionNumber}\nCLI Commit ${gitRevision}` + : `CLI Commit: ${gitRevision}`; return { gitRevision, versionNumber, formatted }; return rawOutput; } From b26a9b8fade670868a2d1ff993c25718ecbf8b65 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 11 Feb 2021 12:24:22 -0500 Subject: [PATCH 10/11] use consistent colons --- ui/desktop/electron-app/src/boundary-cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/desktop/electron-app/src/boundary-cli.js b/ui/desktop/electron-app/src/boundary-cli.js index 36797d023..2227687ed 100644 --- a/ui/desktop/electron-app/src/boundary-cli.js +++ b/ui/desktop/electron-app/src/boundary-cli.js @@ -49,7 +49,7 @@ module.exports = { if (gitRevision) gitRevision = gitRevision.groups.rev; if (versionNumber) versionNumber = versionNumber.groups.ver; const formatted = versionNumber - ? `CLI Version: ${versionNumber}\nCLI Commit ${gitRevision}` + ? `CLI Version: ${versionNumber}\nCLI Commit: ${gitRevision}` : `CLI Commit: ${gitRevision}`; return { gitRevision, versionNumber, formatted }; return rawOutput; From a350d7e5ac22dfb32a8c4d03df35a8d5db4b8079 Mon Sep 17 00:00:00 2001 From: Randall Morey Date: Thu, 11 Feb 2021 12:47:22 -0500 Subject: [PATCH 11/11] =?UTF-8?q?chore:=20=F0=9F=A4=96=20tweak=20target=20?= =?UTF-8?q?"active"=20badge=20appearance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scopes/scope/projects/targets/index.hbs | 15 ++++++++------- .../scope/projects/targets/target/-header.hbs | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs index b816ced05..444f5501c 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs @@ -21,19 +21,20 @@ {{#each @model as |model|}} - {{model.target.displayName}} -

{{model.target.description}}

+ {{#if model.target.description}} +

{{model.target.description}}

+ {{/if}} + {{#if model.target.isActive}} + + {{t "states.active"}} + + {{/if}} {{@model.displayName}} {{#if @model.isActive}} +   {{t "states.active"}}