Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions addons/api/addon/handlers/sqlite-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export default class SqliteHandler {
payload,
storeToken,
tokenKey,
pushToStore,
serializer,
store,
schema,
Expand Down Expand Up @@ -207,6 +208,7 @@ export default class SqliteHandler {
payload,
storeToken,
tokenKey,
pushToStore,
serializer,
store,
schema,
Expand All @@ -218,11 +220,6 @@ export default class SqliteHandler {
]);
}

// Remove any records from the DB if the API indicates they've been deleted
if (payload.removed_ids?.length > 0) {
await this.sqlite.deleteResource(type, payload.removed_ids);
}

const normalizedPayload = serializer.normalizeResponse(
store,
schema,
Expand All @@ -233,6 +230,21 @@ export default class SqliteHandler {

const { data: payloadData } = normalizedPayload;

// Remove any records from the DB if the API indicates they've been deleted
// Additionally remove deleted records from ember data store for symmetry
if (payload.removed_ids?.length > 0) {
await this.sqlite.deleteResource(type, payload.removed_ids);

if (pushToStore) {
payload.removed_ids.forEach((id) => {
const record = store.peekRecord(type, id);
if (record) {
store.unloadRecord(record);
}
});
}
}

// Store the new data we just got back from the API refresh
const items = payloadData.map((datum) => {
const params = Object.values(modelMapping[type]).map((key) => {
Expand Down
3 changes: 2 additions & 1 deletion ui/admin/app/routes/scopes/scope/targets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export default class ScopesScopeTargetsIndexRoute extends Route {
if (this.can.can('list model', scope, { collection: 'sessions' })) {
const sessions = await this.store.query('session', {
scope_id,
include_terminated: true,
query: {
filters: {
scope_id: [{ equals: scope_id }],
Expand Down Expand Up @@ -147,7 +148,7 @@ export default class ScopesScopeTargetsIndexRoute extends Route {
},
},
},
{ pushToStore: true, peekDb: true },
{ peekDb: true },
);
}
return { targets, doTargetsExist, totalItems };
Expand Down
10 changes: 7 additions & 3 deletions ui/admin/tests/acceptance/targets/list-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,11 @@ module('Acceptance | targets | list', function (hooks) {
instances.sshTarget.id,
'session is associated with correct target',
);
const emberDataSessionModel = this.owner
const emberDataSessionModelBefore = this.owner
.lookup('service:store')
.peekRecord('session', instances.session.id);
assert.strictEqual(
emberDataSessionModel.status,
emberDataSessionModelBefore.status,
STATUS_SESSION_ACTIVE,
'ember data session model is active',
);
Expand All @@ -389,14 +389,18 @@ module('Acceptance | targets | list', function (hooks) {
instances.session.status = STATUS_SESSION_TERMINATED;

await click(commonSelectors.HREF(urls.targets));

const emberDataSessionModelAfter = this.owner
.lookup('service:store')
.peekRecord('session', instances.session.id);
assert
.dom(selectors.TABLE_TARGETS_ROW(instances.sshTarget.id))
.exists('the target is still listed in the table');
assert
.dom(selectors.TABLE_ACTIVE_SESSIONS(instances.sshTarget.id))
.doesNotExist('the target does not have an active session');
assert.strictEqual(
emberDataSessionModel.status,
emberDataSessionModelAfter.status,
STATUS_SESSION_TERMINATED,
'the session ember data model status is updated',
);
Expand Down
4 changes: 2 additions & 2 deletions ui/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ The static production assets are saved into the `dist/` folder.
The Boundary CLI is downloaded and extracted to `electron-app/cli/` folder as part of
packaging. CLI version is defined in `electron-app/config/cli.js`.

Similar to running in development, you can also use `BYPASS_CLI_SETUP=true` to
bypass the download of the CLI, which can be useful for pre-release testing. See
Similar to running in development, you can also use `SETUP_CLI=true` to
enable the download of the CLI, which can be useful for pre-release testing. See
[Developing Using Non-Release Versions of
Boundary](#developing-using-non-release-versions-of-boundary) for more details.

Expand Down
25 changes: 7 additions & 18 deletions ui/desktop/app/routes/scopes/scope/projects/targets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
filters.type.push({ equals: type });
});

// Before querying sessions, unload sessions currently stored in ember data store
// so that we remove any expired sessions that still might be cached.
this.store.unloadAll('session');

const sessions = await this.getSessions(orgScope, scopes, orgFilter);
this.addActiveSessionFilters(filters, availableSessions, sessions);

Expand Down Expand Up @@ -156,27 +160,12 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
},
});

// To correctly show targets with active sessions, the associated
// sessions need to be queried to sync all the session models in
// ember data and retrieve their updated `status` properties
const sessionsPromise = this.store.query(
'session',
{
query: {
filters: {
target_id: targets.map((target) => ({ equals: target.id })),
},
},
},
{ pushToStore: true },
);

// Load the sessions and aliases for the targets on the current page
// Load the aliases for the targets on the current page
try {
await Promise.all([aliasPromise, sessionsPromise]);
await aliasPromise;
} catch (e) {
__electronLog?.warn(
'Could not retrieve aliases and/or sessions for targets',
'Could not retrieve aliases for targets',
e.message,
);
// Separately await and catch the error here so we can continue loading
Expand Down
7 changes: 5 additions & 2 deletions ui/desktop/electron-app/src/models/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const {
spawnAsyncJSONPromise,
spawnSync,
} = require('../helpers/spawn-promise.js');
const log = require('electron-log/main');

class Session {
#id;
Expand Down Expand Up @@ -89,7 +90,6 @@ class Session {
).then((spawnedSession) => {
this.#process = spawnedSession.childProcess;
this.#proxyDetails = spawnedSession.response;
this.#process = spawnedSession.childProcess;
this.#id = this.#proxyDetails.session_id;
return this.#proxyDetails;
});
Expand All @@ -102,7 +102,10 @@ class Session {
return new Promise((resolve, reject) => {
if (this.isRunning) {
this.#process.on('close', () => resolve());
this.#process.on('error', (e) => reject(e));
this.#process.on('error', (e) => {
log.error('Process error in session stop method: ', e);
return reject(e);
});

// Cancel session before killing process
const sanitizedToken = sanitizer.base62EscapeAndValidate(this.#token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ module('Acceptance | projects | sessions | index', function (hooks) {
'sessions',
'targets',
'aliases',
'sessions',
{
resource: 'sessions',
func: () => [instances.session2],
Expand Down
41 changes: 20 additions & 21 deletions ui/desktop/tests/acceptance/projects/targets/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ module('Acceptance | projects | targets | index', function (hooks) {
targets: null,
target: null,
session: null,
sessions: null,
};

const setDefaultClusterUrl = (test) => {
Expand Down Expand Up @@ -158,7 +157,7 @@ module('Acceptance | projects | targets | index', function (hooks) {
setDefaultClusterUrl(this);

this.ipcStub.withArgs('isCacheDaemonRunning').returns(true);
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
});

test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) {
Expand Down Expand Up @@ -214,7 +213,7 @@ module('Acceptance | projects | targets | index', function (hooks) {
test('visiting targets list view with no targets', async function (assert) {
this.server.schema.targets.all().destroy();
this.server.schema.sessions.all().destroy();
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');

await visit(urls.projects);

Expand All @@ -235,7 +234,7 @@ module('Acceptance | projects | targets | index', function (hooks) {

instances.target.authorized_actions =
instances.target.authorized_actions.filter((item) => item !== 'read');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');

await visit(urls.projects);

Expand Down Expand Up @@ -282,7 +281,7 @@ module('Acceptance | projects | targets | index', function (hooks) {
instances.target.authorized_actions.filter(
(item) => item !== 'authorize-session',
);
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');

await visit(urls.projects);

Expand Down Expand Up @@ -332,7 +331,7 @@ module('Acceptance | projects | targets | index', function (hooks) {

instances.target.authorized_actions =
instances.target.authorized_actions.filter((item) => item !== 'read');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
this.ipcStub.withArgs('cliExists').returns(true);
this.ipcStub.withArgs('connect').returns({
session_id: instances.session.id,
Expand Down Expand Up @@ -367,7 +366,7 @@ module('Acceptance | projects | targets | index', function (hooks) {
instances.target.authorized_actions.filter((item) => item !== 'read');
this.ipcStub.withArgs('cliExists').returns(true);
this.ipcStub.withArgs('connect').rejects();
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
const confirmService = this.owner.lookup('service:confirm');
confirmService.enabled = true;
await visit(urls.projects);
Expand Down Expand Up @@ -429,17 +428,12 @@ module('Acceptance | projects | targets | index', function (hooks) {
'sessions',
'targets',
'aliases',
'sessions',
{
resource: 'sessions',
func: () => [],
},
'targets',
'aliases',
{
resource: 'sessions',
func: () => [],
},
);
await visit(urls.projects);

Expand Down Expand Up @@ -478,7 +472,7 @@ module('Acceptance | projects | targets | index', function (hooks) {

instances.session.authorized_actions =
instances.session.authorized_actions.filter((item) => item !== 'cancel');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
await visit(urls.projects);

await click(`[href="${urls.targets}"]`);
Expand Down Expand Up @@ -534,7 +528,7 @@ module('Acceptance | projects | targets | index', function (hooks) {

instances.session.authorized_actions =
instances.session.authorized_actions.filter((item) => item !== 'read');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
await visit(urls.projects);

await click(`[href="${urls.targets}"]`);
Expand Down Expand Up @@ -569,13 +563,11 @@ module('Acceptance | projects | targets | index', function (hooks) {
'targets',
'aliases',
'sessions',
'sessions',
{
resource: 'targets',
func: () => [instances.target],
},
'aliases',
'sessions',
);

await visit(urls.scopes.global);
Expand Down Expand Up @@ -656,7 +648,6 @@ module('Acceptance | projects | targets | index', function (hooks) {
'sessions',
'targets',
'aliases',
'sessions',

'sessions',
'sessions',
Expand All @@ -665,19 +656,21 @@ module('Acceptance | projects | targets | index', function (hooks) {
'sessions',
'targets',
'aliases',
'sessions',
);

const activeSessionFlyoutButtonSelector = (id) =>
`[data-test-targets-sessions-flyout-button="${id}"]`;

assert.strictEqual(instances.session.status, STATUS_SESSION_ACTIVE);
await visit(urls.targets);
const emberDataSessionModel = this.owner
const emberDataSessionModelBefore = this.owner
.lookup('service:store')
.peekRecord('session', instances.session.id);

assert.strictEqual(emberDataSessionModel.status, STATUS_SESSION_ACTIVE);
assert.strictEqual(
emberDataSessionModelBefore.status,
STATUS_SESSION_ACTIVE,
);

assert
.dom(activeSessionFlyoutButtonSelector(instances.session.targetId))
Expand All @@ -695,7 +688,13 @@ module('Acceptance | projects | targets | index', function (hooks) {

await click(`[href="${urls.targets}"]`);

assert.strictEqual(emberDataSessionModel.status, STATUS_SESSION_TERMINATED);
const emberDataSessionModelAfter = this.owner
.lookup('service:store')
.peekRecord('session', instances.session.id);
assert.strictEqual(
emberDataSessionModelAfter.status,
STATUS_SESSION_TERMINATED,
);
assert
.dom(activeSessionFlyoutButtonSelector(instances.session.targetId))
.doesNotExist();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
setDefaultClusterUrl(this);

this.ipcStub.withArgs('isCacheDaemonRunning').returns(true);
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
});

test('user can connect to a target with an address', async function (assert) {
Expand Down
8 changes: 2 additions & 6 deletions ui/desktop/tests/acceptance/scopes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ module('Acceptance | scopes', function (hooks) {
setDefaultClusterUrl(this);

this.ipcStub.withArgs('isCacheDaemonRunning').returns(true);
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');
});

test('visiting index', async function (assert) {
Expand Down Expand Up @@ -234,22 +234,18 @@ module('Acceptance | scopes', function (hooks) {
'sessions',
'targets',
'aliases',
'sessions',

'sessions',
'targets',
'aliases',
'sessions',

'sessions',
'targets',
'aliases',
'sessions',

'sessions',
'targets',
'aliases',
'sessions',
);
await visit(urls.targets);

Expand Down Expand Up @@ -300,7 +296,7 @@ module('Acceptance | scopes', function (hooks) {
test('visiting empty targets', async function (assert) {
this.server.schema.targets.all().destroy();
this.server.schema.sessions.all().destroy();
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases');

await visit(urls.targets);

Expand Down
Loading
Loading