2017-10-14 18:53:48 +00:00
|
|
|
import { find, findAll, fillIn, click, visit } from 'ember-native-dom-helpers';
|
|
|
|
import Ember from 'ember';
|
2017-09-19 14:47:10 +00:00
|
|
|
import { test } from 'qunit';
|
|
|
|
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
|
|
|
|
|
2017-10-14 18:53:48 +00:00
|
|
|
const { $ } = Ember;
|
|
|
|
|
2017-09-19 14:47:10 +00:00
|
|
|
let job;
|
|
|
|
let node;
|
2017-10-14 18:53:48 +00:00
|
|
|
let managementToken;
|
|
|
|
let clientToken;
|
2017-09-19 14:47:10 +00:00
|
|
|
|
|
|
|
moduleForAcceptance('Acceptance | tokens', {
|
|
|
|
beforeEach() {
|
|
|
|
server.create('agent');
|
|
|
|
node = server.create('node');
|
|
|
|
job = server.create('job');
|
2017-10-14 18:53:48 +00:00
|
|
|
managementToken = server.create('token');
|
|
|
|
clientToken = server.create('token');
|
2017-09-19 14:47:10 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
test('the token form sets the token in session storage', function(assert) {
|
2017-10-14 19:42:14 +00:00
|
|
|
const { secretId } = managementToken;
|
2017-09-19 14:47:10 +00:00
|
|
|
|
|
|
|
visit('/settings/tokens');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(window.sessionStorage.nomadTokenSecret == null, 'No token secret set');
|
|
|
|
|
2017-10-14 18:53:48 +00:00
|
|
|
fillIn('.token-secret', secretId);
|
|
|
|
click('.token-submit');
|
2017-09-19 14:47:10 +00:00
|
|
|
|
|
|
|
andThen(() => {
|
2017-10-14 18:53:48 +00:00
|
|
|
assert.equal(window.sessionStorage.nomadTokenSecret, secretId, 'Token secret was set');
|
2017-09-19 14:47:10 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('the X-Nomad-Token header gets sent with requests once it is set', function(assert) {
|
2017-10-14 19:42:14 +00:00
|
|
|
const { secretId } = managementToken;
|
2017-09-19 14:47:10 +00:00
|
|
|
let requestPosition = 0;
|
|
|
|
|
|
|
|
visit(`/jobs/${job.id}`);
|
|
|
|
visit(`/nodes/${node.id}`);
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(server.pretender.handledRequests.length > 1, 'Requests have been made');
|
|
|
|
|
|
|
|
server.pretender.handledRequests.forEach(req => {
|
2017-10-19 02:04:19 +00:00
|
|
|
assert.notOk(getHeader(req, 'X-Nomad-Token'), `No token for ${req.url}`);
|
2017-09-19 14:47:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
requestPosition = server.pretender.handledRequests.length;
|
|
|
|
});
|
|
|
|
|
|
|
|
visit('/settings/tokens');
|
2017-09-26 07:47:16 +00:00
|
|
|
andThen(() => {
|
2017-10-14 18:53:48 +00:00
|
|
|
fillIn('.token-secret', secretId);
|
|
|
|
click('.token-submit');
|
2017-09-26 07:47:16 +00:00
|
|
|
});
|
2017-09-19 14:47:10 +00:00
|
|
|
|
|
|
|
visit(`/jobs/${job.id}`);
|
|
|
|
visit(`/nodes/${node.id}`);
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
const newRequests = server.pretender.handledRequests.slice(requestPosition);
|
|
|
|
assert.ok(newRequests.length > 1, 'New requests have been made');
|
|
|
|
|
2017-10-18 23:42:08 +00:00
|
|
|
// Cross-origin requests can't have a token
|
2017-10-19 02:04:19 +00:00
|
|
|
newRequests.forEach(req => {
|
|
|
|
assert.equal(getHeader(req, 'X-Nomad-Token'), secretId, `Token set for ${req.url}`);
|
2017-10-14 18:53:48 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('an error message is shown when authenticating a token fails', function(assert) {
|
2017-10-14 19:42:14 +00:00
|
|
|
const { secretId } = managementToken;
|
2017-10-14 18:53:48 +00:00
|
|
|
const bogusSecret = 'this-is-not-the-secret';
|
|
|
|
assert.notEqual(
|
|
|
|
secretId,
|
|
|
|
bogusSecret,
|
|
|
|
'bogus secret is not somehow coincidentally equal to the real secret'
|
|
|
|
);
|
|
|
|
|
|
|
|
visit('/settings/tokens');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
fillIn('.token-secret', bogusSecret);
|
|
|
|
click('.token-submit');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(
|
|
|
|
window.sessionStorage.nomadTokenSecret == null,
|
|
|
|
'Token secret is discarded on failure'
|
|
|
|
);
|
|
|
|
assert.ok(find('.token-error'), 'Token error message is shown');
|
|
|
|
assert.notOk(find('.token-success'), 'Token success message is not shown');
|
|
|
|
assert.notOk(find('.token-policy'), 'No token policies are shown');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('a success message and a special management token message are shown when authenticating succeeds', function(
|
|
|
|
assert
|
|
|
|
) {
|
2017-10-14 19:42:14 +00:00
|
|
|
const { secretId } = managementToken;
|
2017-10-14 18:53:48 +00:00
|
|
|
|
|
|
|
visit('/settings/tokens');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
fillIn('.token-secret', secretId);
|
|
|
|
click('.token-submit');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(find('.token-success'), 'Token success message is shown');
|
|
|
|
assert.notOk(find('.token-error'), 'Token error message is not shown');
|
|
|
|
assert.ok(find('.token-management-message'), 'Token management message is shown');
|
|
|
|
assert.notOk(find('.token-policy'), 'No token policies are shown');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test('a success message and associated policies are shown when authenticating succeeds', function(
|
|
|
|
assert
|
|
|
|
) {
|
2017-10-14 19:42:14 +00:00
|
|
|
const { secretId } = clientToken;
|
2017-10-14 18:53:48 +00:00
|
|
|
const policy = clientToken.policies.models[0];
|
|
|
|
policy.update('description', 'Make sure there is a description');
|
|
|
|
|
|
|
|
visit('/settings/tokens');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
fillIn('.token-secret', secretId);
|
|
|
|
click('.token-submit');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(find('.token-success'), 'Token success message is shown');
|
|
|
|
assert.notOk(find('.token-error'), 'Token error message is not shown');
|
|
|
|
assert.notOk(find('.token-management-message'), 'Token management message is not shown');
|
|
|
|
assert.equal(
|
|
|
|
findAll('.token-policy').length,
|
|
|
|
clientToken.policies.length,
|
|
|
|
'Each policy associated with the token is listed'
|
|
|
|
);
|
|
|
|
|
|
|
|
const policyElement = $(find('.token-policy'));
|
|
|
|
|
|
|
|
assert.equal(
|
|
|
|
policyElement
|
|
|
|
.find('.boxed-section-head')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
policy.name,
|
|
|
|
'Policy Name'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
policyElement
|
|
|
|
.find('.boxed-section-body p.content')
|
|
|
|
.text()
|
|
|
|
.trim(),
|
|
|
|
policy.description,
|
|
|
|
'Policy Description'
|
|
|
|
);
|
|
|
|
assert.equal(
|
|
|
|
policyElement.find('.boxed-section-body pre code').text(),
|
|
|
|
policy.rules,
|
|
|
|
'Policy Rules'
|
|
|
|
);
|
2017-09-19 14:47:10 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2017-10-18 23:42:08 +00:00
|
|
|
|
|
|
|
test('setting a token clears the store', function(assert) {
|
|
|
|
const { secretId } = clientToken;
|
|
|
|
|
|
|
|
visit('/jobs');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
assert.ok(find('.job-row'), 'Jobs found');
|
|
|
|
});
|
|
|
|
|
|
|
|
visit('/settings/tokens');
|
|
|
|
|
|
|
|
andThen(() => {
|
|
|
|
fillIn('.token-secret', secretId);
|
|
|
|
click('.token-submit');
|
|
|
|
});
|
|
|
|
|
|
|
|
// Don't return jobs from the API the second time around
|
|
|
|
andThen(() => {
|
|
|
|
server.pretender.get('/v1/jobs', function() {
|
|
|
|
return [200, {}, '[]'];
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
visit('/jobs');
|
|
|
|
|
|
|
|
// If jobs are lingering in the store, they would show up
|
|
|
|
assert.notOk(find('.job-row'), 'No jobs found');
|
|
|
|
});
|
2017-10-19 02:04:19 +00:00
|
|
|
|
|
|
|
function getHeader({ requestHeaders }, name) {
|
|
|
|
// Headers are case-insensitive, but object property look up is not
|
|
|
|
return (
|
|
|
|
requestHeaders[name] || requestHeaders[name.toLowerCase()] || requestHeaders[name.toUpperCase()]
|
|
|
|
);
|
|
|
|
}
|