Remove renderer url (#3194)
* feat: 🎸 Refactor how we store cluster URL
This commit is contained in:
1 parent
3d257afd49
commit
7dadc53fe1
26 files changed
+139
-217
No files matched your search
@@ -133,6 +133,8 @@ export const electronTest = test.extend({
|
||||
electronPage: async ({ electronApp }, use) => {
|
||||
const page = await electronApp.firstWindow();
|
||||
await page.evaluate(() => localStorage.clear());
|
||||
// Reset the cluster URL stored by electron
|
||||
await page.evaluate(() => window.desktop.cluster.resetClusterUrl());
|
||||
await page.context().tracing.start({ screenshots: true, snapshots: true });
|
||||
|
||||
await use(page);
|
||||
|
||||
@@ -45,7 +45,7 @@ export default class ApplicationController extends Controller {
|
||||
* @type {object}
|
||||
*/
|
||||
get currentScope() {
|
||||
if (this.scope.org.isOrg) {
|
||||
if (this.scope.org?.isOrg) {
|
||||
return { name: this.scope.org.displayName, icon: 'org' };
|
||||
} else {
|
||||
return { name: this.intl.t('titles.global'), icon: 'globe' };
|
||||
@@ -100,13 +100,14 @@ export default class ApplicationController extends Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from clusterUrl and invalidates session, thereby resetting
|
||||
* the client and reloading to the onboarding clusterUrl screen.
|
||||
* Invalidates the session and navigates to the cluster-url route.
|
||||
* The cluster URL is preserved so that upon reload the user is directed
|
||||
* back to the authentication screen for the same cluster.
|
||||
*/
|
||||
@action
|
||||
disconnect() {
|
||||
this.clusterUrl.resetClusterUrl();
|
||||
this.session.invalidate();
|
||||
this.router.replaceWith('cluster-url');
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright IBM Corp. 2021, 2026
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { getOwner } from '@ember/application';
|
||||
|
||||
export function initialize(registry) {
|
||||
// Lookup the application route
|
||||
const ApplicationRoute = registry.resolveRegistration
|
||||
? registry.resolveRegistration('route:application')
|
||||
: registry.resolve('route:application');
|
||||
|
||||
ApplicationRoute.reopen({
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
const originalBeforeModel = this.beforeModel;
|
||||
|
||||
// Override the beforeModel hook and initialize the clusterUrl
|
||||
this.beforeModel = async function () {
|
||||
const clusterUrl = getOwner(this).lookup('service:clusterUrl');
|
||||
return clusterUrl.updateClusterUrl().then(
|
||||
() => originalBeforeModel.apply(this, arguments),
|
||||
() => originalBeforeModel.apply(this, arguments),
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
after: 'ember-simple-auth',
|
||||
initialize,
|
||||
};
|
||||
@@ -15,6 +15,7 @@ export default class ApplicationRoute extends Route {
|
||||
@service session;
|
||||
@service clusterUrl;
|
||||
@service intl;
|
||||
@service store;
|
||||
@service rdp;
|
||||
@service terminal;
|
||||
|
||||
@@ -25,19 +26,20 @@ export default class ApplicationRoute extends Route {
|
||||
*/
|
||||
routeIfUnauthenticated = 'index';
|
||||
|
||||
/**
|
||||
* Check that the clusterUrl specified in the renderer matches the clusterUrl
|
||||
* reported by the main process. If they differ, update the main process
|
||||
* clusterUrl so that the renderer's CSP can be rewritten to allow requests.
|
||||
*/
|
||||
@notifyError(({ message }) => message, {
|
||||
catch: true,
|
||||
log: { origin: 'ApplicationRoute:beforeModel' },
|
||||
})
|
||||
async beforeModel() {
|
||||
this.intl.setLocale(['en-us']);
|
||||
|
||||
const clusterUrl = await this.clusterUrl.getClusterUrl();
|
||||
if (clusterUrl) {
|
||||
const adapter = this.store.adapterFor('application');
|
||||
adapter.host = clusterUrl;
|
||||
}
|
||||
|
||||
await this.session.setup();
|
||||
await this.clusterUrl.updateClusterUrl();
|
||||
const theme = this.session.get('data.theme');
|
||||
/* eslint-disable-next-line ember/no-controller-access-in-routes */
|
||||
const controller = this.controllerFor(this.routeName);
|
||||
|
||||
@@ -41,9 +41,9 @@ export default class ClusterUrlRoute extends Route {
|
||||
* Adds the existing clusterUrl, if any, to the controller scope.
|
||||
* @param {Controller} controller
|
||||
*/
|
||||
setupController(controller) {
|
||||
async setupController(controller) {
|
||||
super.setupController(...arguments);
|
||||
let clusterUrl = this.clusterUrl.rendererClusterUrl;
|
||||
let clusterUrl = await this.clusterUrl.getClusterUrl();
|
||||
// If clusterUrl is unset and this is a development environment,
|
||||
// auto-set the clusterUrl field of the UI for better DX.
|
||||
// The controller URL is almost always the same as the current window when
|
||||
|
||||
@@ -18,12 +18,12 @@ export default class IndexRoute extends Route {
|
||||
/**
|
||||
* If no clusterUrl is specified yet, redirects to cluster-url, otherwise scopes.
|
||||
*/
|
||||
redirect() {
|
||||
async beforeModel() {
|
||||
// cleanup terminal view when navigating to index route - on window reload
|
||||
this.terminal.cleanup();
|
||||
|
||||
const rendererClusterUrl = this.clusterUrl.rendererClusterUrl;
|
||||
if (!rendererClusterUrl) {
|
||||
const clusterUrl = await this.clusterUrl.getClusterUrl();
|
||||
if (!clusterUrl) {
|
||||
this.router.replaceWith('cluster-url');
|
||||
} else {
|
||||
this.router.replaceWith('scopes');
|
||||
|
||||
@@ -17,8 +17,11 @@ export default class ScopesScopeAuthenticateRoute extends Route {
|
||||
|
||||
// =methods
|
||||
|
||||
beforeModel() {
|
||||
if (this.session.isAuthenticated) {
|
||||
async beforeModel() {
|
||||
const clusterUrl = await this.clusterUrl.getClusterUrl();
|
||||
if (!clusterUrl) {
|
||||
this.router.replaceWith('cluster-url');
|
||||
} else if (this.session.isAuthenticated) {
|
||||
this.router.replaceWith('scopes.scope.index');
|
||||
}
|
||||
}
|
||||
@@ -64,17 +67,13 @@ export default class ScopesScopeAuthenticateRoute extends Route {
|
||||
};
|
||||
}
|
||||
|
||||
redirect() {
|
||||
if (!this.clusterUrl.rendererClusterUrl) this.router.replaceWith('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the existing clusterUrl, if any, to the controller scope.
|
||||
* @param {Controller} controller
|
||||
*/
|
||||
setupController(controller) {
|
||||
async setupController(controller) {
|
||||
super.setupController(...arguments);
|
||||
const clusterUrl = this.clusterUrl.rendererClusterUrl;
|
||||
const clusterUrl = await this.clusterUrl.getClusterUrl();
|
||||
controller.setProperties({ clusterUrl });
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ export default class ScopesScopeProjectsSettingsIndexRoute extends Route {
|
||||
|
||||
const logLevel = await window.desktop.logging.getLogLevel();
|
||||
const logPath = await window.desktop.logging.getLogPath();
|
||||
const serverInformation = this.clusterUrl.rendererClusterUrl;
|
||||
const serverInformation = await this.clusterUrl.getClusterUrl();
|
||||
const { isLinux } = await window.desktop.system.checkOS();
|
||||
|
||||
return {
|
||||
|
||||
@@ -18,7 +18,6 @@ export default class ScopesScopeProjectsTargetsIndexRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service abilities;
|
||||
@service clusterUrl;
|
||||
@service resourceFilterStore;
|
||||
@service router;
|
||||
@service session;
|
||||
|
||||
@@ -12,7 +12,6 @@ export default class ClusterUrlService extends Service {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service storage;
|
||||
|
||||
// =attributes
|
||||
|
||||
@@ -23,35 +22,10 @@ export default class ClusterUrlService extends Service {
|
||||
return this.store.adapterFor('application');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {?string}
|
||||
*/
|
||||
get rendererClusterUrl() {
|
||||
return this.storage.getItem('cluster-url');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?string} clusterUrl
|
||||
*/
|
||||
set rendererClusterUrl(clusterUrl) {
|
||||
this.storage.setItem('cluster-url', clusterUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Promise{?string}}
|
||||
*/
|
||||
get mainClusterUrl() {
|
||||
return window.desktop.cluster.getClusterUrl();
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Sets the main clusterUrl equal to the current renderer clusterUrl (if any).
|
||||
*/
|
||||
async updateClusterUrl() {
|
||||
const rendererClusterUrl = this.rendererClusterUrl;
|
||||
if (rendererClusterUrl) await this.setClusterUrl(rendererClusterUrl);
|
||||
async getClusterUrl() {
|
||||
return window.desktop.cluster.getClusterUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,26 +47,24 @@ export default class ClusterUrlService extends Service {
|
||||
clusterUrl = clusterUrl.trim();
|
||||
clusterUrl = clusterUrl.replace(/\/*$/, '');
|
||||
this.adapter.host = clusterUrl;
|
||||
this.rendererClusterUrl = clusterUrl;
|
||||
if (clusterUrl !== (await this.mainClusterUrl)) {
|
||||
if (clusterUrl !== (await this.getClusterUrl())) {
|
||||
await window.desktop.cluster.setClusterUrl(clusterUrl);
|
||||
}
|
||||
} catch (e) {
|
||||
this.adapter.host = originalHost;
|
||||
this.rendererClusterUrl = null;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clusterUrl.
|
||||
* Resets the clusterUrl in both the electron store and the adapter host.
|
||||
*/
|
||||
@notifyError(({ message }) => message, {
|
||||
catch: true,
|
||||
log: { origin: 'resetClusterUrl' },
|
||||
})
|
||||
async resetClusterUrl() {
|
||||
this.rendererClusterUrl = null;
|
||||
await window.desktop.cluster.resetClusterUrl();
|
||||
this.adapter.host = undefined;
|
||||
return window.desktop.cluster.resetClusterUrl();
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ handle('getClusterUrl', () => runtimeSettings.clusterUrl);
|
||||
handle('setClusterUrl', async (requestOrigin) => {
|
||||
const clusterUrl = sanitizer.urlValidate(requestOrigin);
|
||||
await runtimeSettings.validateClusterUrl(clusterUrl);
|
||||
await runtimeSettings.setClusterUrl(clusterUrl);
|
||||
await runtimeSettings.triggerClusterUrlUpdate(clusterUrl);
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,26 +4,25 @@
|
||||
*/
|
||||
|
||||
const { netRequest } = require('../helpers/request-promise.js');
|
||||
const store = require('../services/electron-store-manager');
|
||||
|
||||
// Runtime settings are any configuration, especially user-specified,
|
||||
// set up at runtime. For example, the Boundary clusterUrl is a runtime setting.
|
||||
class RuntimeSettings {
|
||||
// Internal private clusterUrl is exposed via getter/setter below.
|
||||
#clusterUrl = undefined;
|
||||
|
||||
/**
|
||||
* The user-specified Boundary clusterUrl, which should be allowed by CSP.
|
||||
* @type {?string}
|
||||
*/
|
||||
get clusterUrl() {
|
||||
return this.#clusterUrl;
|
||||
return store.get('clusterUrl');
|
||||
}
|
||||
|
||||
async setClusterUrl(clusterUrl) {
|
||||
if (this.#clusterUrl !== clusterUrl) {
|
||||
this.#clusterUrl = clusterUrl;
|
||||
await this.triggerClusterUrlChanged();
|
||||
}
|
||||
/**
|
||||
* Sets the user specified Boundary clusterUrl.
|
||||
* @param value {string}
|
||||
*/
|
||||
set clusterUrl(value) {
|
||||
store.set('clusterUrl', value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,8 +50,8 @@ class RuntimeSettings {
|
||||
/**
|
||||
* Sets the clusterUrl to null.
|
||||
*/
|
||||
async resetClusterUrl() {
|
||||
await this.setClusterUrl(null);
|
||||
resetClusterUrl() {
|
||||
store.delete('clusterUrl');
|
||||
}
|
||||
|
||||
// Quick and dirty event handler pattern to enable the application to respond
|
||||
@@ -63,11 +62,14 @@ class RuntimeSettings {
|
||||
this.#clusterUrlWatchers.push(fn);
|
||||
}
|
||||
|
||||
async triggerClusterUrlChanged() {
|
||||
// We currently only store one function but this will execute serially
|
||||
// which may or may not be the desired behavior if there ever is more
|
||||
for (const fn of this.#clusterUrlWatchers) {
|
||||
await fn(this.#clusterUrl);
|
||||
async triggerClusterUrlUpdate(clusterUrl) {
|
||||
if (this.clusterUrl !== clusterUrl) {
|
||||
this.clusterUrl = clusterUrl;
|
||||
for (const fn of this.#clusterUrlWatchers) {
|
||||
// We currently only store one function but this will execute serially
|
||||
// which may or may not be the desired behavior if there ever is more
|
||||
await fn(this.clusterUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,12 +71,6 @@ module('Acceptance | authentication', function (hooks) {
|
||||
const MODAL_CANCEL_BTN = '.hds-modal__footer .hds-button--color-secondary';
|
||||
const HEADER_DROPDOWN_BTN = '.app-header__utility-actions button';
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
await invalidateSession();
|
||||
|
||||
@@ -130,7 +124,7 @@ module('Acceptance | authentication', function (hooks) {
|
||||
urls.targets = `${urls.projects}/targets`;
|
||||
urls.sessions = `${urls.projects}/sessions`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
});
|
||||
|
||||
hooks.afterEach(async function () {
|
||||
@@ -147,8 +141,17 @@ module('Acceptance | authentication', function (hooks) {
|
||||
|
||||
test('visiting authenticate route without clusterUrl redirects to clusterUrl index', async function (assert) {
|
||||
assert.expect(1);
|
||||
this.owner.lookup('service:clusterUrl').rendererClusterUrl = null;
|
||||
await visit(urls.authenticate.global);
|
||||
window.desktop.cluster.getClusterUrl.resolves(null);
|
||||
|
||||
try {
|
||||
await visit(urls.authenticate.global);
|
||||
} catch (e) {
|
||||
if (e.message === 'TransitionAborted') {
|
||||
// Ignore the expected transition abort error caused by the redirect in beforeModel
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
assert.strictEqual(currentURL(), urls.clusterUrl);
|
||||
});
|
||||
|
||||
@@ -8,13 +8,11 @@ import { visit, currentURL, fillIn, click, find } from '@ember/test-helpers';
|
||||
import { setupApplicationTest } from 'desktop/tests/helpers';
|
||||
import sinon from 'sinon';
|
||||
import { invalidateSession } from 'ember-simple-auth/test-support';
|
||||
import { setupBrowserFakes } from 'ember-browser-services/test-support';
|
||||
import { setupDesktopContextBridgeApiMock } from '../helpers/desktop-context-bridge-api-mock';
|
||||
import config from '../../config/environment';
|
||||
|
||||
module('Acceptance | clusterUrl', function (hooks) {
|
||||
setupApplicationTest(hooks);
|
||||
setupBrowserFakes(hooks, { window: true });
|
||||
|
||||
const currentOrigin = window.location.origin;
|
||||
|
||||
@@ -108,7 +106,15 @@ module('Acceptance | clusterUrl', function (hooks) {
|
||||
|
||||
test('visiting index without a clusterUrl specified redirects to clusterUrl route', async function (assert) {
|
||||
assert.expect(2);
|
||||
await visit(urls.index);
|
||||
try {
|
||||
await visit(urls.index);
|
||||
} catch (e) {
|
||||
if (e.message === 'TransitionAborted') {
|
||||
// Ignore the expected transition abort error caused by the redirect in beforeModel
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
assert.notOk(window.desktop.clusterUrl);
|
||||
assert.strictEqual(currentURL(), urls.clusterUrl);
|
||||
|
||||
@@ -49,12 +49,6 @@ module('Acceptance | projects', function (hooks) {
|
||||
projects: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
instances.scopes.global = this.server.schema.scopes.find('global');
|
||||
instances.authMethods.global = this.server.schema.authMethods.first();
|
||||
@@ -87,7 +81,7 @@ module('Acceptance | projects', function (hooks) {
|
||||
urls.authenticate.methods.global = `${urls.authenticate.global}/${instances.authMethods.global.id}`;
|
||||
urls.projects = `${urls.scopes.org}/projects`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
});
|
||||
|
||||
test('visiting index while unauthenticated redirects to global authenticate method', async function (assert) {
|
||||
|
||||
@@ -72,12 +72,6 @@ module('Acceptance | projects | sessions | index', function (hooks) {
|
||||
session: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
// create scopes
|
||||
instances.scopes.global = this.server.schema.scopes.find('global');
|
||||
@@ -148,8 +142,7 @@ module('Acceptance | projects | sessions | index', function (hooks) {
|
||||
urls.sessions2 = `${urls.projects2}/sessions`;
|
||||
urls.session = `${urls.projects}/sessions/${instances.session.id}`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
window.desktop.daemon.isCacheDaemonRunning.resolves(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'sessions', 'targets');
|
||||
|
||||
|
||||
@@ -58,12 +58,6 @@ module('Acceptance | projects | sessions | session', function (hooks) {
|
||||
rdpSession: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
let originalUncaughtException = QUnit.onUncaughtException;
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
@@ -139,7 +133,7 @@ module('Acceptance | projects | sessions | session', function (hooks) {
|
||||
urls.session = `${urls.projects}/sessions/${instances.session.id}`;
|
||||
urls.rdpSession = `${urls.projects}/sessions/${instances.rdpSession.id}`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
|
||||
// mock RDP service calls
|
||||
this.rdpService = this.owner.lookup('service:rdp');
|
||||
|
||||
@@ -69,12 +69,6 @@ module('Acceptance | projects | settings | index', function (hooks) {
|
||||
const RDP_RECOMMENDED_CLIENT = '[data-test-recommended-rdp-client]';
|
||||
const RDP_RECOMMENDED_CLIENT_LINK = '[data-test-recommended-rdp-client] a';
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
// Generate scopes
|
||||
instances.scopes.global = this.server.schema.scopes.find('global');
|
||||
@@ -96,7 +90,7 @@ module('Acceptance | projects | settings | index', function (hooks) {
|
||||
urls.projects = `${urls.scopes.org}/projects`;
|
||||
urls.settings = `${urls.projects}/settings`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
|
||||
// mock RDP client data
|
||||
window.desktop.rdp.getRdpClients.resolves([
|
||||
|
||||
@@ -90,12 +90,6 @@ module('Acceptance | projects | targets | index', function (hooks) {
|
||||
sessions: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
// bypass mirage config that expects recursive to be passed in as queryParam
|
||||
this.server.get('/targets', ({ targets }) => targets.all());
|
||||
@@ -165,7 +159,7 @@ module('Acceptance | projects | targets | index', function (hooks) {
|
||||
// Generate resource counter
|
||||
getTargetCount = () => this.server.schema.targets.all().models.length;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
|
||||
window.desktop.daemon.isCacheDaemonRunning.resolves(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
|
||||
|
||||
@@ -77,12 +77,6 @@ module('Acceptance | projects | targets | target', function (hooks) {
|
||||
targetWithManyHosts: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
// bypass mirage config that expects recursive to be passed in as queryParam
|
||||
this.server.get('/targets', ({ targets }) => targets.all());
|
||||
@@ -150,8 +144,7 @@ module('Acceptance | projects | targets | target', function (hooks) {
|
||||
urls.targetWithTwoHosts = `${urls.targets}/${instances.targetWithTwoHosts.id}`;
|
||||
urls.targetWithManyHosts = `${urls.targets}/${instances.targetWithManyHosts.id}`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
window.desktop.daemon.isCacheDaemonRunning.resolves(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
|
||||
|
||||
|
||||
@@ -73,12 +73,6 @@ module('Acceptance | scopes', function (hooks) {
|
||||
target: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
// bypass mirage config that expects recursive to be passed in as queryParam
|
||||
this.server.get('/targets', ({ targets }) => targets.all());
|
||||
@@ -135,8 +129,7 @@ module('Acceptance | scopes', function (hooks) {
|
||||
urls.globalTargets = `${urls.globalProjects}/targets`;
|
||||
urls.target = `${urls.targets}/${instances.target.id}`;
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
window.desktop.daemon.isCacheDaemonRunning.resolves(true);
|
||||
this.stubCacheDaemonSearch('sessions', 'targets', 'aliases', 'sessions');
|
||||
|
||||
|
||||
@@ -16,25 +16,17 @@ module('Integration | Component | settings-card/server', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = 'hashicorp.cloud';
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
|
||||
test('it displays HCP cluster url in server information section', async function (assert) {
|
||||
await render(hbs`<SettingsCard::Server/>`);
|
||||
this.set('model', { serverInformation: 'boundary.hashicorp.cloud' });
|
||||
await render(hbs`<SettingsCard::Server @model={{this.model}}/>`);
|
||||
assert.dom(SERVER_NAME).hasText('HashiCorp Cloud Platform');
|
||||
assert.dom(SERVER_URL).hasText('hashicorp.cloud');
|
||||
assert.dom(SERVER_URL).hasText('boundary.hashicorp.cloud');
|
||||
});
|
||||
|
||||
test('it displays non HCP cluster url in server information section', async function (assert) {
|
||||
this.owner.lookup('service:clusterUrl').rendererClusterUrl =
|
||||
'everythingelse';
|
||||
await render(hbs`<SettingsCard::Server/>`);
|
||||
assert.dom(SERVER_NAME).hasText('Self-Managed');
|
||||
this.set('model', { serverInformation: 'everythingelse' });
|
||||
await render(hbs`<SettingsCard::Server @model={{this.model}}/>`);
|
||||
assert.dom(SERVER_NAME).hasText('Self-managed');
|
||||
assert.dom(SERVER_URL).hasText('everythingelse');
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import { setupDesktopContextBridgeApiMock } from '../../helpers/desktop-context-bridge-api-mock';
|
||||
import sinon from 'sinon';
|
||||
|
||||
module('Unit | Controller | application', function (hooks) {
|
||||
setupTest(hooks);
|
||||
@@ -40,18 +41,19 @@ module('Unit | Controller | application', function (hooks) {
|
||||
assert.strictEqual(session.data.theme, 'light');
|
||||
});
|
||||
|
||||
test('disconnect action de-authenticates a user and resets cluster url', async function (assert) {
|
||||
test('disconnect action de-authenticates a user and keeps last cluster url', async function (assert) {
|
||||
const url = 'http://localhost:9200';
|
||||
await clusterUrl.setClusterUrl(url);
|
||||
|
||||
assert.true(session.isAuthenticated);
|
||||
assert.strictEqual(clusterUrl.rendererClusterUrl, url);
|
||||
assert.strictEqual(await window.desktop.cluster.getClusterUrl(), url);
|
||||
assert.strictEqual(clusterUrl.adapter.host, url);
|
||||
|
||||
sinon.stub(controller.router, 'replaceWith');
|
||||
await controller.disconnect();
|
||||
|
||||
assert.false(session.isAuthenticated);
|
||||
assert.notOk(clusterUrl.rendererClusterUrl);
|
||||
assert.notOk(await window.desktop.cluster.getClusterUrl());
|
||||
assert.strictEqual(await window.desktop.cluster.getClusterUrl(), url);
|
||||
assert.strictEqual(clusterUrl.adapter.host, url);
|
||||
});
|
||||
});
|
||||
@@ -12,16 +12,13 @@ import { setupDesktopContextBridgeApiMock } from '../../helpers/desktop-context-
|
||||
module('Unit | Controller | cluster-url', function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
setupDesktopContextBridgeApiMock(hooks);
|
||||
|
||||
let controller;
|
||||
let clusterUrl;
|
||||
|
||||
setupDesktopContextBridgeApiMock(hooks);
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
await authenticateSession({});
|
||||
controller = this.owner.lookup('controller:cluster-url');
|
||||
clusterUrl = this.owner.lookup('service:cluster-url');
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
@@ -30,12 +27,10 @@ module('Unit | Controller | cluster-url', function (hooks) {
|
||||
|
||||
test('setClusterUrl action de-authenticates a user and resets cluster url', async function (assert) {
|
||||
const newClusterUrl = 'http://localhost:9200';
|
||||
assert.notEqual(clusterUrl.rendererClusterUrl, newClusterUrl);
|
||||
assert.notEqual(window.desktop.clusterUrl, newClusterUrl);
|
||||
|
||||
await controller.setClusterUrl(newClusterUrl);
|
||||
|
||||
assert.strictEqual(clusterUrl.rendererClusterUrl, newClusterUrl);
|
||||
assert.strictEqual(window.desktop.clusterUrl, newClusterUrl);
|
||||
});
|
||||
});
|
||||
@@ -35,12 +35,6 @@ module(
|
||||
targets: null,
|
||||
};
|
||||
|
||||
const setDefaultClusterUrl = (test) => {
|
||||
const windowOrigin = window.location.origin;
|
||||
const clusterUrl = test.owner.lookup('service:clusterUrl');
|
||||
clusterUrl.rendererClusterUrl = windowOrigin;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
controller = this.owner.lookup(
|
||||
'controller:scopes/scope/authenticate/method/index',
|
||||
@@ -58,7 +52,7 @@ module(
|
||||
|
||||
urls.targets = '/scopes/global/projects/targets';
|
||||
|
||||
setDefaultClusterUrl(this);
|
||||
window.desktop.cluster.getClusterUrl.resolves(window.location.origin);
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
|
||||
@@ -17,37 +17,69 @@ module('Unit | Service | clusterUrl', function (hooks) {
|
||||
service = this.owner.lookup('service:clusterUrl');
|
||||
});
|
||||
|
||||
test('resets clusterUrl on error', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
test('keeps clusterUrl on error', async function (assert) {
|
||||
assert.expect(3);
|
||||
await service.setClusterUrl(window.location.origin);
|
||||
|
||||
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
window.desktop.cluster.setClusterUrl.rejects();
|
||||
service.setClusterUrl('invalid-origin').catch(() => {
|
||||
assert.notOk(service.rendererClusterUrl);
|
||||
|
||||
try {
|
||||
await service.setClusterUrl('http://other-origin');
|
||||
} catch {
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
});
|
||||
assert.true(
|
||||
window.desktop.cluster.setClusterUrl.calledWithExactly(
|
||||
'http://other-origin',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('drops trailing slashes from clusterUrl on setClusterUrl', async function (assert) {
|
||||
assert.expect(4);
|
||||
await service.setClusterUrl(`${window.location.origin}/`);
|
||||
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
assert.true(
|
||||
window.desktop.cluster.setClusterUrl.calledWithExactly(
|
||||
window.location.origin,
|
||||
),
|
||||
);
|
||||
|
||||
await service.setClusterUrl(`${window.location.origin}//////`);
|
||||
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
assert.true(
|
||||
window.desktop.cluster.setClusterUrl.calledWithExactly(
|
||||
window.location.origin,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('trim spaces from clusterUrl on setClusterUrl', async function (assert) {
|
||||
assert.expect(4);
|
||||
await service.setClusterUrl(` ${window.location.origin}/ `);
|
||||
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
assert.true(
|
||||
window.desktop.cluster.setClusterUrl.calledWithExactly(
|
||||
window.location.origin,
|
||||
),
|
||||
);
|
||||
|
||||
await service.setClusterUrl(` ${window.location.origin} `);
|
||||
assert.strictEqual(service.rendererClusterUrl, window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
assert.true(
|
||||
window.desktop.cluster.setClusterUrl.calledWithExactly(
|
||||
window.location.origin,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('resetClusterUrl clears adapter host and invokes IPC', async function (assert) {
|
||||
await service.setClusterUrl(window.location.origin);
|
||||
assert.strictEqual(service.adapter.host, window.location.origin);
|
||||
|
||||
await service.resetClusterUrl();
|
||||
|
||||
assert.strictEqual(service.adapter.host, undefined);
|
||||
assert.true(window.desktop.cluster.resetClusterUrl.calledOnce);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user