diff --git a/ui/desktop/app/routes/scopes/scope/projects/sessions/index.js b/ui/desktop/app/routes/scopes/scope/projects/sessions/index.js
index 8d9ff7283..e0fc0f7d6 100644
--- a/ui/desktop/app/routes/scopes/scope/projects/sessions/index.js
+++ b/ui/desktop/app/routes/scopes/scope/projects/sessions/index.js
@@ -62,6 +62,8 @@ export default class ScopesScopeProjectsSessionsIndexRoute extends Route {
*/
async model({ targets, status, scopes, page, pageSize }, transition) {
const from = transition.from?.name;
+ const projects = this.modelFor('scopes.scope.projects');
+ const projectIds = projects.map((project) => project.id);
const filters = {
user_id: [{ equals: this.session.data.authenticated.user_id }],
@@ -78,6 +80,11 @@ export default class ScopesScopeProjectsSessionsIndexRoute extends Route {
scopes.forEach((scope) => {
filters.scope_id.push({ equals: scope });
});
+ if (scopes.length === 0) {
+ projectIds.forEach((projectId) => {
+ filters.scope_id.push({ equals: projectId });
+ });
+ }
const queryOptions = {
query: { filters },
@@ -105,8 +112,6 @@ export default class ScopesScopeProjectsSessionsIndexRoute extends Route {
this.allTargets = await this.store.query('target', {}, options);
}
- const projects = this.modelFor('scopes.scope.projects');
-
return {
sessions,
projects,
@@ -115,4 +120,14 @@ export default class ScopesScopeProjectsSessionsIndexRoute extends Route {
totalItems,
};
}
+
+ resetController(controller, isExiting, transition) {
+ const { to } = transition;
+ // Reset the scopes query param when changing org scope
+ if (!isExiting && to.queryParams.scopes === '[]') {
+ controller.setProperties({
+ scopes: [],
+ });
+ }
+ }
}
diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/index.js b/ui/desktop/app/routes/scopes/scope/projects/targets/index.js
index 90fb82518..182c0890e 100644
--- a/ui/desktop/app/routes/scopes/scope/projects/targets/index.js
+++ b/ui/desktop/app/routes/scopes/scope/projects/targets/index.js
@@ -84,11 +84,18 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
transition,
) {
await this.getAllTargets(transition);
+ const projects = this.modelFor('scopes.scope.projects');
+ const projectIds = projects.map((project) => project.id);
const filters = { scope_id: [], id: { values: [] }, type: [] };
scopes.forEach((scope) => {
filters.scope_id.push({ equals: scope });
});
+ if (scopes.length === 0) {
+ projectIds.forEach((projectId) => {
+ filters.scope_id.push({ equals: projectId });
+ });
+ }
types.forEach((type) => {
filters.type.push({ equals: type });
});
@@ -124,7 +131,6 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
targets = targets.filter((target) =>
this.can.can('connect target', target),
);
- const projects = this.modelFor('scopes.scope.projects');
return {
targets,
@@ -134,6 +140,16 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
};
}
+ resetController(controller, isExiting, transition) {
+ const { to } = transition;
+ // Reset the scopes query param when changing org scope
+ if (!isExiting && to.queryParams.scopes === '[]') {
+ controller.setProperties({
+ scopes: [],
+ });
+ }
+ }
+
/**
* Get all the targets but only load them once when entering the route. Ideally we would lazy load it when needed
* but this can be revisited in the future.
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 ca1ae794a..687f3fe5c 100644
--- a/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs
+++ b/ui/desktop/app/templates/scopes/scope/projects/sessions/index.hbs
@@ -84,7 +84,7 @@
{{B.data.id}}
@@ -101,7 +101,7 @@
@acknowledgeText={{t 'states.copied'}}
>
{{B.data.id}}
{{/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 e31b96bc6..bc6ffb024 100644
--- a/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs
+++ b/ui/desktop/app/templates/scopes/scope/projects/targets/index.hbs
@@ -127,7 +127,9 @@
@buttonText={{t 'actions.copy-to-clipboard'}}
@acknowledgeText={{t 'states.copied'}}
>
- {{B.data.project.id}}
+ {{B.data.project.id}}
{{#if B.data.project.name}}
diff --git a/ui/desktop/tests/acceptance/projects/sessions/index-test.js b/ui/desktop/tests/acceptance/projects/sessions/index-test.js
index 1db0ff444..b5e8ca8eb 100644
--- a/ui/desktop/tests/acceptance/projects/sessions/index-test.js
+++ b/ui/desktop/tests/acceptance/projects/sessions/index-test.js
@@ -35,19 +35,25 @@ module('Acceptance | projects | sessions | index', function (hooks) {
scopes: {
global: null,
org: null,
+ org2: null,
project: null,
+ project2: null,
},
authMethods: {
global: null,
},
user: null,
+ target: null,
+ target2: null,
session: null,
+ session2: null,
};
const urls = {
scopes: {
global: null,
org: null,
+ org2: null,
},
authenticate: {
global: null,
@@ -56,7 +62,9 @@ module('Acceptance | projects | sessions | index', function (hooks) {
},
},
projects: null,
+ projects2: null,
sessions: null,
+ sessions2: null,
session: null,
};
@@ -74,7 +82,10 @@ module('Acceptance | projects | sessions | index', function (hooks) {
authenticateSession({ user_id: instances.user.id });
// create scopes
- instances.scopes.global = this.server.create('scope', { id: 'global' });
+ instances.scopes.global = this.server.create('scope', {
+ id: 'global',
+ name: 'Global',
+ });
const globalScope = { id: 'global', type: 'global' };
instances.scopes.org = this.server.create('scope', {
type: 'org',
@@ -85,7 +96,17 @@ module('Acceptance | projects | sessions | index', function (hooks) {
type: 'project',
scope: orgScope,
});
+ instances.scopes.org2 = this.server.create('scope', {
+ type: 'org',
+ scope: globalScope,
+ });
+ const org2Scope = { id: instances.scopes.org2.id, type: 'org' };
+ instances.scopes.project2 = this.server.create('scope', {
+ type: 'project',
+ scope: org2Scope,
+ });
+ // create resources
instances.authMethods.global = this.server.create('auth-method', {
scope: instances.scopes.global,
});
@@ -104,13 +125,33 @@ module('Acceptance | projects | sessions | index', function (hooks) {
},
'withAssociations',
);
+ // create resources in second org
+ instances.target2 = this.server.create(
+ 'target',
+ { scope: instances.scopes.project2 },
+ 'withAssociations',
+ );
+ instances.session2 = this.server.create(
+ 'session',
+ {
+ scope: instances.scopes.project2,
+ target: instances.target2,
+ status: STATUS_SESSION_ACTIVE,
+ user: instances.user,
+ },
+ 'withAssociations',
+ );
urls.scopes.global = `/scopes/${instances.scopes.global.id}`;
urls.scopes.org = `/scopes/${instances.scopes.org.id}`;
+ urls.scopes.org2 = `/scopes/${instances.scopes.org2.id}`;
urls.authenticate.global = `${urls.scopes.global}/authenticate`;
urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`;
urls.projects = `${urls.scopes.org}/projects`;
+ urls.projects2 = `${urls.scopes.org2}/projects`;
+ urls.globalSessions = `${urls.scopes.global}/projects/sessions`;
urls.sessions = `${urls.projects}/sessions`;
+ urls.sessions2 = `${urls.projects2}/sessions`;
urls.session = `${urls.projects}/sessions/${instances.session.id}`;
// Mock the postMessage interface used by IPC.
@@ -169,7 +210,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await visit(urls.projects);
await click(`[href="${urls.sessions}"]`);
- await click('[data-test-session-detail-link]');
+ await click(`[data-test-session-detail-link="${instances.session.id}"]`);
assert.strictEqual(currentURL(), urls.session);
});
@@ -181,9 +222,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await visit(urls.sessions);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.isVisible();
});
@@ -195,9 +234,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await click(`[href="${urls.sessions}"]`);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.isVisible();
});
@@ -209,9 +246,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await click(`[href="${urls.sessions}"]`);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.isVisible();
});
@@ -223,9 +258,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await click(`[href="${urls.sessions}"]`);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.isVisible();
});
@@ -235,12 +268,10 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await visit(urls.sessions);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.doesNotExist();
assert
- .dom('tbody tr:first-child td:first-child [data-test-session-id-copy]')
+ .dom(`[data-test-session-id-copy="${instances.session.id}"]`)
.isVisible();
});
@@ -250,12 +281,10 @@ module('Acceptance | projects | sessions | index', function (hooks) {
await visit(urls.sessions);
assert
- .dom(
- 'tbody tr:first-child td:first-child [data-test-session-detail-link]',
- )
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
.doesNotExist();
assert
- .dom('tbody tr:first-child td:first-child [data-test-session-id-copy]')
+ .dom(`[data-test-session-id-copy="${instances.session.id}"]`)
.isVisible();
});
@@ -332,4 +361,41 @@ module('Acceptance | projects | sessions | index', function (hooks) {
assert.dom('[role="alert"].is-error').isVisible();
});
+
+ test('user can change org scope and only sessions for that org will be displayed', async function (assert) {
+ this.stubClientDaemonSearch(
+ 'sessions',
+ 'sessions',
+ 'targets',
+ 'targets',
+ 'sessions',
+ 'targets',
+ {
+ resource: 'sessions',
+ func: () => [instances.session2],
+ },
+ 'sessions',
+ 'targets',
+ );
+ await visit(urls.globalSessions);
+
+ assert
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
+ .isVisible();
+ assert
+ .dom(`[data-test-session-detail-link="${instances.session2.id}"]`)
+ .isVisible();
+
+ // change scope in app header
+ await click('.rose-header-nav .rose-dropdown a:nth-of-type(3)');
+ // navigate to back sessions
+ await click(`[href="${urls.sessions2}"]`);
+
+ assert
+ .dom(`[data-test-session-detail-link="${instances.session.id}"]`)
+ .doesNotExist();
+ assert
+ .dom(`[data-test-session-detail-link="${instances.session2.id}"]`)
+ .isVisible();
+ });
});
diff --git a/ui/desktop/tests/acceptance/projects/targets/index-test.js b/ui/desktop/tests/acceptance/projects/targets/index-test.js
index e7c6ecb4a..5d14f2b6e 100644
--- a/ui/desktop/tests/acceptance/projects/targets/index-test.js
+++ b/ui/desktop/tests/acceptance/projects/targets/index-test.js
@@ -47,12 +47,15 @@ module('Acceptance | projects | targets | index', function (hooks) {
scopes: {
global: null,
org: null,
+ org2: null,
project: null,
+ project2: null,
},
authMethods: {
global: null,
},
target: null,
+ target2: null,
session: null,
};
@@ -85,7 +88,10 @@ module('Acceptance | projects | targets | index', function (hooks) {
this.server.get('/targets', ({ targets }) => targets.all());
// Generate scopes
- instances.scopes.global = this.server.create('scope', { id: 'global' });
+ instances.scopes.global = this.server.create('scope', {
+ id: 'global',
+ name: 'Global',
+ });
const globalScope = { id: 'global', type: 'global' };
instances.scopes.org = this.server.create('scope', {
type: 'org',
@@ -96,6 +102,15 @@ module('Acceptance | projects | targets | index', function (hooks) {
type: 'project',
scope: orgScope,
});
+ instances.scopes.org2 = this.server.create('scope', {
+ type: 'org',
+ scope: globalScope,
+ });
+ const org2Scope = { id: instances.scopes.org2.id, type: 'org' };
+ instances.scopes.project2 = this.server.create('scope', {
+ type: 'project',
+ scope: org2Scope,
+ });
// Generate resources
instances.authMethods.global = this.server.create('auth-method', {
@@ -119,6 +134,10 @@ module('Acceptance | projects | targets | index', function (hooks) {
},
'withAssociations',
);
+ instances.target2 = this.server.create('target', {
+ scope: instances.scopes.project2,
+ address: 'localhost',
+ });
// Generate route URLs for resources
urls.scopes.global = `/scopes/${instances.scopes.global.id}`;
@@ -412,4 +431,28 @@ module('Acceptance | projects | targets | index', function (hooks) {
assert.strictEqual(currentURL(), urls.session);
});
+
+ test('user can change org scope and only targets for that org will be displayed', async function (assert) {
+ this.stubClientDaemonSearch('targets', 'sessions', 'targets', 'sessions', {
+ resource: 'targets',
+ func: () => [instances.target],
+ });
+
+ await visit(urls.scopes.global);
+
+ assert
+ .dom(`[data-test-target-project-id="${instances.scopes.project.id}"]`)
+ .exists();
+ assert
+ .dom(`[data-test-target-project-id="${instances.scopes.project2.id}"]`)
+ .exists();
+
+ await click('.rose-header-nav .rose-dropdown a:nth-of-type(2)');
+ assert
+ .dom(`[data-test-target-project-id="${instances.scopes.project.id}"]`)
+ .exists();
+ assert
+ .dom(`[data-test-target-project-id="${instances.scopes.project2.id}"]`)
+ .doesNotExist();
+ });
});