зеркало из https://github.com/mozilla/fxa.git
bug(auth): Fix test timeouts
Becuase: - After upgrading sentry we were seeing test timeouts - There were some kinda weird patterns in place for these tests anyways - Test server wasn't getting cleaned up - Test server start up is taking longer (presumably because of sentry upgrade?) This Commit: - Moves before an after blocks next to each other so setup and tear down are easy to follow - Makes sure test server start / stop is done in before each blocks - Increase test timeouts to 60s when test server is used - Switches to async/await for before and after blocks, which feels less error prone
This commit is contained in:
Родитель
83dc649b52
Коммит
03940753cd
|
@ -288,15 +288,39 @@ async function run(config) {
|
|||
log: log,
|
||||
async close() {
|
||||
log.info('shutdown');
|
||||
await server.stop();
|
||||
statsd.close();
|
||||
|
||||
try {
|
||||
await server.stop();
|
||||
} catch (e) {
|
||||
log.warn('shutdown', {
|
||||
message: 'Server did not shut down cleanly. ' + e.message,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
statsd.close();
|
||||
} catch (e) {
|
||||
log.warn('shutdown', {
|
||||
message: 'Statsd did not shut down cleanly. ' + e.message,
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
senders.email.stop();
|
||||
} catch (e) {
|
||||
// XXX: simplesmtp module may quit early and set socket to `false`, stopping it may fail
|
||||
log.warn('shutdown', { message: 'Mailer client already disconnected' });
|
||||
log.warn('shutdown', {
|
||||
message: 'senders.email did not shut down cleanly. ' + e.message
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await database.close();
|
||||
} catch (e) {
|
||||
log.warn('shutdown', {
|
||||
message: 'Database connection did not shutdown cleanly. ' + e.message,
|
||||
});
|
||||
}
|
||||
await database.close();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ TestServer.start(config, false).then((server) => {
|
|||
{ stdio: 'inherit' }
|
||||
);
|
||||
|
||||
cp.on('close', (code) => {
|
||||
server.stop();
|
||||
cp.on('close', async (code) => {
|
||||
await server.stop();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -95,26 +95,23 @@ module.exports = (config) => {
|
|||
this.unwrapBKeyVersion2 = unwrapBKeyVersion2;
|
||||
};
|
||||
|
||||
Client.create = function (origin, email, password, options = {}) {
|
||||
Client.create = async function (origin, email, password, options = {}) {
|
||||
const c = new Client(origin, options);
|
||||
|
||||
if (options.version === 'V2') {
|
||||
return (async function () {
|
||||
await c.setupCredentials(email, password);
|
||||
await c.setupCredentialsV2(email, password);
|
||||
await c.setupCredentials(email, password);
|
||||
await c.setupCredentialsV2(email, password);
|
||||
|
||||
c.generateNewWrapKb();
|
||||
c.deriveWrapKbVersion2FromKb();
|
||||
c.generateNewWrapKb();
|
||||
c.deriveWrapKbVersion2FromKb();
|
||||
|
||||
await c.createV2();
|
||||
|
||||
return c;
|
||||
})();
|
||||
const result = await c.createV2();
|
||||
return result;
|
||||
} else {
|
||||
await c.setupCredentials(email, password);
|
||||
const result = await c.create(options);
|
||||
return result;
|
||||
}
|
||||
|
||||
return c.setupCredentials(email, password).then(() => {
|
||||
return c.create(options);
|
||||
});
|
||||
};
|
||||
|
||||
Client.login = function (origin, email, password, options) {
|
||||
|
|
|
@ -16,8 +16,6 @@ const sinon = require('sinon');
|
|||
const db = require('../../lib/oauth/db');
|
||||
const encrypt = require('fxa-shared/auth/encrypt');
|
||||
const config = testServer.config;
|
||||
let Server;
|
||||
let Server2;
|
||||
|
||||
const unique = require('../../lib/oauth/unique');
|
||||
const util = require('../../lib/oauth/util');
|
||||
|
@ -128,35 +126,6 @@ function authParams(params, options) {
|
|||
return defaults;
|
||||
}
|
||||
|
||||
function newToken(payload = {}, options = {}) {
|
||||
var ttl = payload.ttl || MAX_TTL_S;
|
||||
delete payload.ttl;
|
||||
mockAssertion().reply(200, options.verifierResponse || VERIFY_GOOD);
|
||||
return Server.api
|
||||
.post({
|
||||
url: '/authorization',
|
||||
payload: authParams(payload, options),
|
||||
})
|
||||
.then(function (res) {
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
return Server.api.post({
|
||||
url: '/token',
|
||||
payload: {
|
||||
client_id: options.clientId || clientId,
|
||||
client_secret: options.codeVerifier
|
||||
? undefined
|
||||
: options.secret || secret,
|
||||
code: res.result.code,
|
||||
code_verifier: options.codeVerifier,
|
||||
ppid_seed: options.ppidSeed,
|
||||
resource: options.resource,
|
||||
ttl: ttl,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function assertInvalidRequestParam(result, param) {
|
||||
assert.equal(result.code, 400);
|
||||
assert.equal(result.errno, 109);
|
||||
|
@ -187,36 +156,65 @@ function basicAuthHeader(clientId, secret) {
|
|||
}
|
||||
|
||||
describe('#integration - /v1', function () {
|
||||
this.timeout(60000);
|
||||
const VERIFY_FAILURE = '{"status": "failure"}';
|
||||
let sandbox;
|
||||
let Server;
|
||||
|
||||
function newToken(payload = {}, options = {}) {
|
||||
var ttl = payload.ttl || MAX_TTL_S;
|
||||
delete payload.ttl;
|
||||
mockAssertion().reply(200, options.verifierResponse || VERIFY_GOOD);
|
||||
return Server.api
|
||||
.post({
|
||||
url: '/authorization',
|
||||
payload: authParams(payload, options),
|
||||
})
|
||||
.then(function (res) {
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
return Server.api.post({
|
||||
url: '/token',
|
||||
payload: {
|
||||
client_id: options.clientId || clientId,
|
||||
client_secret: options.codeVerifier
|
||||
? undefined
|
||||
: options.secret || secret,
|
||||
code: res.result.code,
|
||||
code_verifier: options.codeVerifier,
|
||||
ppid_seed: options.ppidSeed,
|
||||
resource: options.resource,
|
||||
ttl: ttl,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000);
|
||||
const start = Date.now();
|
||||
console.log('!!! 1', Date.now() - start);
|
||||
Server = await testServer.start();
|
||||
return Promise.all([
|
||||
genAssertion(USERID + config.get('oauthServer.browserid.issuer')).then(
|
||||
function (ass) {
|
||||
AN_ASSERTION = ass;
|
||||
}
|
||||
),
|
||||
db.ping().then(function () {
|
||||
client = clientByName('Mocha');
|
||||
clientId = client.id;
|
||||
assert.equal(encrypt.hash(secret).toString('hex'), client.hashedSecret);
|
||||
assert.equal(
|
||||
encrypt.hash(secretPrevious).toString('hex'),
|
||||
client.hashedSecretPrevious
|
||||
);
|
||||
badSecret = Buffer.from(secret, 'hex').slice();
|
||||
badSecret[badSecret.length - 1] ^= 1;
|
||||
badSecret = badSecret.toString('hex');
|
||||
}),
|
||||
]);
|
||||
console.log('!!! 2', Date.now() - start);
|
||||
AN_ASSERTION = await genAssertion(
|
||||
USERID + config.get('oauthServer.browserid.issuer')
|
||||
);
|
||||
await db.ping();
|
||||
console.log('!!! 3', Date.now() - start);
|
||||
client = clientByName('Mocha');
|
||||
clientId = client.id;
|
||||
assert.equal(encrypt.hash(secret).toString('hex'), client.hashedSecret);
|
||||
assert.equal(
|
||||
encrypt.hash(secretPrevious).toString('hex'),
|
||||
client.hashedSecretPrevious
|
||||
);
|
||||
badSecret = Buffer.from(secret, 'hex').slice();
|
||||
badSecret[badSecret.length - 1] ^= 1;
|
||||
badSecret = badSecret.toString('hex');
|
||||
console.log('!!! 4', Date.now() - start);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await Server?.close();
|
||||
await Server2?.close();
|
||||
await Server.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -2860,37 +2858,57 @@ describe('#integration - /v1', function () {
|
|||
assert.equal(res.result.errno, 115);
|
||||
});
|
||||
|
||||
it('should not reject expired tokens from pocket clients', async function () {
|
||||
describe('expired tokens from pocket clients', () => {
|
||||
const clientId = '749818d3f2e7857f';
|
||||
config.set('oauthServer.expiration.accessTokenExpiryEpoch', undefined);
|
||||
Server2 = await testServer.start();
|
||||
let res = await newToken(
|
||||
{
|
||||
ttl: 1,
|
||||
},
|
||||
{
|
||||
clientId,
|
||||
}
|
||||
);
|
||||
let accessTokenExpiryEpoch;
|
||||
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
assert.equal(res.result.expires_in, 1);
|
||||
|
||||
sandbox.useFakeTimers({
|
||||
now: Date.now() + 1000 * 60 * 60, // 1 hr in future
|
||||
shouldAdvanceTime: true,
|
||||
before(async () => {
|
||||
await Server.close();
|
||||
accessTokenExpiryEpoch = config.get(
|
||||
'oauthServer.expiration.accessTokenExpiryEpoch'
|
||||
);
|
||||
config.set('oauthServer.expiration.accessTokenExpiryEpoch', undefined);
|
||||
Server = await testServer.start();
|
||||
});
|
||||
|
||||
res = await Server2.api.post({
|
||||
url: '/verify',
|
||||
payload: {
|
||||
token: res.result.access_token,
|
||||
},
|
||||
after(async () => {
|
||||
await Server.close();
|
||||
config.set(
|
||||
'oauthServer.expiration.accessTokenExpiryEpoch',
|
||||
accessTokenExpiryEpoch
|
||||
);
|
||||
Server = await testServer.start();
|
||||
});
|
||||
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
it('should not reject expired tokens from pocket clients', async function () {
|
||||
let res = await newToken(
|
||||
{
|
||||
ttl: 1,
|
||||
},
|
||||
{
|
||||
clientId,
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
assert.equal(res.result.expires_in, 1);
|
||||
|
||||
sandbox.useFakeTimers({
|
||||
now: Date.now() + 1000 * 60 * 60, // 1 hr in future
|
||||
shouldAdvanceTime: true,
|
||||
});
|
||||
|
||||
res = await Server.api.post({
|
||||
url: '/verify',
|
||||
payload: {
|
||||
token: res.result.access_token,
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(res.statusCode, 200);
|
||||
assertSecurityHeaders(res);
|
||||
});
|
||||
});
|
||||
|
||||
describe('response', function () {
|
||||
|
|
|
@ -11,11 +11,10 @@ const crypto = require('crypto');
|
|||
const rimraf = require('rimraf');
|
||||
|
||||
describe('#integration - the signing-key management scripts', function () {
|
||||
this.timeout(60000);
|
||||
let runScript;
|
||||
let workDir, keyFile, newKeyFile, oldKeyFile;
|
||||
|
||||
this.timeout(30000);
|
||||
|
||||
beforeEach(() => {
|
||||
const uniqName = crypto.randomBytes(8).toString('hex');
|
||||
workDir = path.join(os.tmpdir(), `fxa-oauth-server-tests-${uniqName}`);
|
||||
|
|
|
@ -21,9 +21,10 @@ const {
|
|||
// Note, intentionally not indenting for code review.
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote account create`, function () {
|
||||
this.timeout(50000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(async () => {
|
||||
|
||||
before(async function () {
|
||||
config.subscriptions = {
|
||||
enabled: true,
|
||||
stripeApiKey: 'fake_key',
|
||||
|
@ -54,6 +55,10 @@ const {
|
|||
return server;
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('unverified account fail when getting keys', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'allyourbasearebelongtous';
|
||||
|
@ -989,9 +994,7 @@ const {
|
|||
assert.equal(kB2, originalKb);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
|
||||
async function login(email, password, version = '') {
|
||||
return await Client.login(config.publicUrl, email, password, {
|
||||
|
|
|
@ -15,13 +15,16 @@ const otplib = require('otplib');
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote account create with sign-up code`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
const password = '4L6prUdlLNfxGIoj';
|
||||
let server, client, email, emailStatus, emailData;
|
||||
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
return server;
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('create and verify sync account', async () => {
|
||||
|
@ -231,9 +234,7 @@ describe(`#integration${testOptions.version} - remote account create with sign-u
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -13,13 +13,15 @@ const config = require('../../config').default.getProperties();
|
|||
// Note, intentionally not indenting for code review.
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote account destroy`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async function () {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('account destroy', () => {
|
||||
|
@ -115,8 +117,6 @@ const config = require('../../config').default.getProperties();
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ const key = {
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote account locale`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
|
||||
before(async () => {
|
||||
|
|
|
@ -17,13 +17,15 @@ const config = require('../../config').default.getProperties();
|
|||
describe(`#integration${testOptions.version} - remote account login`, () => {
|
||||
let server;
|
||||
|
||||
before(function () {
|
||||
this.timeout(15000);
|
||||
before(async function () {
|
||||
this.timeout(60000);
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('the email is returned in the error on Incorrect password errors', () => {
|
||||
|
@ -37,7 +39,12 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
testOptions
|
||||
)
|
||||
.then(() => {
|
||||
return Client.login(config.publicUrl, email, `${password}x`, testOptions);
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
`${password}x`,
|
||||
testOptions
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => assert(false),
|
||||
|
@ -50,8 +57,7 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
});
|
||||
|
||||
it('the email is returned in the error on Incorrect email case errors with correct password', () => {
|
||||
|
||||
if (testOptions.version === "V2") {
|
||||
if (testOptions.version === 'V2') {
|
||||
// Important!!! This test is no longer applicable for V2 passwords.
|
||||
// V1 passwords are encoded with a salt that includes the users
|
||||
// email address. As a result, if the user enters a their email
|
||||
|
@ -72,7 +78,12 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
testOptions
|
||||
)
|
||||
.then(() => {
|
||||
return Client.login(config.publicUrl, loginEmail, password, testOptions);
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
loginEmail,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => assert(false),
|
||||
|
@ -110,7 +121,10 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
return Client.login(config.publicUrl, email, password, { ...testOptions, keys: false });
|
||||
return Client.login(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
keys: false,
|
||||
});
|
||||
})
|
||||
.then((c) => {
|
||||
assert.equal(c.keyFetchToken, null, 'should not have keyFetchToken');
|
||||
|
@ -199,7 +213,7 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
)
|
||||
.then(() => {
|
||||
return Client.login(config.publicUrl, email, 'foo', {
|
||||
... testOptions,
|
||||
...testOptions,
|
||||
metricsContext: {
|
||||
flowId:
|
||||
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
|
@ -329,7 +343,7 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true
|
||||
keys: true,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
|
@ -386,8 +400,6 @@ describe(`#integration${testOptions.version} - remote account login`, () => {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ const CLIENT_ID = config.oauthServer.clients.find(
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - fetch user profile data`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
|
||||
let server, client, email, password;
|
||||
before(async () => {
|
||||
|
|
|
@ -14,13 +14,16 @@ const config = require('../../config').default.getProperties();
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote account reset`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
|
||||
before(async function () {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('account reset w/o sessionToken', async () => {
|
||||
|
@ -255,10 +258,6 @@ const config = require('../../config').default.getProperties();
|
|||
assert.ok(cert1['fxa-keysChangedAt'] < cert2['fxa-keysChangedAt']);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
async function resetPassword(client, code, newPassword, options) {
|
||||
await client.verifyPasswordResetCode(code);
|
||||
return await client.resetPassword(newPassword, {}, options);
|
||||
|
|
|
@ -24,14 +24,17 @@ const mocks = require('../mocks');
|
|||
// Note, intentionally not indenting for code review.
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote account signin verification`, function () {
|
||||
this.timeout(30000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
|
||||
before(async () => {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('account signin without keys does not set challenge', () => {
|
||||
|
@ -810,8 +813,6 @@ const mocks = require('../mocks');
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,16 +14,23 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote account status`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('account status with existing account', () => {
|
||||
return Client.create(config.publicUrl, server.uniqueEmail(), 'password', testOptions)
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
server.uniqueEmail(),
|
||||
'password',
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
return c.api.accountStatus(c.uid);
|
||||
})
|
||||
|
@ -139,9 +146,7 @@ describe(`#integration${testOptions.version} - remote account status`, function
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -14,16 +14,23 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote account unlock`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('/account/lock is no longer supported', () => {
|
||||
return Client.create(config.publicUrl, server.uniqueEmail(), 'password', testOptions)
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
server.uniqueEmail(),
|
||||
'password',
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
return c.lockAccount();
|
||||
})
|
||||
|
@ -38,7 +45,12 @@ describe(`#integration${testOptions.version} - remote account unlock`, function
|
|||
});
|
||||
|
||||
it('/account/unlock/resend_code is no longer supported', () => {
|
||||
return Client.create(config.publicUrl, server.uniqueEmail(), 'password', testOptions)
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
server.uniqueEmail(),
|
||||
'password',
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
return c.resendAccountUnlockCode('en');
|
||||
})
|
||||
|
@ -53,7 +65,12 @@ describe(`#integration${testOptions.version} - remote account unlock`, function
|
|||
});
|
||||
|
||||
it('/account/unlock/verify_code is no longer supported', () => {
|
||||
return Client.create(config.publicUrl, server.uniqueEmail(), 'password', testOptions)
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
server.uniqueEmail(),
|
||||
'password',
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
return c.verifyAccountUnlockCode('bigscaryuid', 'bigscarycode');
|
||||
})
|
||||
|
@ -67,9 +84,7 @@ describe(`#integration${testOptions.version} - remote account unlock`, function
|
|||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ const PUBLIC_CLIENT_ID = '3c49430b43dfba77';
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - attached clients listing`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server, oauthServerDb;
|
||||
before(async () => {
|
||||
config.lastAccessTimeUpdates = {
|
||||
|
@ -34,6 +34,11 @@ describe(`#integration${testOptions.version} - attached clients listing`, functi
|
|||
oauthServerDb = require('../../lib/oauth/db');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
testUtils.restoreStdoutWrite();
|
||||
});
|
||||
|
||||
it('correctly lists a variety of attached clients', async () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'test password';
|
||||
|
@ -119,7 +124,12 @@ describe(`#integration${testOptions.version} - attached clients listing`, functi
|
|||
await tokens.SessionToken.fromHex(client.sessionToken)
|
||||
).id;
|
||||
|
||||
const client2 = await Client.login(config.publicUrl, email, password, testOptions);
|
||||
const client2 = await Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
const device = await client2.updateDevice({
|
||||
name: 'test',
|
||||
type: 'desktop',
|
||||
|
@ -151,7 +161,12 @@ describe(`#integration${testOptions.version} - attached clients listing`, functi
|
|||
await tokens.SessionToken.fromHex(client.sessionToken)
|
||||
).id;
|
||||
|
||||
const client2 = await Client.login(config.publicUrl, email, password, testOptions);
|
||||
const client2 = await Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
const otherSessionTokenId = (
|
||||
await tokens.SessionToken.fromHex(client2.sessionToken)
|
||||
).id;
|
||||
|
@ -207,10 +222,7 @@ describe(`#integration${testOptions.version} - attached clients listing`, functi
|
|||
assert.equal(allClients[0].refreshTokenId, null);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
testUtils.restoreStdoutWrite();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -13,15 +13,17 @@ const superagent = require('superagent');
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote base path`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server, config;
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config = require('../../config').default.getProperties();
|
||||
config.publicUrl = 'http://localhost:9000/auth';
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
function testVersionRoute(path) {
|
||||
|
@ -76,9 +78,7 @@ describe(`#integration${testOptions.version} - remote base path`, function () {
|
|||
testVersionRoute('/__version__')
|
||||
);
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -21,12 +21,14 @@ const publicKey = {
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote certificate sign`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('certificate sign', () => {
|
||||
|
@ -316,8 +318,6 @@ const publicKey = {
|
|||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,13 +13,16 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote concurrent`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
|
||||
before(async () => {
|
||||
config.verifierVersion = 1;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('concurrent create requests', () => {
|
||||
|
@ -38,9 +41,7 @@ describe(`#integration${testOptions.version} - remote concurrent`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -15,6 +15,7 @@ const UnblockCode = require('../../lib/crypto/random').base32(
|
|||
);
|
||||
const uuid = require('uuid');
|
||||
const { normalizeEmail } = require('fxa-shared').email.helpers;
|
||||
const ioredis = require('ioredis');
|
||||
|
||||
const log = { debug() {}, trace() {}, info() {}, error() {} };
|
||||
|
||||
|
@ -70,26 +71,24 @@ const zeroBuffer32 = Buffer.from(
|
|||
let account, secondEmail;
|
||||
|
||||
describe(`#integration - remote db`, function () {
|
||||
this.timeout(20000);
|
||||
this.timeout(60000);
|
||||
let dbServer, db, redis;
|
||||
|
||||
before(() => {
|
||||
redis = require('ioredis').createClient({
|
||||
before(async () => {
|
||||
redis = ioredis.createClient({
|
||||
host: config.redis.host,
|
||||
port: config.redis.port,
|
||||
password: config.redis.password,
|
||||
prefix: config.redis.sessionTokens.prefix,
|
||||
enable_offline_queue: false,
|
||||
});
|
||||
dbServer = await TestServer.start(config);
|
||||
db = await DB.connect(config);
|
||||
});
|
||||
|
||||
return TestServer.start(config)
|
||||
.then((s) => {
|
||||
dbServer = s;
|
||||
return DB.connect(config);
|
||||
})
|
||||
.then((x) => {
|
||||
db = x;
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(dbServer);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -1613,10 +1612,4 @@ describe(`#integration - remote db`, function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(dbServer).then(() => {
|
||||
return db && db.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -35,7 +35,7 @@ const UNKNOWN_REFRESH_TOKEN =
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote device with refresh tokens`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let client;
|
||||
let db;
|
||||
let email;
|
||||
|
@ -44,20 +44,14 @@ describe(`#integration${testOptions.version} - remote device with refresh tokens
|
|||
let refreshToken;
|
||||
let server;
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config.lastAccessTimeUpdates = lastAccessTimeUpdates;
|
||||
const DB = require('../../lib/db')(config, log, Token);
|
||||
|
||||
testUtils.disableLogs();
|
||||
return TestServer.start(config, false)
|
||||
.then((s) => {
|
||||
server = s;
|
||||
return DB.connect(config);
|
||||
})
|
||||
.then((x) => {
|
||||
db = x;
|
||||
oauthServerDb = require('../../lib/oauth/db');
|
||||
});
|
||||
server = await TestServer.start(config, false);
|
||||
db = await DB.connect(config);
|
||||
oauthServerDb = require('../../lib/oauth/db');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
|
|
|
@ -13,12 +13,14 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote email validity`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('/account/create with a variety of malformed email addresses', () => {
|
||||
|
@ -77,9 +79,7 @@ describe(`#integration${testOptions.version} - remote email validity`, function
|
|||
return Promise.all(emails);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -15,15 +15,17 @@ const pubSigKey = JWTool.JWK.fromFile(config.publicKeyFile);
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote flow`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
let email1;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
email1 = server.uniqueEmail();
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
email1 = server.uniqueEmail();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('Create account flow', () => {
|
||||
|
@ -112,8 +114,6 @@ const pubSigKey = JWTool.JWK.fromFile(config.publicKeyFile);
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,12 +14,13 @@ const config = require('../../config').default.getProperties();
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote misc`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
function testVersionRoute(route) {
|
||||
|
@ -286,8 +287,6 @@ const config = require('../../config').default.getProperties();
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,7 +23,7 @@ const MOCK_CODE_CHALLENGE = 'YPhkZqm08uTfwjNSiYcx80-NPT9Zn94kHboQW97KyV0';
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - /oauth/ session token scope`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let client;
|
||||
let email;
|
||||
let password;
|
||||
|
|
|
@ -25,7 +25,7 @@ const { decodeJWT } = testUtils;
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - /oauth/ routes`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let client;
|
||||
let email;
|
||||
let password;
|
||||
|
|
|
@ -20,15 +20,17 @@ function getSessionTokenId(sessionTokenHex) {
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote password change`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('password change, with unverified session', () => {
|
||||
|
@ -544,8 +546,6 @@ function getSessionTokenId(sessionTokenHex) {
|
|||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,450 +2,449 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
const chai = require('chai');
|
||||
const chaiAsPromised = require('chai-as-promised');
|
||||
const url = require('url');
|
||||
const Client = require('../client')();
|
||||
const TestServer = require('../test_server');
|
||||
const crypto = require('crypto');
|
||||
const base64url = require('base64url');
|
||||
const chai = require('chai');
|
||||
const chaiAsPromised = require('chai-as-promised');
|
||||
const url = require('url');
|
||||
const Client = require('../client')();
|
||||
const TestServer = require('../test_server');
|
||||
const crypto = require('crypto');
|
||||
const base64url = require('base64url');
|
||||
|
||||
const config = require('../../config').default.getProperties();
|
||||
const mocks = require('../mocks');
|
||||
const config = require('../../config').default.getProperties();
|
||||
const mocks = require('../mocks');
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
const { assert } = chai;
|
||||
chai.use(chaiAsPromised);
|
||||
const { assert } = chai;
|
||||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote password forgot`, function () {
|
||||
this.timeout(15000);
|
||||
let server;
|
||||
before(() => {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote password forgot`, function () {
|
||||
this.timeout(15000);
|
||||
let server;
|
||||
before(async () => {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
server = await TestServer.start(config)
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('forgot password', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'allyourbasearebelongtous';
|
||||
const newPassword = 'ez';
|
||||
let wrapKb = null;
|
||||
let kA = null;
|
||||
let client = null;
|
||||
const options = {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
metricsContext: mocks.generateMetricsContext(),
|
||||
};
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
options
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.keys();
|
||||
})
|
||||
.then((keys) => {
|
||||
wrapKb = keys.wrapKb;
|
||||
kA = keys.kA;
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-begin-time'],
|
||||
options.metricsContext.flowBeginTime,
|
||||
'flow begin time set'
|
||||
);
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-id'],
|
||||
options.metricsContext.flowId,
|
||||
'flow id set'
|
||||
);
|
||||
assert.equal(emailData.headers['x-template-name'], 'recovery');
|
||||
return emailData.headers['x-recovery-code'];
|
||||
})
|
||||
.then((code) => {
|
||||
assert.isRejected(client.resetPassword(newPassword));
|
||||
return resetPassword(client, code, newPassword, undefined, options);
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.ok(query.email, 'email is in the link');
|
||||
it('forgot password', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'allyourbasearebelongtous';
|
||||
const newPassword = 'ez';
|
||||
let wrapKb = null;
|
||||
let kA = null;
|
||||
let client = null;
|
||||
const options = {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
metricsContext: mocks.generateMetricsContext(),
|
||||
};
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
options
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.keys();
|
||||
})
|
||||
.then((keys) => {
|
||||
wrapKb = keys.wrapKb;
|
||||
kA = keys.kA;
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-begin-time'],
|
||||
options.metricsContext.flowBeginTime,
|
||||
'flow begin time set'
|
||||
);
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-id'],
|
||||
options.metricsContext.flowId,
|
||||
'flow id set'
|
||||
);
|
||||
assert.equal(emailData.headers['x-template-name'], 'recovery');
|
||||
return emailData.headers['x-recovery-code'];
|
||||
})
|
||||
.then((code) => {
|
||||
assert.isRejected(client.resetPassword(newPassword));
|
||||
return resetPassword(client, code, newPassword, undefined, options);
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.ok(query.email, 'email is in the link');
|
||||
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-begin-time'],
|
||||
options.metricsContext.flowBeginTime,
|
||||
'flow begin time set'
|
||||
);
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-id'],
|
||||
options.metricsContext.flowId,
|
||||
'flow id set'
|
||||
);
|
||||
assert.equal(emailData.headers['x-template-name'], 'passwordReset');
|
||||
})
|
||||
.then(() => {
|
||||
return upgradeCredentials(email, newPassword);
|
||||
})
|
||||
.then(
|
||||
// make sure we can still login after password reset
|
||||
() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
});
|
||||
}
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.keys();
|
||||
})
|
||||
.then((keys) => {
|
||||
assert.equal(typeof keys.wrapKb, 'string', 'yep, wrapKb');
|
||||
assert.notEqual(wrapKb, keys.wrapKb, 'wrapKb was reset');
|
||||
assert.equal(kA, keys.kA, 'kA was not reset');
|
||||
assert.equal(typeof client.kB, 'string');
|
||||
assert.equal(client.kB.length, 64, 'kB exists, has the right length');
|
||||
});
|
||||
});
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-begin-time'],
|
||||
options.metricsContext.flowBeginTime,
|
||||
'flow begin time set'
|
||||
);
|
||||
assert.equal(
|
||||
emailData.headers['x-flow-id'],
|
||||
options.metricsContext.flowId,
|
||||
'flow id set'
|
||||
);
|
||||
assert.equal(emailData.headers['x-template-name'], 'passwordReset');
|
||||
})
|
||||
.then(() => {
|
||||
return upgradeCredentials(email, newPassword);
|
||||
})
|
||||
.then(
|
||||
// make sure we can still login after password reset
|
||||
() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
});
|
||||
}
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.keys();
|
||||
})
|
||||
.then((keys) => {
|
||||
assert.equal(typeof keys.wrapKb, 'string', 'yep, wrapKb');
|
||||
assert.notEqual(wrapKb, keys.wrapKb, 'wrapKb was reset');
|
||||
assert.equal(kA, keys.kA, 'kA was not reset');
|
||||
assert.equal(typeof client.kB, 'string');
|
||||
assert.equal(client.kB.length, 64, 'kB exists, has the right length');
|
||||
});
|
||||
});
|
||||
|
||||
it('forgot password limits verify attempts', () => {
|
||||
let code = null;
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'hothamburger';
|
||||
let client = null;
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then(() => {
|
||||
client = new Client(config.publicUrl, testOptions);
|
||||
client.email = email;
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((c) => {
|
||||
code = c;
|
||||
})
|
||||
.then(() => {
|
||||
return client.reforgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((c) => {
|
||||
assert.equal(code, c, 'same code as before');
|
||||
})
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 2, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 1'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 1, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 2'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 0, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 3'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with invalid token');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid authentication token: Missing authentication',
|
||||
'token is now invalid'
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
it('forgot password limits verify attempts', () => {
|
||||
let code = null;
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'hothamburger';
|
||||
let client = null;
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then(() => {
|
||||
client = new Client(config.publicUrl, testOptions);
|
||||
client.email = email;
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((c) => {
|
||||
code = c;
|
||||
})
|
||||
.then(() => {
|
||||
return client.reforgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((c) => {
|
||||
assert.equal(code, c, 'same code as before');
|
||||
})
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 2, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 1'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 1, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 2'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with bad code');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(err.tries, 0, 'used a try');
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid confirmation code',
|
||||
'bad attempt 3'
|
||||
);
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
return resetPassword(
|
||||
client,
|
||||
'00000000000000000000000000000000',
|
||||
'password'
|
||||
);
|
||||
})
|
||||
.then(
|
||||
() => {
|
||||
assert(false, 'reset password with invalid token');
|
||||
},
|
||||
(err) => {
|
||||
assert.equal(
|
||||
err.message,
|
||||
'Invalid authentication token: Missing authentication',
|
||||
'token is now invalid'
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('recovery email link', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
let client = null;
|
||||
const options = {
|
||||
...testOptions,
|
||||
redirectTo: `https://sync.${config.smtp.redirectDomain}/`,
|
||||
service: 'sync',
|
||||
};
|
||||
return Client.create(config.publicUrl, email, password, options)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.ok(query.token, 'uid is in link');
|
||||
assert.ok(query.code, 'code is in link');
|
||||
assert.equal(
|
||||
query.redirectTo,
|
||||
options.redirectTo,
|
||||
'redirectTo is in link'
|
||||
);
|
||||
assert.equal(query.service, options.service, 'service is in link');
|
||||
assert.equal(query.email, email, 'email is in link');
|
||||
});
|
||||
});
|
||||
it('recovery email link', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
let client = null;
|
||||
const options = {
|
||||
...testOptions,
|
||||
redirectTo: `https://sync.${config.smtp.redirectDomain}/`,
|
||||
service: 'sync',
|
||||
};
|
||||
return Client.create(config.publicUrl, email, password, options)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.ok(query.token, 'uid is in link');
|
||||
assert.ok(query.code, 'code is in link');
|
||||
assert.equal(
|
||||
query.redirectTo,
|
||||
options.redirectTo,
|
||||
'redirectTo is in link'
|
||||
);
|
||||
assert.equal(query.service, options.service, 'service is in link');
|
||||
assert.equal(query.email, email, 'email is in link');
|
||||
});
|
||||
});
|
||||
|
||||
it('password forgot status with valid token', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
return Client.create(config.publicUrl, email, password, testOptions).then(
|
||||
(c) => {
|
||||
return c
|
||||
.forgotPassword()
|
||||
.then(() => {
|
||||
return c.api.passwordForgotStatus(c.passwordForgotToken);
|
||||
})
|
||||
.then((x) => {
|
||||
assert.equal(x.tries, 3, 'three tries remaining');
|
||||
assert.ok(
|
||||
x.ttl > 0 && x.ttl <= config.tokenLifetimes.passwordForgotToken,
|
||||
'ttl is ok'
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
it('password forgot status with valid token', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
return Client.create(config.publicUrl, email, password, testOptions).then(
|
||||
(c) => {
|
||||
return c
|
||||
.forgotPassword()
|
||||
.then(() => {
|
||||
return c.api.passwordForgotStatus(c.passwordForgotToken);
|
||||
})
|
||||
.then((x) => {
|
||||
assert.equal(x.tries, 3, 'three tries remaining');
|
||||
assert.ok(
|
||||
x.ttl > 0 && x.ttl <= config.tokenLifetimes.passwordForgotToken,
|
||||
'ttl is ok'
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('password forgot status with invalid token', () => {
|
||||
const client = new Client(config.publicUrl, testOptions);
|
||||
return client.api
|
||||
.passwordForgotStatus(
|
||||
'0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'
|
||||
)
|
||||
.then(
|
||||
() => assert(false),
|
||||
(err) => {
|
||||
assert.equal(err.errno, 110, 'invalid token');
|
||||
}
|
||||
);
|
||||
});
|
||||
it('password forgot status with invalid token', () => {
|
||||
const client = new Client(config.publicUrl, testOptions);
|
||||
return client.api
|
||||
.passwordForgotStatus(
|
||||
'0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'
|
||||
)
|
||||
.then(
|
||||
() => assert(false),
|
||||
(err) => {
|
||||
assert.equal(err.errno, 110, 'invalid token');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('/password/forgot/verify_code should set an unverified account as verified', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
let client = null;
|
||||
return Client.create(config.publicUrl, email, password, testOptions)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return client.emailStatus();
|
||||
})
|
||||
.then((status) => {
|
||||
assert.equal(status.verified, false, 'email unverified');
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email); // ignore this code
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
return client.verifyPasswordResetCode(code);
|
||||
})
|
||||
.then(() => {
|
||||
return client.emailStatus();
|
||||
})
|
||||
.then((status) => {
|
||||
assert.equal(status.verified, true, 'account unverified');
|
||||
});
|
||||
});
|
||||
it('/password/forgot/verify_code should set an unverified account as verified', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'something';
|
||||
let client = null;
|
||||
return Client.create(config.publicUrl, email, password, testOptions)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return client.emailStatus();
|
||||
})
|
||||
.then((status) => {
|
||||
assert.equal(status.verified, false, 'email unverified');
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email); // ignore this code
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
return client.verifyPasswordResetCode(code);
|
||||
})
|
||||
.then(() => {
|
||||
return client.emailStatus();
|
||||
})
|
||||
.then((status) => {
|
||||
assert.equal(status.verified, true, 'account unverified');
|
||||
});
|
||||
});
|
||||
|
||||
it('forgot password with service query parameter', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const options = {
|
||||
...testOptions,
|
||||
redirectTo: `https://sync.${config.smtp.redirectDomain}/`,
|
||||
serviceQuery: 'sync',
|
||||
};
|
||||
let client;
|
||||
return Client.create(config.publicUrl, email, 'wibble', options)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.equal(
|
||||
query.service,
|
||||
options.serviceQuery,
|
||||
'service is in link'
|
||||
);
|
||||
});
|
||||
});
|
||||
it('forgot password with service query parameter', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const options = {
|
||||
...testOptions,
|
||||
redirectTo: `https://sync.${config.smtp.redirectDomain}/`,
|
||||
serviceQuery: 'sync',
|
||||
};
|
||||
let client;
|
||||
return Client.create(config.publicUrl, email, 'wibble', options)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const link = emailData.headers['x-link'];
|
||||
const query = url.parse(link, true).query;
|
||||
assert.equal(
|
||||
query.service,
|
||||
options.serviceQuery,
|
||||
'service is in link'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('forgot password, then get device list', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const newPassword = 'foo';
|
||||
let client;
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
'bar',
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
return client.updateDevice({
|
||||
name: 'baz',
|
||||
type: 'mobile',
|
||||
pushCallback: 'https://updates.push.services.mozilla.com/qux',
|
||||
pushPublicKey: mocks.MOCK_PUSH_KEY,
|
||||
pushAuthKey: base64url(crypto.randomBytes(16)),
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return client.devices();
|
||||
})
|
||||
.then((devices) => {
|
||||
assert.equal(devices.length, 1, 'devices list contains 1 item');
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
return resetPassword(client, code, newPassword);
|
||||
})
|
||||
.then(() => {
|
||||
return upgradeCredentials(email, newPassword);
|
||||
})
|
||||
.then(() => {
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
newPassword,
|
||||
testOptions
|
||||
);
|
||||
})
|
||||
.then((client) => {
|
||||
return client.devices();
|
||||
})
|
||||
.then((devices) => {
|
||||
assert.equal(devices.length, 0, 'devices list is empty');
|
||||
});
|
||||
});
|
||||
it('forgot password, then get device list', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const newPassword = 'foo';
|
||||
let client;
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
'bar',
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
return client.updateDevice({
|
||||
name: 'baz',
|
||||
type: 'mobile',
|
||||
pushCallback: 'https://updates.push.services.mozilla.com/qux',
|
||||
pushPublicKey: mocks.MOCK_PUSH_KEY,
|
||||
pushAuthKey: base64url(crypto.randomBytes(16)),
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return client.devices();
|
||||
})
|
||||
.then((devices) => {
|
||||
assert.equal(devices.length, 1, 'devices list contains 1 item');
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
return resetPassword(client, code, newPassword);
|
||||
})
|
||||
.then(() => {
|
||||
return upgradeCredentials(email, newPassword);
|
||||
})
|
||||
.then(() => {
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
newPassword,
|
||||
testOptions
|
||||
);
|
||||
})
|
||||
.then((client) => {
|
||||
return client.devices();
|
||||
})
|
||||
.then((devices) => {
|
||||
assert.equal(devices.length, 0, 'devices list is empty');
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
async function resetPassword(client, code, newPassword, headers, options) {
|
||||
await client.verifyPasswordResetCode(code, headers, options);
|
||||
await client.resetPassword(newPassword, {}, options);
|
||||
}
|
||||
async function resetPassword(client, code, newPassword, headers, options) {
|
||||
await client.verifyPasswordResetCode(code, headers, options);
|
||||
await client.resetPassword(newPassword, {}, options);
|
||||
}
|
||||
|
||||
async function upgradeCredentials(email, newPassword) {
|
||||
if (testOptions.version === 'V2') {
|
||||
await Client.upgradeCredentials(config.publicUrl, email, newPassword, {
|
||||
version: '',
|
||||
key: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
async function upgradeCredentials(email, newPassword) {
|
||||
if (testOptions.version === 'V2') {
|
||||
await Client.upgradeCredentials(config.publicUrl, email, newPassword, {
|
||||
version: '',
|
||||
key: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -50,18 +50,17 @@ const mockLog = {
|
|||
};
|
||||
|
||||
describe(`#integration - remote push db`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
|
||||
let dbServer, db;
|
||||
before(() => {
|
||||
return TestServer.start(config)
|
||||
.then((s) => {
|
||||
dbServer = s;
|
||||
return DB.connect(config);
|
||||
})
|
||||
.then((x) => {
|
||||
db = x;
|
||||
});
|
||||
before(async () => {
|
||||
dbServer = await TestServer.start(config);
|
||||
db = await DB.connect(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(dbServer);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('push db tests', () => {
|
||||
|
@ -179,7 +178,5 @@ describe(`#integration - remote push db`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return Promise.all([TestServer.stop(dbServer), db.close()]);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -14,6 +14,8 @@ const BASE_36 = require('../../lib/routes/validators').BASE_36;
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote backup authentication codes`, function () {
|
||||
this.timeout(60000);
|
||||
|
||||
let server, client, email, recoveryCodes;
|
||||
const recoveryCodeCount = 9;
|
||||
const password = 'pssssst';
|
||||
|
@ -22,19 +24,21 @@ describe(`#integration${testOptions.version} - remote backup authentication code
|
|||
flowId: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
};
|
||||
|
||||
this.timeout(10000);
|
||||
|
||||
|
||||
otplib.authenticator.options = {
|
||||
encoding: 'hex',
|
||||
window: 10,
|
||||
};
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config.totp.recoveryCodes.count = recoveryCodeCount;
|
||||
config.totp.recoveryCodes.notifyLowCount = recoveryCodeCount - 2;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -248,9 +252,7 @@ describe(`#integration${testOptions.version} - remote backup authentication code
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -15,14 +15,16 @@ const password = 'allyourbasearebelongtous',
|
|||
[ {version:""}, {version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote change email`, function () {
|
||||
this.timeout(30000);
|
||||
this.timeout(60000);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config = require('../../config').default.getProperties();
|
||||
config.securityHistory.ipProfiling = {};
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -147,22 +149,29 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
.then((res) => {
|
||||
assert.ok(res, 'ok response');
|
||||
|
||||
if (testOptions.version === "V2") {
|
||||
if (testOptions.version === 'V2') {
|
||||
// Note for V2 we can login with new primary email. The password is not encrypted with
|
||||
// the original email, so this now works!
|
||||
return Client.login(config.publicUrl, secondEmail, password, testOptions);
|
||||
}
|
||||
else {
|
||||
// Verify account can login with new primary email
|
||||
return Client.login(config.publicUrl, secondEmail, password, testOptions).then(
|
||||
() => {
|
||||
assert.fail(
|
||||
new Error(
|
||||
'Should have returned correct email for user to login'
|
||||
)
|
||||
);
|
||||
}
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
secondEmail,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
} else {
|
||||
// Verify account can login with new primary email
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
secondEmail,
|
||||
password,
|
||||
testOptions
|
||||
).then(() => {
|
||||
assert.fail(
|
||||
new Error(
|
||||
'Should have returned correct email for user to login'
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
@ -175,7 +184,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
|
||||
return Client.login(config.publicUrl, err.email, password, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -190,7 +199,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
assert.ok(res, 'ok response');
|
||||
return Client.login(config.publicUrl, email, password, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -201,7 +210,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
assert.ok(res, 'ok response');
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -240,18 +249,23 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
assert.ok(res, 'ok response');
|
||||
})
|
||||
.then(() => {
|
||||
if (testOptions.version === "V2") {
|
||||
return Client.upgradeCredentials(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
version: '',
|
||||
keys: true
|
||||
});
|
||||
if (testOptions.version === 'V2') {
|
||||
return Client.upgradeCredentials(
|
||||
config.publicUrl,
|
||||
email,
|
||||
newPassword,
|
||||
{
|
||||
originalLoginEmail: secondEmail,
|
||||
version: '',
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -269,7 +283,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
.then(() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
})
|
||||
.then(() => {
|
||||
assert.fail(
|
||||
|
@ -356,7 +370,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
|
||||
const res = await Client.login(config.publicUrl, client1Email, password, {
|
||||
originalLoginEmail: client2Email,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
|
||||
assert.ok(res, 'ok response');
|
||||
|
@ -399,13 +413,17 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
});
|
||||
|
||||
it('can login', () => {
|
||||
|
||||
if (testOptions.version === "V2") {
|
||||
if (testOptions.version === 'V2') {
|
||||
// Note that with V2 logins, you can actually use the secondary email to login. This is
|
||||
// due to the fact the salt is now independent of the original email.
|
||||
return Client.login(config.publicUrl, secondEmail, password, testOptions).then((res) => {
|
||||
assert.exists(res.sessionToken)
|
||||
})
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
secondEmail,
|
||||
password,
|
||||
testOptions
|
||||
).then((res) => {
|
||||
assert.exists(res.sessionToken);
|
||||
});
|
||||
}
|
||||
|
||||
// Verify account can still login with new primary email
|
||||
|
@ -425,7 +443,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
|
||||
return Client.login(config.publicUrl, err.email, password, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -436,7 +454,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
it('can change password', () => {
|
||||
return Client.login(config.publicUrl, email, password, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
})
|
||||
.then((res) => {
|
||||
client = res;
|
||||
|
@ -446,7 +464,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
assert.ok(res, 'ok response');
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -471,18 +489,23 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
assert.ok(res, 'ok response');
|
||||
})
|
||||
.then(() => {
|
||||
if (testOptions.version === "V2") {
|
||||
return Client.upgradeCredentials(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
version: '',
|
||||
keys:true
|
||||
});
|
||||
if (testOptions.version === 'V2') {
|
||||
return Client.upgradeCredentials(
|
||||
config.publicUrl,
|
||||
email,
|
||||
newPassword,
|
||||
{
|
||||
originalLoginEmail: secondEmail,
|
||||
version: '',
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
});
|
||||
})
|
||||
.then((res) => {
|
||||
|
@ -494,7 +517,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
return client.destroyAccount().then(() => {
|
||||
return Client.login(config.publicUrl, email, newPassword, {
|
||||
originalLoginEmail: secondEmail,
|
||||
...testOptions
|
||||
...testOptions,
|
||||
})
|
||||
.then(() => {
|
||||
assert.fail(
|
||||
|
@ -509,9 +532,7 @@ describe(`#integration${testOptions.version} - remote change email`, function ()
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
|
||||
function resetPassword(client, code, newPassword, headers, options) {
|
||||
return client.verifyPasswordResetCode(code, headers, options).then(() => {
|
||||
|
|
|
@ -15,16 +15,18 @@ const password = 'allyourbasearebelongtous';
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote emails`, function () {
|
||||
this.timeout(30000);
|
||||
this.timeout(60000);
|
||||
|
||||
before(() => {
|
||||
before(async function () {
|
||||
config = require('../../config').default.getProperties();
|
||||
config.securityHistory.ipProfiling = {};
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -572,10 +574,16 @@ describe(`#integration${testOptions.version} - remote emails`, function () {
|
|||
assert.equal(emailData.cc[0].address, secondEmail);
|
||||
})
|
||||
.then(() => {
|
||||
if (testOptions.version === "V2") {
|
||||
return Client.upgradeCredentials(config.publicUrl, email, 'password1', {version:'', keys:true})
|
||||
if (testOptions.version === 'V2') {
|
||||
return Client.upgradeCredentials(
|
||||
config.publicUrl,
|
||||
email,
|
||||
'password1',
|
||||
{ version: '', keys: true }
|
||||
);
|
||||
}
|
||||
}).then((x) => {
|
||||
})
|
||||
.then((x) => {
|
||||
if (x) {
|
||||
client = x;
|
||||
}
|
||||
|
@ -627,53 +635,56 @@ describe(`#integration${testOptions.version} - remote emails`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('receives new device sign-in email', () => {
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
return TestServer.start(config)
|
||||
.then((s) => {
|
||||
server = s;
|
||||
email = server.uniqueEmail();
|
||||
secondEmail = server.uniqueEmail();
|
||||
thirdEmail = server.uniqueEmail();
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
);
|
||||
})
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.createEmail(secondEmail);
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(secondEmail);
|
||||
})
|
||||
.then((code) => {
|
||||
return client
|
||||
.verifySecondaryEmailWithCode(code, secondEmail)
|
||||
.then(() => {
|
||||
// Clear add secondary email notification
|
||||
return server.mailbox.waitForEmail(email);
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// Create unverified email
|
||||
return client.createEmail(thirdEmail);
|
||||
})
|
||||
.then(() => {
|
||||
return client.login({ keys: true });
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then((emailData) => {
|
||||
const templateName = emailData['headers']['x-template-name'];
|
||||
assert.equal(templateName, 'newDeviceLogin');
|
||||
assert.equal(emailData.cc.length, 1);
|
||||
assert.equal(emailData.cc[0].address, secondEmail);
|
||||
});
|
||||
describe('new device signin', function () {
|
||||
let skipForNewAccountsEnabled;
|
||||
before(async function () {
|
||||
// Stop currently running server, and create new config
|
||||
await TestServer.stop(server);
|
||||
skipForNewAccountsEnabled =
|
||||
config.signinConfirmation.skipForNewAccounts.enabled;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = true;
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
// Restore server to previous config
|
||||
await TestServer.stop(server);
|
||||
config.signinConfirmation.skipForNewAccounts.enabled =
|
||||
skipForNewAccountsEnabled;
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
it('receives new device sign-in email', async function () {
|
||||
email = server.uniqueEmail();
|
||||
secondEmail = server.uniqueEmail();
|
||||
thirdEmail = server.uniqueEmail();
|
||||
const client = await Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
);
|
||||
await client.createEmail(secondEmail);
|
||||
const code = await server.mailbox.waitForCode(secondEmail);
|
||||
await client.verifySecondaryEmailWithCode(code, secondEmail);
|
||||
|
||||
// Clear add secondary email notification
|
||||
await server.mailbox.waitForEmail(email);
|
||||
|
||||
// Create unverified email
|
||||
await client.createEmail(thirdEmail);
|
||||
|
||||
// Login again
|
||||
await client.login({ keys: true });
|
||||
const emailData = await server.mailbox.waitForEmail(email);
|
||||
|
||||
// Check for new device lgoin email
|
||||
const templateName = emailData['headers']['x-template-name'];
|
||||
assert.equal(templateName, 'newDeviceLogin');
|
||||
assert.equal(emailData.cc.length, 1);
|
||||
assert.equal(emailData.cc[0].address, secondEmail);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -799,7 +810,12 @@ describe(`#integration${testOptions.version} - remote emails`, function () {
|
|||
return server.mailbox.waitForEmail(email);
|
||||
})
|
||||
.then(() => {
|
||||
return Client.create(config.publicUrl, secondEmail, password, testOptions)
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
secondEmail,
|
||||
password,
|
||||
testOptions
|
||||
)
|
||||
.then(assert.fail)
|
||||
.catch((err) => {
|
||||
assert.equal(err.errno, 144, 'return correct errno');
|
||||
|
@ -931,9 +947,7 @@ describe(`#integration${testOptions.version} - remote emails`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
|
||||
function resetPassword(client, code, newPassword, headers, options) {
|
||||
return client.verifyPasswordResetCode(code, headers, options).then(() => {
|
||||
|
|
|
@ -13,15 +13,16 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote recovery email resend code`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('sign-in verification resend email verify code', () => {
|
||||
|
@ -36,25 +37,13 @@ describe(`#integration${testOptions.version} - remote recovery email resend code
|
|||
resume: 'resumeToken',
|
||||
keys: true,
|
||||
};
|
||||
return Client.create(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
options
|
||||
)
|
||||
return Client.create(config.publicUrl, email, password, options)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
// Clear first account create email and login again
|
||||
return server.mailbox
|
||||
.waitForEmail(email)
|
||||
.then(() =>
|
||||
Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
options
|
||||
)
|
||||
)
|
||||
.then(() => Client.login(config.publicUrl, email, password, options))
|
||||
.then((c) => (client = c));
|
||||
})
|
||||
.then(() => server.mailbox.waitForCode(email))
|
||||
|
@ -100,12 +89,7 @@ describe(`#integration${testOptions.version} - remote recovery email resend code
|
|||
)
|
||||
.then(() => {
|
||||
// Attempt to login from new location
|
||||
return Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
options
|
||||
);
|
||||
return Client.login(config.publicUrl, email, password, options);
|
||||
})
|
||||
.then((c) => {
|
||||
client2 = c;
|
||||
|
@ -162,12 +146,7 @@ describe(`#integration${testOptions.version} - remote recovery email resend code
|
|||
server.mailbox,
|
||||
options
|
||||
),
|
||||
Client.create(
|
||||
config.publicUrl,
|
||||
secondEmail,
|
||||
password,
|
||||
options
|
||||
),
|
||||
Client.create(config.publicUrl, secondEmail, password, options),
|
||||
])
|
||||
.then((res) => {
|
||||
// Login with `email` and attempt to resend verification code for `secondEmail`
|
||||
|
@ -232,9 +211,7 @@ describe(`#integration${testOptions.version} - remote recovery email resend code
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
|
|
|
@ -14,12 +14,14 @@ const config = require('../../config').default.getProperties();
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote recovery email verify`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('create account verify with incorrect code', () => {
|
||||
|
@ -85,9 +87,7 @@ describe(`#integration${testOptions.version} - remote recovery email verify`, fu
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -2,385 +2,395 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
const { assert } = require('chai');
|
||||
const config = require('../../config').default.getProperties();
|
||||
const crypto = require('crypto');
|
||||
const TestServer = require('../test_server');
|
||||
const Client = require('../client')();
|
||||
const { JWTool } = require('@fxa/vendored/jwtool');
|
||||
const { assert } = require('chai');
|
||||
const config = require('../../config').default.getProperties();
|
||||
const crypto = require('crypto');
|
||||
const TestServer = require('../test_server');
|
||||
const Client = require('../client')();
|
||||
const { JWTool } = require('@fxa/vendored/jwtool');
|
||||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote recovery keys`, function () {
|
||||
this.timeout(10000);
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote recovery keys`, function () {
|
||||
this.timeout(60000);
|
||||
|
||||
let server, client, email;
|
||||
const password = '(-.-)Zzz...';
|
||||
let server, client, email;
|
||||
const password = '(-.-)Zzz...';
|
||||
|
||||
let recoveryKeyId;
|
||||
let recoveryData;
|
||||
let keys;
|
||||
let recoveryKeyId;
|
||||
let recoveryData;
|
||||
let keys;
|
||||
|
||||
function createMockRecoveryKey() {
|
||||
// The auth-server does not care about the encryption details of the recovery data.
|
||||
// To simplify things, we can mock out some random bits to be stored. Check out
|
||||
// /docs/recovery_keys.md for more details on the encryption that a client
|
||||
// could perform.
|
||||
const recoveryCode = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryKeyId = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryKey = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryData = crypto.randomBytes(32).toString('hex');
|
||||
function createMockRecoveryKey() {
|
||||
// The auth-server does not care about the encryption details of the recovery data.
|
||||
// To simplify things, we can mock out some random bits to be stored. Check out
|
||||
// /docs/recovery_keys.md for more details on the encryption that a client
|
||||
// could perform.
|
||||
const recoveryCode = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryKeyId = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryKey = crypto.randomBytes(16).toString('hex');
|
||||
const recoveryData = crypto.randomBytes(32).toString('hex');
|
||||
|
||||
return Promise.resolve({
|
||||
recoveryCode,
|
||||
recoveryData,
|
||||
recoveryKeyId,
|
||||
recoveryKey,
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
recoveryCode,
|
||||
recoveryData,
|
||||
recoveryKeyId,
|
||||
recoveryKey,
|
||||
});
|
||||
}
|
||||
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => (server = s));
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
email = server.uniqueEmail();
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
assert.ok(client.authAt, 'authAt was set');
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
return client.keys();
|
||||
})
|
||||
.then((result) => {
|
||||
keys = result;
|
||||
beforeEach(() => {
|
||||
email = server.uniqueEmail();
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
assert.ok(client.authAt, 'authAt was set');
|
||||
|
||||
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
|
||||
recoveryKeyId = result.recoveryKeyId;
|
||||
recoveryData = result.recoveryData;
|
||||
// Should create account recovery key
|
||||
return client
|
||||
.createRecoveryKey(result.recoveryKeyId, result.recoveryData)
|
||||
.then((res) => assert.ok(res, 'empty response'))
|
||||
.then(() => server.mailbox.waitForEmail(email))
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'postAddAccountRecovery'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return client.keys();
|
||||
})
|
||||
.then((result) => {
|
||||
keys = result;
|
||||
|
||||
it('should get account recovery key', () => {
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) => {
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned');
|
||||
});
|
||||
});
|
||||
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
|
||||
recoveryKeyId = result.recoveryKeyId;
|
||||
recoveryData = result.recoveryData;
|
||||
// Should create account recovery key
|
||||
return client
|
||||
.createRecoveryKey(result.recoveryKeyId, result.recoveryData)
|
||||
.then((res) => assert.ok(res, 'empty response'))
|
||||
.then(() => server.mailbox.waitForEmail(email))
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'postAddAccountRecovery'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to get unknown account recovery key', () => {
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey('abce1234567890'))
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 159, 'account recovery key is not valid');
|
||||
});
|
||||
});
|
||||
it('should get account recovery key', () => {
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) => {
|
||||
assert.equal(
|
||||
res.recoveryData,
|
||||
recoveryData,
|
||||
'recoveryData returned'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
async function checkPayloadV2(mutate, restore) {
|
||||
await getAccountResetToken(client, server, email);
|
||||
await client.getRecoveryKey(recoveryKeyId);
|
||||
let err;
|
||||
try {
|
||||
mutate();
|
||||
await client.api.accountResetWithRecoveryKeyV2(
|
||||
client.accountResetToken,
|
||||
client.authPW,
|
||||
client.authPWVersion2,
|
||||
client.wrapKb,
|
||||
client.wrapKbVersion2,
|
||||
client.clientSalt,
|
||||
recoveryKeyId,
|
||||
undefined,
|
||||
{}
|
||||
);
|
||||
} catch (error) {
|
||||
err = error;
|
||||
} finally {
|
||||
restore();
|
||||
}
|
||||
it('should fail to get unknown account recovery key', () => {
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey('abce1234567890'))
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 159, 'account recovery key is not valid');
|
||||
});
|
||||
});
|
||||
|
||||
assert.exists(err);
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
}
|
||||
async function checkPayloadV2(mutate, restore) {
|
||||
await getAccountResetToken(client, server, email);
|
||||
await client.getRecoveryKey(recoveryKeyId);
|
||||
let err;
|
||||
try {
|
||||
mutate();
|
||||
await client.api.accountResetWithRecoveryKeyV2(
|
||||
client.accountResetToken,
|
||||
client.authPW,
|
||||
client.authPWVersion2,
|
||||
client.wrapKb,
|
||||
client.wrapKbVersion2,
|
||||
client.clientSalt,
|
||||
recoveryKeyId,
|
||||
undefined,
|
||||
{}
|
||||
);
|
||||
} catch (error) {
|
||||
err = error;
|
||||
} finally {
|
||||
restore();
|
||||
}
|
||||
|
||||
it('should fail if wrapKb is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
const temp = client.wrapKb;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.unwrapBKey = undefined;
|
||||
client.wrapKb = undefined;
|
||||
},
|
||||
() => {
|
||||
client.wrapKb = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
assert.exists(err);
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
}
|
||||
|
||||
it('should fail if wrapKbVersion2 is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
it('should fail if wrapKb is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
const temp = client.wrapKb;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.unwrapBKey = undefined;
|
||||
client.wrapKb = undefined;
|
||||
},
|
||||
() => {
|
||||
client.wrapKb = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const temp = client.wrapKbVersion2;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.wrapKbVersion2 = undefined;
|
||||
},
|
||||
() => {
|
||||
client.wrapKbVersion2 = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
it('should fail if wrapKbVersion2 is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
it('should fail if clientSalt is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
const temp = client.clientSalt;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.clientSalt = undefined;
|
||||
},
|
||||
() => {
|
||||
client.clientSalt = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
const temp = client.wrapKbVersion2;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.wrapKbVersion2 = undefined;
|
||||
},
|
||||
() => {
|
||||
client.wrapKbVersion2 = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should fail if recoveryKeyId is missing', function () {
|
||||
if (testOptions.version === 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
it('should fail if clientSalt is missing and authPWVersion2 is provided', async function () {
|
||||
if (testOptions.version !== 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
const temp = client.clientSalt;
|
||||
await checkPayloadV2(
|
||||
() => {
|
||||
client.clientSalt = undefined;
|
||||
},
|
||||
() => {
|
||||
client.clientSalt = temp;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) =>
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned')
|
||||
)
|
||||
.then(() =>
|
||||
client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
undefined,
|
||||
{},
|
||||
{ keys: true }
|
||||
)
|
||||
)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
});
|
||||
});
|
||||
it('should fail if recoveryKeyId is missing', function () {
|
||||
if (testOptions.version === 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
it('should fail if wrapKb is missing', function () {
|
||||
if (testOptions.version === 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) =>
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned')
|
||||
)
|
||||
.then(() =>
|
||||
client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
undefined,
|
||||
{},
|
||||
{ keys: true }
|
||||
)
|
||||
)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
});
|
||||
});
|
||||
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) =>
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned')
|
||||
)
|
||||
.then(() =>
|
||||
client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
recoveryKeyId,
|
||||
{},
|
||||
{ keys: true, undefinedWrapKb: true }
|
||||
)
|
||||
)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
});
|
||||
});
|
||||
it('should fail if wrapKb is missing', function () {
|
||||
if (testOptions.version === 'V2') {
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
it('should reset password while keeping kB', async () => {
|
||||
await getAccountResetToken(client, server, email);
|
||||
let res = await client.getRecoveryKey(recoveryKeyId);
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned');
|
||||
return getAccountResetToken(client, server, email)
|
||||
.then(() => client.getRecoveryKey(recoveryKeyId))
|
||||
.then((res) =>
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned')
|
||||
)
|
||||
.then(() =>
|
||||
client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
recoveryKeyId,
|
||||
{},
|
||||
{ keys: true, undefinedWrapKb: true }
|
||||
)
|
||||
)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 107, 'invalid param');
|
||||
});
|
||||
});
|
||||
|
||||
const duration = 1000 * 60 * 60 * 24; // 24 hours
|
||||
const publicKey = {
|
||||
algorithm: 'RS',
|
||||
n: '4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
|
||||
e: '65537',
|
||||
};
|
||||
const cert1 = JWTool.unverify(
|
||||
await client.sign(publicKey, duration)
|
||||
).payload;
|
||||
it('should reset password while keeping kB', async () => {
|
||||
await getAccountResetToken(client, server, email);
|
||||
let res = await client.getRecoveryKey(recoveryKeyId);
|
||||
assert.equal(res.recoveryData, recoveryData, 'recoveryData returned');
|
||||
|
||||
res = await client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
recoveryKeyId,
|
||||
{},
|
||||
{ keys: true }
|
||||
);
|
||||
assert.equal(res.uid, client.uid, 'uid returned');
|
||||
assert.ok(res.sessionToken, 'sessionToken return');
|
||||
const duration = 1000 * 60 * 60 * 24; // 24 hours
|
||||
const publicKey = {
|
||||
algorithm: 'RS',
|
||||
n: '4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
|
||||
e: '65537',
|
||||
};
|
||||
const cert1 = JWTool.unverify(
|
||||
await client.sign(publicKey, duration)
|
||||
).payload;
|
||||
|
||||
const emailData = await server.mailbox.waitForEmail(email);
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'passwordResetAccountRecovery',
|
||||
'correct template sent'
|
||||
);
|
||||
res = await client.resetAccountWithRecoveryKey(
|
||||
'newpass',
|
||||
keys.kB,
|
||||
recoveryKeyId,
|
||||
{},
|
||||
{ keys: true }
|
||||
);
|
||||
assert.equal(res.uid, client.uid, 'uid returned');
|
||||
assert.ok(res.sessionToken, 'sessionToken return');
|
||||
|
||||
res = await client.keys();
|
||||
assert.equal(res.kA, keys.kA, 'kA are equal returned');
|
||||
assert.equal(res.kB, keys.kB, 'kB are equal returned');
|
||||
const emailData = await server.mailbox.waitForEmail(email);
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'passwordResetAccountRecovery',
|
||||
'correct template sent'
|
||||
);
|
||||
|
||||
// Login with new password and check to see kB hasn't changed
|
||||
const c = await Client.login(config.publicUrl, email, 'newpass', {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
});
|
||||
assert.ok(c.sessionToken, 'sessionToken returned');
|
||||
res = await c.keys();
|
||||
assert.equal(res.kA, keys.kA, 'kA are equal returned');
|
||||
assert.equal(res.kB, keys.kB, 'kB are equal returned');
|
||||
res = await client.keys();
|
||||
assert.equal(res.kA, keys.kA, 'kA are equal returned');
|
||||
assert.equal(res.kB, keys.kB, 'kB are equal returned');
|
||||
|
||||
const cert2 = JWTool.unverify(await c.sign(publicKey, duration)).payload;
|
||||
// Login with new password and check to see kB hasn't changed
|
||||
const c = await Client.login(config.publicUrl, email, 'newpass', {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
});
|
||||
assert.ok(c.sessionToken, 'sessionToken returned');
|
||||
res = await c.keys();
|
||||
assert.equal(res.kA, keys.kA, 'kA are equal returned');
|
||||
assert.equal(res.kB, keys.kB, 'kB are equal returned');
|
||||
|
||||
assert.equal(cert1['fxa-uid'], cert2['fxa-uid']);
|
||||
assert.ok(cert1['fxa-generation'] < cert2['fxa-generation']);
|
||||
assert.equal(cert1['fxa-keysChangedAt'], cert2['fxa-keysChangedAt']);
|
||||
});
|
||||
const cert2 = JWTool.unverify(await c.sign(publicKey, duration)).payload;
|
||||
|
||||
it('should delete account recovery key', () => {
|
||||
return client.deleteRecoveryKey().then((res) => {
|
||||
assert.ok(res, 'empty response');
|
||||
return client
|
||||
.getRecoveryKeyExists()
|
||||
.then((result) => {
|
||||
assert.equal(result.exists, false, 'account recovery key deleted');
|
||||
})
|
||||
.then(() => server.mailbox.waitForEmail(email))
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'postRemoveAccountRecovery'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
assert.equal(cert1['fxa-uid'], cert2['fxa-uid']);
|
||||
assert.ok(cert1['fxa-generation'] < cert2['fxa-generation']);
|
||||
assert.equal(cert1['fxa-keysChangedAt'], cert2['fxa-keysChangedAt']);
|
||||
});
|
||||
|
||||
it('should fail to create account recovery key when one already exists', () => {
|
||||
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
|
||||
recoveryKeyId = result.recoveryKeyId;
|
||||
recoveryData = result.recoveryData;
|
||||
return client
|
||||
.createRecoveryKey(result.recoveryKeyId, result.recoveryData)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 161, 'correct errno');
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should delete account recovery key', () => {
|
||||
return client.deleteRecoveryKey().then((res) => {
|
||||
assert.ok(res, 'empty response');
|
||||
return client
|
||||
.getRecoveryKeyExists()
|
||||
.then((result) => {
|
||||
assert.equal(result.exists, false, 'account recovery key deleted');
|
||||
})
|
||||
.then(() => server.mailbox.waitForEmail(email))
|
||||
.then((emailData) => {
|
||||
assert.equal(
|
||||
emailData.headers['x-template-name'],
|
||||
'postRemoveAccountRecovery'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('check account recovery key status', () => {
|
||||
describe('with sessionToken', () => {
|
||||
it('should return true if account recovery key exists and enabled', () => {
|
||||
return client.getRecoveryKeyExists().then((res) => {
|
||||
assert.equal(res.exists, true, 'account recovery key exists');
|
||||
});
|
||||
});
|
||||
it('should fail to create account recovery key when one already exists', () => {
|
||||
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
|
||||
recoveryKeyId = result.recoveryKeyId;
|
||||
recoveryData = result.recoveryData;
|
||||
return client
|
||||
.createRecoveryKey(result.recoveryKeyId, result.recoveryData)
|
||||
.then(assert.fail, (err) => {
|
||||
assert.equal(err.errno, 161, 'correct errno');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should return false if account recovery key doesn't exist", () => {
|
||||
email = server.uniqueEmail();
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
return client.getRecoveryKeyExists();
|
||||
})
|
||||
.then((res) => {
|
||||
assert.equal(
|
||||
res.exists,
|
||||
false,
|
||||
'account recovery key doesnt exists'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('check account recovery key status', () => {
|
||||
describe('with sessionToken', () => {
|
||||
it('should return true if account recovery key exists and enabled', () => {
|
||||
return client.getRecoveryKeyExists().then((res) => {
|
||||
assert.equal(res.exists, true, 'account recovery key exists');
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if account recovery key exist but not enabled', async () => {
|
||||
const email2 = server.uniqueEmail();
|
||||
const client2 = await Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email2,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
const recoveryKeyMock = await createMockRecoveryKey(
|
||||
client2.uid,
|
||||
keys.kB
|
||||
);
|
||||
let res = await client2.createRecoveryKey(
|
||||
recoveryKeyMock.recoveryKeyId,
|
||||
recoveryKeyMock.recoveryData,
|
||||
false
|
||||
);
|
||||
assert.deepEqual(res, {});
|
||||
it("should return false if account recovery key doesn't exist", () => {
|
||||
email = server.uniqueEmail();
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
)
|
||||
.then((c) => {
|
||||
client = c;
|
||||
return client.getRecoveryKeyExists();
|
||||
})
|
||||
.then((res) => {
|
||||
assert.equal(
|
||||
res.exists,
|
||||
false,
|
||||
'account recovery key doesnt exists'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
res = await client2.getRecoveryKeyExists();
|
||||
assert.equal(res.exists, false, 'account recovery key doesnt exists');
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should return false if account recovery key exist but not enabled', async () => {
|
||||
const email2 = server.uniqueEmail();
|
||||
const client2 = await Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email2,
|
||||
password,
|
||||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
const recoveryKeyMock = await createMockRecoveryKey(
|
||||
client2.uid,
|
||||
keys.kB
|
||||
);
|
||||
let res = await client2.createRecoveryKey(
|
||||
recoveryKeyMock.recoveryKeyId,
|
||||
recoveryKeyMock.recoveryData,
|
||||
false
|
||||
);
|
||||
assert.deepEqual(res, {});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
});
|
||||
res = await client2.getRecoveryKeyExists();
|
||||
assert.equal(
|
||||
res.exists,
|
||||
false,
|
||||
'account recovery key doesnt exists'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getAccountResetToken(client, server, email) {
|
||||
return client
|
||||
.forgotPassword()
|
||||
.then(() => server.mailbox.waitForCode(email))
|
||||
.then((code) =>
|
||||
client.verifyPasswordResetCode(
|
||||
code,
|
||||
{},
|
||||
{ accountResetWithRecoveryKey: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function getAccountResetToken(client, server, email) {
|
||||
return client
|
||||
.forgotPassword()
|
||||
.then(() => server.mailbox.waitForCode(email))
|
||||
.then((code) =>
|
||||
client.verifyPasswordResetCode(
|
||||
code,
|
||||
{},
|
||||
{ accountResetWithRecoveryKey: true }
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,121 +2,119 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
const { assert } = require('chai');
|
||||
const Client = require('../client')();
|
||||
const TestServer = require('../test_server');
|
||||
const config = require('../../config').default.getProperties();
|
||||
const { assert } = require('chai');
|
||||
const Client = require('../client')();
|
||||
const TestServer = require('../test_server');
|
||||
const config = require('../../config').default.getProperties();
|
||||
|
||||
function resetPassword(client, code, newPassword, options) {
|
||||
return client.verifyPasswordResetCode(code).then(() => {
|
||||
return client.resetPassword(newPassword, {}, options);
|
||||
});
|
||||
}
|
||||
function resetPassword(client, code, newPassword, options) {
|
||||
return client.verifyPasswordResetCode(code).then(() => {
|
||||
return client.resetPassword(newPassword, {}, options);
|
||||
});
|
||||
}
|
||||
|
||||
function delay(seconds) {
|
||||
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
||||
}
|
||||
function delay(seconds) {
|
||||
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
||||
}
|
||||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote securityEvents`, () => {
|
||||
let server;
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote securityEvents`, function () {
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
|
||||
before(function () {
|
||||
this.timeout(15000);
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
});
|
||||
before(async function () {
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
it('returns securityEvents on creating and login into an account', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'abcdef';
|
||||
let client;
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.login().then(() => {
|
||||
return delay(1).then(() => {
|
||||
return client.securityEvents();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then((events) => {
|
||||
assert.equal(events.length, 2);
|
||||
assert.equal(events[0].name, 'account.login');
|
||||
assert.isBelow(events[0].createdAt, new Date().getTime());
|
||||
assert.equal(events[0].verified, false);
|
||||
it('returns securityEvents on creating and login into an account', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'abcdef';
|
||||
let client;
|
||||
|
||||
assert.equal(events[1].name, 'account.create');
|
||||
assert.isBelow(events[1].createdAt, new Date().getTime());
|
||||
assert.equal(events[1].verified, true);
|
||||
});
|
||||
});
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
return client.login().then(() => {
|
||||
return delay(1).then(() => {
|
||||
return client.securityEvents();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then((events) => {
|
||||
assert.equal(events.length, 2);
|
||||
assert.equal(events[0].name, 'account.login');
|
||||
assert.isBelow(events[0].createdAt, new Date().getTime());
|
||||
assert.equal(events[0].verified, false);
|
||||
|
||||
it('returns security events after account reset w/o keys, with sessionToken', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'oldPassword';
|
||||
const newPassword = 'newPassword';
|
||||
let client;
|
||||
assert.equal(events[1].name, 'account.create');
|
||||
assert.isBelow(events[1].createdAt, new Date().getTime());
|
||||
assert.equal(events[1].verified, true);
|
||||
});
|
||||
});
|
||||
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
assert.isRejected(client.resetPassword(newPassword));
|
||||
return resetPassword(client, code, newPassword);
|
||||
})
|
||||
.then((response) => {
|
||||
assert.ok(response.sessionToken, 'session token is in response');
|
||||
assert(
|
||||
!response.keyFetchToken,
|
||||
'keyFetchToken token is not in response'
|
||||
);
|
||||
assert.equal(response.verified, true, 'verified is true');
|
||||
})
|
||||
.then(() => {
|
||||
return delay(1).then(() => {
|
||||
return client.securityEvents();
|
||||
});
|
||||
})
|
||||
.then((events) => {
|
||||
assert.equal(events.length, 2);
|
||||
assert.equal(events[0].name, 'account.reset');
|
||||
assert.isBelow(events[0].createdAt, new Date().getTime());
|
||||
assert.equal(events[0].verified, true);
|
||||
it('returns security events after account reset w/o keys, with sessionToken', () => {
|
||||
const email = server.uniqueEmail();
|
||||
const password = 'oldPassword';
|
||||
const newPassword = 'newPassword';
|
||||
let client;
|
||||
|
||||
assert.equal(events[1].name, 'account.create');
|
||||
assert.isBelow(events[1].createdAt, new Date().getTime());
|
||||
assert.equal(events[1].verified, true);
|
||||
});
|
||||
});
|
||||
return Client.createAndVerify(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
server.mailbox,
|
||||
testOptions
|
||||
)
|
||||
.then((x) => {
|
||||
client = x;
|
||||
})
|
||||
.then(() => {
|
||||
return client.forgotPassword();
|
||||
})
|
||||
.then(() => {
|
||||
return server.mailbox.waitForCode(email);
|
||||
})
|
||||
.then((code) => {
|
||||
assert.isRejected(client.resetPassword(newPassword));
|
||||
return resetPassword(client, code, newPassword);
|
||||
})
|
||||
.then((response) => {
|
||||
assert.ok(response.sessionToken, 'session token is in response');
|
||||
assert(
|
||||
!response.keyFetchToken,
|
||||
'keyFetchToken token is not in response'
|
||||
);
|
||||
assert.equal(response.verified, true, 'verified is true');
|
||||
})
|
||||
.then(() => {
|
||||
return delay(1).then(() => {
|
||||
return client.securityEvents();
|
||||
});
|
||||
})
|
||||
.then((events) => {
|
||||
assert.equal(events.length, 2);
|
||||
assert.equal(events[0].name, 'account.reset');
|
||||
assert.isBelow(events[0].createdAt, new Date().getTime());
|
||||
assert.equal(events[0].verified, true);
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
});
|
||||
});
|
||||
assert.equal(events[1].name, 'account.create');
|
||||
assert.isBelow(events[1].createdAt, new Date().getTime());
|
||||
assert.equal(events[1].verified, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,13 +19,14 @@ const publicKey = {
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote session`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
before(() => {
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
describe('destroy', () => {
|
||||
|
@ -609,8 +610,6 @@ const publicKey = {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,17 +10,18 @@ const TestServer = require('../test_server');
|
|||
const path = require('path');
|
||||
|
||||
describe(`#integration - remote sign key`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server;
|
||||
before(() => {
|
||||
before(async () => {
|
||||
const config = require('../../config').default.getProperties();
|
||||
config.oldPublicKeyFile = path.resolve(
|
||||
__dirname,
|
||||
'../../config/public-key.json'
|
||||
);
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('.well-known/browserid has keys', () => {
|
||||
|
@ -37,7 +38,5 @@ describe(`#integration - remote sign key`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -37,7 +37,7 @@ const PRODUCT_NAME = 'All Done Pro';
|
|||
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote subscriptions:`, function () {
|
||||
this.timeout(10000);
|
||||
this.timeout(60000);
|
||||
|
||||
before(async () => {
|
||||
config.subscriptions.stripeApiKey = null;
|
||||
|
@ -48,7 +48,7 @@ const PRODUCT_NAME = 'All Done Pro';
|
|||
});
|
||||
|
||||
describe('config.subscriptions.enabled = true and direct stripe access:', function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
|
||||
let client, server, tokens;
|
||||
const mockStripeHelper = {};
|
||||
|
|
|
@ -20,18 +20,19 @@ const {
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote tokenCodes`, function () {
|
||||
this.timeout(60000);
|
||||
|
||||
let server, client, email, code;
|
||||
const password = 'pssssst';
|
||||
|
||||
this.timeout(10000);
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
Container.set(PlaySubscriptions, {});
|
||||
Container.set(AppStoreSubscriptions, {});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -241,9 +242,7 @@ describe(`#integration${testOptions.version} - remote tokenCodes`, function () {
|
|||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -22,9 +22,10 @@ function fail() {
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote token expiry`, function () {
|
||||
this.timeout(15000);
|
||||
this.timeout(60000);
|
||||
let server, config;
|
||||
before(() => {
|
||||
|
||||
before(async () => {
|
||||
config = require('../../config').default.getProperties();
|
||||
config.tokenLifetimes.passwordChangeToken = 1;
|
||||
config.tokenLifetimes.sessionTokenWithoutDevice = 1;
|
||||
|
@ -32,9 +33,11 @@ describe(`#integration${testOptions.version} - remote token expiry`, function ()
|
|||
Container.set(PlaySubscriptions, {});
|
||||
Container.set(AppStoreSubscriptions, {});
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
it('token expiry', () => {
|
||||
|
@ -73,9 +76,7 @@ describe(`#integration${testOptions.version} - remote token expiry`, function ()
|
|||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -21,6 +21,8 @@ const {
|
|||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
|
||||
describe(`#integration${testOptions.version} - remote totp`, function () {
|
||||
this.timeout(60000);
|
||||
|
||||
let server, client, email, totpToken, authenticator;
|
||||
const password = 'pssssst';
|
||||
const metricsContext = {
|
||||
|
@ -28,24 +30,24 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
flowId: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
|
||||
};
|
||||
|
||||
this.timeout(10000);
|
||||
|
||||
otplib.authenticator.options = {
|
||||
crypto: crypto,
|
||||
encoding: 'hex',
|
||||
window: 10,
|
||||
};
|
||||
|
||||
before(() => {
|
||||
before(async () => {
|
||||
config.securityHistory.ipProfiling = {};
|
||||
config.signinConfirmation.skipForNewAccounts.enabled = false;
|
||||
|
||||
Container.set(PlaySubscriptions, {});
|
||||
Container.set(AppStoreSubscriptions, {});
|
||||
|
||||
return TestServer.start(config).then((s) => {
|
||||
server = s;
|
||||
});
|
||||
server = await TestServer.start(config);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
});
|
||||
|
||||
function verifyTOTP(client) {
|
||||
|
@ -78,7 +80,7 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
emailData.headers['x-template-name'],
|
||||
'postAddTwoStepAuthentication'
|
||||
);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -192,7 +194,7 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
})
|
||||
|
@ -257,7 +259,7 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
server.mailbox,
|
||||
{
|
||||
...testOptions,
|
||||
keys: true
|
||||
keys: true,
|
||||
}
|
||||
);
|
||||
})
|
||||
|
@ -271,7 +273,10 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
});
|
||||
|
||||
it('should request `totp-2fa` on login if user has verified totp token', () => {
|
||||
return Client.login(config.publicUrl, email, password, { ...testOptions, keys:true }).then((response) => {
|
||||
return Client.login(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}).then((response) => {
|
||||
assert.equal(
|
||||
response.verificationMethod,
|
||||
'totp-2fa',
|
||||
|
@ -289,7 +294,12 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
return client
|
||||
.deleteTotpToken()
|
||||
.then(() => client.createTotpToken())
|
||||
.then(() => Client.login(config.publicUrl, email, password, { ...testOptions, keys:true }))
|
||||
.then(() =>
|
||||
Client.login(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
})
|
||||
)
|
||||
.then((response) => {
|
||||
assert.notEqual(
|
||||
response.verificationMethod,
|
||||
|
@ -305,7 +315,10 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
});
|
||||
|
||||
it('should not bypass `totp-2fa` by resending sign-in confirmation code', () => {
|
||||
return Client.login(config.publicUrl, email, password, {...testOptions, keys:true}).then((response) => {
|
||||
return Client.login(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
}).then((response) => {
|
||||
client = response;
|
||||
assert.equal(
|
||||
response.verificationMethod,
|
||||
|
@ -364,21 +377,9 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
});
|
||||
|
||||
it('should not bypass `totp-2fa` by when using session reauth', () => {
|
||||
return Client.login(config.publicUrl, email, password, testOptions).then((response) => {
|
||||
client = response;
|
||||
assert.equal(
|
||||
response.verificationMethod,
|
||||
'totp-2fa',
|
||||
'verification method set'
|
||||
);
|
||||
assert.equal(
|
||||
response.verificationReason,
|
||||
'login',
|
||||
'verification reason set'
|
||||
);
|
||||
|
||||
// Lets attempt to sign-in reusing session reauth
|
||||
return client.reauth().then((response) => {
|
||||
return Client.login(config.publicUrl, email, password, testOptions).then(
|
||||
(response) => {
|
||||
client = response;
|
||||
assert.equal(
|
||||
response.verificationMethod,
|
||||
'totp-2fa',
|
||||
|
@ -389,34 +390,43 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
'login',
|
||||
'verification reason set'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Lets attempt to sign-in reusing session reauth
|
||||
return client.reauth().then((response) => {
|
||||
assert.equal(
|
||||
response.verificationMethod,
|
||||
'totp-2fa',
|
||||
'verification method set'
|
||||
);
|
||||
assert.equal(
|
||||
response.verificationReason,
|
||||
'login',
|
||||
'verification reason set'
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should not create verified session after account reset with totp', async () => {
|
||||
const newPassword = 'anotherPassword';
|
||||
|
||||
const client = await Client.login(config.publicUrl, email, password, { ...testOptions, keys:true });
|
||||
const client = await Client.login(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
keys: true,
|
||||
});
|
||||
assert.equal(
|
||||
client.verificationMethod,
|
||||
'totp-2fa',
|
||||
'verification method set'
|
||||
);
|
||||
assert.equal(
|
||||
client.verificationReason,
|
||||
'login',
|
||||
'verification reason set'
|
||||
);
|
||||
assert.equal(client.verificationReason, 'login', 'verification reason set');
|
||||
await client.forgotPassword();
|
||||
const code = await server.mailbox.waitForCode(email);
|
||||
await client.verifyPasswordResetCode(code);
|
||||
const res = await client.resetPassword(newPassword, {}, { keys: true })
|
||||
const res = await client.resetPassword(newPassword, {}, { keys: true });
|
||||
|
||||
assert.equal(
|
||||
res.verificationMethod,
|
||||
'totp-2fa',
|
||||
'verificationMethod set'
|
||||
);
|
||||
assert.equal(res.verificationMethod, 'totp-2fa', 'verificationMethod set');
|
||||
assert.equal(res.verificationReason, 'login', 'verificationMethod set');
|
||||
assert.equal(res.verified, false);
|
||||
assert.ok(res.keyFetchToken);
|
||||
|
@ -515,9 +525,7 @@ describe(`#integration${testOptions.version} - remote totp`, function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
return TestServer.stop(server);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -31,61 +31,56 @@ const {
|
|||
AppStoreSubscriptions,
|
||||
} = require('../../lib/payments/iap/apple-app-store/subscriptions');
|
||||
|
||||
let client, db, server;
|
||||
[{ version: '' }, { version: 'V2' }].forEach((testOptions) => {
|
||||
describe(`#integration${testOptions.version} - remote verifier upgrade`, function () {
|
||||
this.timeout(60000);
|
||||
|
||||
[{version:""},{version:"V2"}].forEach((testOptions) => {
|
||||
let client, db, server;
|
||||
|
||||
describe(`#integration${testOptions.version} - remote verifier upgrade`, function () {
|
||||
this.timeout(30000);
|
||||
before(async () => {
|
||||
config.verifierVersion = 0;
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
|
||||
before(async () => {
|
||||
config.verifierVersion = 0;
|
||||
config.securityHistory.ipProfiling.allowedRecency = 0;
|
||||
Container.set(PlaySubscriptions, {});
|
||||
Container.set(AppStoreSubscriptions, {});
|
||||
|
||||
Container.set(PlaySubscriptions, {});
|
||||
Container.set(AppStoreSubscriptions, {});
|
||||
|
||||
server = await TestServer.start(config);
|
||||
db = await DB.connect(config);
|
||||
});
|
||||
|
||||
it('upgrading verifierVersion upgrades the account on password change', async () => {
|
||||
const email = `${Math.random()}@example.com`;
|
||||
const password = 'ok';
|
||||
|
||||
client = await Client.create(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
preVerified: true,
|
||||
keys: true,
|
||||
server = await TestServer.start(config);
|
||||
db = await DB.connect(config);
|
||||
});
|
||||
|
||||
let account = await db.account(client.uid);
|
||||
|
||||
assert.equal(account.verifierVersion, 0, 'wrong version');
|
||||
|
||||
await TestServer.stop(server);
|
||||
|
||||
config.verifierVersion = 1;
|
||||
server = await TestServer.start(config);
|
||||
|
||||
client = await Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
|
||||
await client.changePassword(password);
|
||||
account = await db.account(client.uid);
|
||||
assert.equal(account.verifierVersion, 1, 'wrong upgrade version');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
try {
|
||||
await db.close();
|
||||
after(async () => {
|
||||
await TestServer.stop(server);
|
||||
} catch (e) {}
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('upgrading verifierVersion upgrades the account on password change', async () => {
|
||||
const email = `${Math.random()}@example.com`;
|
||||
const password = 'ok';
|
||||
|
||||
client = await Client.create(config.publicUrl, email, password, {
|
||||
...testOptions,
|
||||
preVerified: true,
|
||||
keys: true,
|
||||
});
|
||||
|
||||
let account = await db.account(client.uid);
|
||||
|
||||
assert.equal(account.verifierVersion, 0, 'wrong version');
|
||||
await TestServer.stop(server);
|
||||
|
||||
config.verifierVersion = 1;
|
||||
server = await TestServer.start(config);
|
||||
|
||||
client = await Client.login(
|
||||
config.publicUrl,
|
||||
email,
|
||||
password,
|
||||
testOptions
|
||||
);
|
||||
|
||||
await client.changePassword(password);
|
||||
account = await db.account(client.uid);
|
||||
assert.equal(account.verifierVersion, 1, 'wrong upgrade version');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -44,9 +44,11 @@ function createRandomEmailAddr(template) {
|
|||
return `${Math.random() + template}`;
|
||||
}
|
||||
|
||||
describe('#integration - scripts/check-users:', async function () {
|
||||
this.timeout(30000);
|
||||
describe('#integration - scripts/check-users:', function () {
|
||||
this.timeout(60000);
|
||||
|
||||
let server, db, validClient, invalidClient, filename;
|
||||
|
||||
before(async () => {
|
||||
server = await TestServer.start(config);
|
||||
db = await DB.connect(config);
|
||||
|
|
|
@ -15,8 +15,6 @@ const createProfileHelper = require('./profile_helper');
|
|||
const { CapabilityService } = require('../lib/payments/capability');
|
||||
const { AppConfig } = require('../lib/types');
|
||||
|
||||
let currentServer;
|
||||
|
||||
/* eslint-disable no-console */
|
||||
function TestServer(config, printLogs, options = {}) {
|
||||
Container.set(AppConfig, config);
|
||||
|
@ -57,60 +55,42 @@ function TestServer(config, printLogs, options = {}) {
|
|||
}
|
||||
|
||||
TestServer.start = async function (config, printLogs, options) {
|
||||
await TestServer.stop();
|
||||
|
||||
currentServer = new TestServer(config, printLogs, options);
|
||||
|
||||
return currentServer.start().then(() => currentServer);
|
||||
const server = new TestServer(config, printLogs, options);
|
||||
await server.start();
|
||||
return server;
|
||||
};
|
||||
|
||||
TestServer.prototype.start = function () {
|
||||
TestServer.prototype.start = async function () {
|
||||
const { authServerMockDependencies = {} } = this.options;
|
||||
const createAuthServer = proxyquire(
|
||||
'../bin/key_server',
|
||||
authServerMockDependencies
|
||||
);
|
||||
|
||||
const promises = [
|
||||
createAuthServer(this.config),
|
||||
createMailHelper(this.printLogs),
|
||||
];
|
||||
this.server = await createAuthServer(this.config);
|
||||
this.mail = await createMailHelper(this.printLogs);
|
||||
|
||||
if (this.config.profileServer.url && !this.profileServer) {
|
||||
promises.push(createProfileHelper());
|
||||
if (this.config.profileServer.url) {
|
||||
this.profileServer = await createProfileHelper();
|
||||
}
|
||||
return Promise.all(promises).then(([auth, mail, profileServer]) => {
|
||||
this.server = auth;
|
||||
this.mail = mail;
|
||||
this.profileServer = profileServer;
|
||||
});
|
||||
};
|
||||
|
||||
TestServer.stop = async function (maybeServer) {
|
||||
if (maybeServer) {
|
||||
await maybeServer.stop();
|
||||
maybeServer = undefined;
|
||||
TestServer.stop = async function (server) {
|
||||
if (!server) {
|
||||
throw new Error('Server must be provided');
|
||||
}
|
||||
|
||||
if (currentServer) {
|
||||
await currentServer.stop();
|
||||
currentServer = undefined;
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
await server.stop();
|
||||
};
|
||||
|
||||
TestServer.prototype.stop = async function () {
|
||||
currentServer = undefined;
|
||||
|
||||
if (this.server) {
|
||||
const doomed = [this.server.close(), this.mail.close()];
|
||||
if (this.profileServer) {
|
||||
doomed.push(this.profileServer.close());
|
||||
}
|
||||
return Promise.all(doomed);
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
await this.server.close();
|
||||
}
|
||||
if (this.mail) {
|
||||
await this.mail.close();
|
||||
}
|
||||
if (this.profileServer) {
|
||||
await this.profileServer.close();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче