refactor: 💡 remove route-action usage for scopes in desktop (#2447)
* refactor: 💡 remove route-action usage for scopes in desktop ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-12621
This commit is contained in:
1 parent
98cd9dc1ec
commit
8605a54221
21 files changed
+395
-141
No files matched your search
@@ -5,10 +5,48 @@
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default class ApplicationController extends Controller {
|
||||
// =services
|
||||
|
||||
@service ipc;
|
||||
@service session;
|
||||
@service clusterUrl;
|
||||
@service flashMessages;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Delegates invalidation to the session service.
|
||||
*/
|
||||
@action
|
||||
invalidateSession() {
|
||||
this.session.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from clusterUrl and invalidates session, thereby resetting
|
||||
* the client and reloading to the onboarding clusterUrl screen.
|
||||
*/
|
||||
@action
|
||||
disconnect() {
|
||||
this.clusterUrl.resetClusterUrl();
|
||||
this.invalidateSession();
|
||||
}
|
||||
|
||||
@action
|
||||
minimize() {
|
||||
this.ipc.invoke('minimizeWindow');
|
||||
}
|
||||
|
||||
@action
|
||||
toggleFullScreen() {
|
||||
this.ipc.invoke('toggleFullscreenWindow');
|
||||
}
|
||||
|
||||
@action
|
||||
close() {
|
||||
this.ipc.invoke('closeWindow');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ClusterUrlController extends Controller {
|
||||
// =services
|
||||
|
||||
@service router;
|
||||
@service('cluster-url') clusterUrlService;
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Points the API to the specified clusterUrl. When the main process receives
|
||||
* the clusterUrl, it is expected that the renderer will be restarted.
|
||||
* @param {string} clusterUrl
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(() => 'errors.cluster-url-verification-failed.description', {
|
||||
catch: true,
|
||||
})
|
||||
async setClusterUrl(clusterUrl) {
|
||||
await this.clusterUrlService.setClusterUrl(clusterUrl);
|
||||
this.router.replaceWith('index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ErrorController extends Controller {
|
||||
@controller('application') appUtilities;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeAuthenticateMethodIndexController extends Controller {
|
||||
// =services
|
||||
|
||||
@service session;
|
||||
@service ipc;
|
||||
@service intl;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Kicks off the OIDC auth flow by opening a new window to the provider.
|
||||
* @param {string} authenticatorName
|
||||
* @param {object} options
|
||||
*/
|
||||
async startOIDCAuthentication(authenticatorName, options) {
|
||||
const oidc = getOwner(this).lookup(authenticatorName);
|
||||
// TODO: delegate this call from the session service so that we don't have
|
||||
// to look up the authenticator directly
|
||||
const json = await oidc.startAuthentication(options);
|
||||
await this.openExternalOIDCFlow(json.attributes.auth_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the specified URL in a new tab or window. By default this uses
|
||||
* `window.open`, but may be overridden.
|
||||
* @param {string} url
|
||||
*/
|
||||
async openExternalOIDCFlow(url) {
|
||||
await this.ipc.invoke('openExternal', url);
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Delegates authentication to an authenticator of type matching the current
|
||||
* auth method. If authentication fails, notifies with an alert.
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(() => 'errors.authentication-failed.title', {
|
||||
sticky: false,
|
||||
catch: true,
|
||||
})
|
||||
async authenticate(authMethod, creds) {
|
||||
const scope = authMethod.scope;
|
||||
const authenticatorName = `authenticator:${authMethod.type}`;
|
||||
const requestCookies = false;
|
||||
switch (authMethod.type) {
|
||||
case 'password':
|
||||
case 'ldap':
|
||||
await this.session.authenticate(
|
||||
authenticatorName,
|
||||
creds,
|
||||
requestCookies,
|
||||
{ scope, authMethod },
|
||||
);
|
||||
this.router.transitionTo('index');
|
||||
break;
|
||||
case 'oidc':
|
||||
await this.startOIDCAuthentication(authenticatorName, {
|
||||
scope,
|
||||
authMethod,
|
||||
});
|
||||
this.router.transitionTo('scopes.scope.authenticate.method.oidc');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ export default class ScopesScopeAuthenticateMethodOidcController extends Control
|
||||
// =attributes
|
||||
|
||||
/**
|
||||
* Authetnication URL for the pending OIDC flow, if any.
|
||||
* Authentication URL for the pending OIDC flow, if any.
|
||||
* @type {?string}
|
||||
*/
|
||||
get authURL() {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
|
||||
export default class ScopesScopeProjectsErrorController extends Controller {
|
||||
@controller('application') appUtilities;
|
||||
}
|
||||
@@ -61,24 +61,6 @@ export default class ApplicationRoute extends Route {
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Delegates invalidation to the session service.
|
||||
*/
|
||||
@action
|
||||
invalidateSession() {
|
||||
this.session.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from clusterUrl and invalidates session, thereby resetting
|
||||
* the client and reloading to the onboarding clusterUrl screen.
|
||||
*/
|
||||
@action
|
||||
disconnect() {
|
||||
this.clusterUrl.resetClusterUrl();
|
||||
this.invalidateSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the session if a 401 error occurs and returns false to
|
||||
* prevent further error handling.
|
||||
@@ -121,19 +103,4 @@ export default class ApplicationRoute extends Route {
|
||||
rootEl.classList.remove('rose-theme-light');
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
minimize() {
|
||||
this.ipc.invoke('minimizeWindow');
|
||||
}
|
||||
|
||||
@action
|
||||
toggleFullScreen() {
|
||||
this.ipc.invoke('toggleFullscreenWindow');
|
||||
}
|
||||
|
||||
@action
|
||||
close() {
|
||||
this.ipc.invoke('closeWindow');
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import config from '../config/environment';
|
||||
|
||||
export default class ClusterUrlRoute extends Route {
|
||||
@@ -47,37 +45,13 @@ export default class ClusterUrlRoute extends Route {
|
||||
super.setupController(...arguments);
|
||||
let clusterUrl = this.clusterUrl.rendererClusterUrl;
|
||||
// If clusterUrl is unset and this is a development environment,
|
||||
// autoset the clusterUrl field of the UI for better DX.
|
||||
// auto-set the clusterUrl field of the UI for better DX.
|
||||
// The controller URL is almost always the same as the current window when
|
||||
// using mocks, and this makes development more rapid since developers
|
||||
// do not need to fill a clusterUrl on every session.
|
||||
if (!clusterUrl && config.autoOrigin) {
|
||||
clusterUrl = this.window.location.origin;
|
||||
}
|
||||
controller.setProperties({ clusterUrl: clusterUrl });
|
||||
}
|
||||
|
||||
/**
|
||||
* Points the API to the specified clusterUrl. When the main process receives
|
||||
* the clusterUrl, it is expected that the renderer will be restarted.
|
||||
* @param {string} clusterUrl
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
async setClusterUrl(clusterUrl) {
|
||||
try {
|
||||
await this.clusterUrl.setClusterUrl(clusterUrl);
|
||||
this.router.replaceWith('index');
|
||||
} catch (e) {
|
||||
// If scopes do not load, we assume this is not a Boundary API
|
||||
const errorMessage = this.intl.t(
|
||||
'errors.cluster-url-verification-failed.description',
|
||||
);
|
||||
this.flashMessages.danger(errorMessage, {
|
||||
notificationType: 'error',
|
||||
sticky: true,
|
||||
dismiss: (flash) => flash.destroyMessage(),
|
||||
});
|
||||
}
|
||||
controller.setProperties({ clusterUrl });
|
||||
}
|
||||
}
|
||||
@@ -5,19 +5,11 @@
|
||||
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { action } from '@ember/object';
|
||||
import { loading } from 'ember-loading';
|
||||
import { notifyError } from 'core/decorators/notify';
|
||||
|
||||
export default class ScopesScopeAuthenticateMethodRoute extends Route {
|
||||
// =services
|
||||
|
||||
@service store;
|
||||
@service session;
|
||||
@service ipc;
|
||||
@service intl;
|
||||
@service router;
|
||||
|
||||
// =methods
|
||||
|
||||
@@ -30,62 +22,4 @@ export default class ScopesScopeAuthenticateMethodRoute extends Route {
|
||||
const adapterOptions = { scopeID: this.modelFor('scopes.scope').id };
|
||||
return this.store.peekRecord('auth-method', id, adapterOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async startOIDCAuthentication(authenticatorName, options) {
|
||||
const oidc = getOwner(this).lookup(authenticatorName);
|
||||
// TODO: delegate this call from the session service so that we don't have
|
||||
// to look up the authenticator directly
|
||||
const json = await oidc.startAuthentication(options);
|
||||
await this.openExternalOIDCFlow(json.attributes.auth_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the specified URL in a new tab or window. By default this uses
|
||||
* `window.open`, but may be overriden.
|
||||
* @param {string} url
|
||||
*/
|
||||
async openExternalOIDCFlow(url) {
|
||||
await this.ipc.invoke('openExternal', url);
|
||||
}
|
||||
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Delegates authentication to an authenticator of type matching the current
|
||||
* auth method. If authentication fails, notifies with an alert.
|
||||
*/
|
||||
@action
|
||||
@loading
|
||||
@notifyError(() => 'errors.authentication-failed.title', {
|
||||
sticky: false,
|
||||
catch: true,
|
||||
})
|
||||
async authenticate(creds) {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const authMethod = this.modelFor('scopes.scope.authenticate.method');
|
||||
const authenticatorName = `authenticator:${authMethod.type}`;
|
||||
const requestCookies = false;
|
||||
switch (authMethod.type) {
|
||||
case 'password':
|
||||
case 'ldap':
|
||||
await this.session.authenticate(
|
||||
authenticatorName,
|
||||
creds,
|
||||
requestCookies,
|
||||
{ scope, authMethod },
|
||||
);
|
||||
this.router.transitionTo('index');
|
||||
break;
|
||||
case 'oidc':
|
||||
await this.startOIDCAuthentication(authenticatorName, {
|
||||
scope,
|
||||
authMethod,
|
||||
});
|
||||
this.router.transitionTo('scopes.scope.authenticate.method.oidc');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,21 +26,21 @@
|
||||
@style='warning'
|
||||
class='button-window-close'
|
||||
title={{t 'actions.close'}}
|
||||
{{on 'click' (route-action 'close')}}
|
||||
{{on 'click' this.close}}
|
||||
/>
|
||||
<Rose::Button
|
||||
@iconOnly='flight-icons/svg/square-16'
|
||||
@style='secondary'
|
||||
class='button-window-fullscreen'
|
||||
title={{t 'actions.fullscreen'}}
|
||||
{{on 'click' (route-action 'toggleFullScreen')}}
|
||||
{{on 'click' this.toggleFullScreen}}
|
||||
/>
|
||||
<Rose::Button
|
||||
@iconOnly='flight-icons/svg/minus-16'
|
||||
@style='secondary'
|
||||
class='button-window-minimize'
|
||||
title={{t 'actions.minimize'}}
|
||||
{{on 'click' (route-action 'minimize')}}
|
||||
{{on 'click' this.minimize}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
@icon='flight-icons/svg/user-circle-16'
|
||||
as |dropdown|
|
||||
>
|
||||
<dropdown.button {{on 'click' (route-action 'invalidateSession')}}>
|
||||
<dropdown.button {{on 'click' this.invalidateSession}}>
|
||||
{{t 'actions.deauthenticate'}}
|
||||
</dropdown.button>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
>
|
||||
<Rose::Form
|
||||
class='full-width'
|
||||
@onSubmit={{route-action 'setClusterUrl' this.clusterUrl}}
|
||||
@onSubmit={{fn this.setClusterUrl this.clusterUrl}}
|
||||
@cancel={{false}}
|
||||
@disabled={{(is-loading)}}
|
||||
as |form|
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</Rose::Layout::Centered>
|
||||
|
||||
<Rose::Layout::Centered>
|
||||
<Rose::Button @style='primary' {{on 'click' (route-action 'disconnect')}}>
|
||||
<Rose::Button @style='primary' {{on 'click' this.appUtilities.disconnect}}>
|
||||
{{t 'actions.disconnect'}}
|
||||
</Rose::Button>
|
||||
</Rose::Layout::Centered>
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
<Form::Authenticate
|
||||
@model={{@model}}
|
||||
@submit={{route-action 'authenticate'}}
|
||||
@submit={{fn this.authenticate @model}}
|
||||
@disabled={{(is-loading)}}
|
||||
/>
|
||||
@@ -21,7 +21,7 @@
|
||||
</Rose::Layout::Centered>
|
||||
|
||||
<Rose::Layout::Centered>
|
||||
<Rose::Button @style='primary' {{on 'click' (route-action 'disconnect')}}>
|
||||
<Rose::Button @style='primary' {{on 'click' this.appUtilities.disconnect}}>
|
||||
{{t 'actions.disconnect'}}
|
||||
</Rose::Button>
|
||||
</Rose::Layout::Centered>
|
||||
|
||||
@@ -21,7 +21,9 @@ class MockIPC {
|
||||
return this.clusterUrl;
|
||||
}
|
||||
|
||||
resetClusterUrl() {}
|
||||
resetClusterUrl() {
|
||||
this.clusterUrl = null;
|
||||
}
|
||||
hasMacOSChrome() {}
|
||||
showWindowActions() {}
|
||||
addTokenToDaemons() {}
|
||||
@@ -40,7 +42,7 @@ class MockIPC {
|
||||
* to support the IPC mechanism.
|
||||
*
|
||||
* This mock is necessary to guarantee synchronous and deterministic
|
||||
* operation. The window's own API is evented and asychronous, which
|
||||
* operation. The window's own API is evented and asynchronous, which
|
||||
* cannot be relied on for testing purposes.
|
||||
*
|
||||
* @todo refactor mock postMessage and MessageChannel for reusability
|
||||
|
||||
@@ -5,13 +5,57 @@
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import WindowMockIPC from '../../helpers/window-mock-ipc';
|
||||
|
||||
module('Unit | Controller | application', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
let controller;
|
||||
let session;
|
||||
let clusterUrl;
|
||||
let mockIPC;
|
||||
|
||||
const setupMockIpc = (test) => {
|
||||
test.owner.register('service:browser/window', WindowMockIPC);
|
||||
mockIPC = test.owner.lookup('service:browser/window').mockIPC;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
authenticateSession({});
|
||||
controller = this.owner.lookup('controller:application');
|
||||
session = this.owner.lookup('service:session');
|
||||
clusterUrl = this.owner.lookup('service:cluster-url');
|
||||
setupMockIpc(this);
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup('controller:application');
|
||||
assert.ok(controller);
|
||||
assert.ok(controller.minimize);
|
||||
assert.ok(controller.toggleFullScreen);
|
||||
assert.ok(controller.close);
|
||||
});
|
||||
|
||||
test('invalidateSession action de-authenticates a user', async function (assert) {
|
||||
assert.true(session.isAuthenticated);
|
||||
|
||||
await controller.invalidateSession();
|
||||
|
||||
assert.false(session.isAuthenticated);
|
||||
});
|
||||
|
||||
test('disconnect action de-authenticates a user and resets 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(mockIPC.clusterUrl, url);
|
||||
|
||||
await controller.disconnect();
|
||||
|
||||
assert.false(session.isAuthenticated);
|
||||
assert.notOk(clusterUrl.rendererClusterUrl);
|
||||
assert.notOk(mockIPC.clusterUrl);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
import WindowMockIPC from '../../helpers/window-mock-ipc';
|
||||
|
||||
module('Unit | Controller | cluster-url', function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
|
||||
let controller;
|
||||
let clusterUrl;
|
||||
let mockIPC;
|
||||
|
||||
const setupMockIpc = (test) => {
|
||||
test.owner.register('service:browser/window', WindowMockIPC);
|
||||
mockIPC = test.owner.lookup('service:browser/window').mockIPC;
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
authenticateSession({});
|
||||
controller = this.owner.lookup('controller:cluster-url');
|
||||
clusterUrl = this.owner.lookup('service:cluster-url');
|
||||
setupMockIpc(this);
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
assert.ok(controller);
|
||||
});
|
||||
|
||||
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(mockIPC.clusterUrl, newClusterUrl);
|
||||
|
||||
await controller.setClusterUrl(newClusterUrl);
|
||||
|
||||
assert.strictEqual(clusterUrl.rendererClusterUrl, newClusterUrl);
|
||||
assert.strictEqual(mockIPC.clusterUrl, newClusterUrl);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Controller | error', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup('controller:error');
|
||||
assert.ok(controller);
|
||||
assert.ok(controller.appUtilities);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
|
||||
import { authenticateSession } from 'ember-simple-auth/test-support';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
import { TYPE_AUTH_METHOD_PASSWORD } from 'api/models/auth-method';
|
||||
|
||||
module(
|
||||
'Unit | Controller | scopes/scope/authenticate/method/index',
|
||||
function (hooks) {
|
||||
setupTest(hooks);
|
||||
setupMirage(hooks);
|
||||
setupIntl(hooks, 'en-us');
|
||||
|
||||
let controller;
|
||||
let store;
|
||||
let session;
|
||||
|
||||
const instances = {
|
||||
scopes: {
|
||||
global: null,
|
||||
},
|
||||
authMethod: null,
|
||||
};
|
||||
|
||||
hooks.beforeEach(async function () {
|
||||
authenticateSession({});
|
||||
controller = this.owner.lookup(
|
||||
'controller:scopes/scope/authenticate/method/index',
|
||||
);
|
||||
store = this.owner.lookup('service:store');
|
||||
session = this.owner.lookup('service:session');
|
||||
|
||||
instances.scopes.global = this.server.create('scope', {
|
||||
id: 'global',
|
||||
type: 'global',
|
||||
});
|
||||
instances.authMethod = this.server.create('auth-method', {
|
||||
scope: instances.scopes.global,
|
||||
type: TYPE_AUTH_METHOD_PASSWORD,
|
||||
});
|
||||
});
|
||||
|
||||
test('it exists', function (assert) {
|
||||
assert.ok(controller);
|
||||
});
|
||||
|
||||
test('authenticate action saves login information', async function (assert) {
|
||||
const identification = 'admin123';
|
||||
const authMethod = await store.findRecord(
|
||||
'auth-method',
|
||||
instances.authMethod.id,
|
||||
);
|
||||
const { authenticator: authBefore, username: usernameBefore } =
|
||||
session.data.authenticated;
|
||||
|
||||
assert.notOk(usernameBefore);
|
||||
assert.strictEqual(authBefore, 'authenticator:test');
|
||||
|
||||
await controller.authenticate(authMethod, {
|
||||
identification,
|
||||
password: 'password',
|
||||
});
|
||||
const { authenticator: authAfter, username: usernameAfter } =
|
||||
session.data.authenticated;
|
||||
|
||||
assert.strictEqual(
|
||||
authAfter,
|
||||
`authenticator:${instances.authMethod.type}`,
|
||||
);
|
||||
assert.strictEqual(usernameAfter, identification);
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -11,7 +11,6 @@ module(
|
||||
function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup(
|
||||
'controller:scopes/scope/authenticate/method/oidc',
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'desktop/tests/helpers';
|
||||
|
||||
module('Unit | Controller | scopes/scope/projects/error', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup(
|
||||
'controller:scopes/scope/projects/error',
|
||||
);
|
||||
assert.ok(controller);
|
||||
assert.ok(controller.appUtilities);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user