mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
f4ad3b23ba
refs https://github.com/TryGhost/Toolbox/issues/129 - The "Origin" header is require in Admin API requests so it makes sense to bake it into a default request made by most tests. Reduces unnecesary fluf around test request setup and removes a "config" dependency in each tests suite using the "e2e framework"
419 lines
14 KiB
JavaScript
419 lines
14 KiB
JavaScript
const {expect} = require('chai');
|
|
const {any} = require('expect');
|
|
const security = require('@tryghost/security');
|
|
|
|
const testUtils = require('../../../../utils/index');
|
|
const framework = require('../../../../utils/e2e-framework');
|
|
const models = require('../../../../../core/server/models/index');
|
|
const settingsCache = require('../../../../../core/shared/settings-cache');
|
|
|
|
describe('Authentication API canary', function () {
|
|
let request;
|
|
let emailStub;
|
|
|
|
describe('Blog setup', function () {
|
|
before(async function () {
|
|
request = await framework.getAgent('/ghost/api/canary/admin/');
|
|
});
|
|
|
|
after(async function () {
|
|
await framework.resetDb();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
emailStub = framework.stubMail();
|
|
});
|
|
|
|
afterEach(function () {
|
|
framework.restoreMocks();
|
|
});
|
|
|
|
it('is setup? no', async function () {
|
|
const res = await request
|
|
.get('authentication/setup')
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('complete setup', async function () {
|
|
const res = await request
|
|
.post('authentication/setup')
|
|
.send({
|
|
setup: [{
|
|
name: 'test user',
|
|
email: 'test@example.com',
|
|
password: 'thisissupersafe',
|
|
blogTitle: 'a test blog'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(201);
|
|
|
|
expect(res.body).to.matchSnapshot({
|
|
users: [{
|
|
created_at: any(Date),
|
|
updated_at: any(Date)
|
|
}]
|
|
});
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
|
|
expect(emailStub.called).to.be.true;
|
|
});
|
|
|
|
it('is setup? yes', async function () {
|
|
const res = await request
|
|
.get('authentication/setup');
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('complete setup again', function () {
|
|
return request
|
|
.post('authentication/setup')
|
|
.send({
|
|
setup: [{
|
|
name: 'test user',
|
|
email: 'test-leo@example.com',
|
|
password: 'thisissupersafe',
|
|
blogTitle: 'a test blog'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(403);
|
|
});
|
|
|
|
it('update setup', async function () {
|
|
await framework.initFixtures();
|
|
await request.loginAsOwner();
|
|
|
|
const res = await request
|
|
.put('authentication/setup')
|
|
.send({
|
|
setup: [{
|
|
name: 'test user edit',
|
|
email: 'test-edit@example.com',
|
|
password: 'thisissupersafe',
|
|
blogTitle: 'a test blog'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot({
|
|
users: [{
|
|
created_at: any(String),
|
|
last_seen: any(String),
|
|
updated_at: any(String)
|
|
}]
|
|
});
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Invitation', function () {
|
|
before(async function () {
|
|
request = await framework.getAgent('/ghost/api/canary/admin/');
|
|
// NOTE: this order of fixture initialization boggles me. Ideally should not depend on agent/login sequence
|
|
await framework.initFixtures('invites');
|
|
await request.loginAsOwner();
|
|
});
|
|
|
|
after(async function () {
|
|
await framework.resetDb();
|
|
});
|
|
|
|
it('check invite with invalid email', function () {
|
|
return request
|
|
.get('authentication/invitation?email=invalidemail')
|
|
.expect('Content-Type', /json/)
|
|
.expect(400);
|
|
});
|
|
|
|
it('check valid invite', async function () {
|
|
const res = await request
|
|
.get(`authentication/invitation?email=${testUtils.DataGenerator.forKnex.invites[0].email}`)
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
});
|
|
|
|
it('check invalid invite', async function () {
|
|
const res = await request
|
|
.get(`authentication/invitation?email=notinvited@example.org`)
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
});
|
|
|
|
it('try to accept without invite', function () {
|
|
return request
|
|
.post('authentication/invitation')
|
|
.send({
|
|
invitation: [{
|
|
token: 'lul11111',
|
|
password: 'lel123456',
|
|
email: 'not-invited@example.org',
|
|
name: 'not invited'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(404);
|
|
});
|
|
|
|
it('try to accept with invite and existing email address', function () {
|
|
return request
|
|
.post('authentication/invitation')
|
|
.send({
|
|
invitation: [{
|
|
token: testUtils.DataGenerator.forKnex.invites[0].token,
|
|
password: '12345678910',
|
|
email: testUtils.DataGenerator.forKnex.users[0].email,
|
|
name: 'invited'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(422);
|
|
});
|
|
|
|
it('try to accept with invite', async function () {
|
|
const res = await request
|
|
.post('authentication/invitation')
|
|
.send({
|
|
invitation: [{
|
|
token: testUtils.DataGenerator.forKnex.invites[0].token,
|
|
password: '12345678910',
|
|
email: testUtils.DataGenerator.forKnex.invites[0].email,
|
|
name: 'invited'
|
|
}]
|
|
})
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('Password reset', function () {
|
|
const user = testUtils.DataGenerator.forModel.users[0];
|
|
|
|
before(async function () {
|
|
request = await framework.getAgent('/ghost/api/canary/admin/');
|
|
// NOTE: this order of fixture initialization boggles me. Ideally should not depend on agent/login sequence
|
|
await framework.initFixtures('invites');
|
|
await request.loginAsOwner();
|
|
});
|
|
|
|
after(async function () {
|
|
await framework.resetDb();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
emailStub = framework.stubMail();
|
|
});
|
|
|
|
afterEach(function () {
|
|
framework.restoreMocks();
|
|
});
|
|
|
|
it('reset password', async function () {
|
|
const ownerUser = await models.User.getOwnerUser(testUtils.context.internal);
|
|
|
|
const token = security.tokens.resetToken.generateHash({
|
|
expires: Date.now() + (1000 * 60),
|
|
email: user.email,
|
|
dbHash: settingsCache.get('db_hash'),
|
|
password: ownerUser.get('password')
|
|
});
|
|
|
|
const res = await request.put('authentication/passwordreset')
|
|
.set('Accept', 'application/json')
|
|
.send({
|
|
passwordreset: [{
|
|
token: token,
|
|
newPassword: 'thisissupersafe',
|
|
ne2Password: 'thisissupersafe'
|
|
}]
|
|
})
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('reset password: invalid token', async function () {
|
|
const res = await request
|
|
.put('authentication/passwordreset')
|
|
.set('Accept', 'application/json')
|
|
.send({
|
|
passwordreset: [{
|
|
token: 'invalid',
|
|
newPassword: 'thisissupersafe',
|
|
ne2Password: 'thisissupersafe'
|
|
}]
|
|
})
|
|
.expect(401);
|
|
|
|
expect(res.body).to.matchSnapshot({
|
|
errors: [{
|
|
id: any(String)
|
|
}]
|
|
});
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('reset password: expired token', async function () {
|
|
const ownerUser = await models.User.getOwnerUser(testUtils.context.internal);
|
|
|
|
const dateInThePast = Date.now() - (1000 * 60);
|
|
const token = security.tokens.resetToken.generateHash({
|
|
expires: dateInThePast,
|
|
email: user.email,
|
|
dbHash: settingsCache.get('db_hash'),
|
|
password: ownerUser.get('password')
|
|
});
|
|
|
|
const res = await request
|
|
.put('authentication/passwordreset')
|
|
.set('Accept', 'application/json')
|
|
.send({
|
|
passwordreset: [{
|
|
token: token,
|
|
newPassword: 'thisissupersafe',
|
|
ne2Password: 'thisissupersafe'
|
|
}]
|
|
})
|
|
.expect(400);
|
|
|
|
expect(res.body).to.matchSnapshot({
|
|
errors: [{
|
|
id: any(String)
|
|
}]
|
|
});
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('reset password: unmatched token', async function () {
|
|
const token = security.tokens.resetToken.generateHash({
|
|
expires: Date.now() + (1000 * 60),
|
|
email: user.email,
|
|
dbHash: settingsCache.get('db_hash'),
|
|
password: 'invalid_password'
|
|
});
|
|
|
|
const res = await request
|
|
.put('authentication/passwordreset')
|
|
.set('Accept', 'application/json')
|
|
.send({
|
|
passwordreset: [{
|
|
token: token,
|
|
newPassword: 'thisissupersafe',
|
|
ne2Password: 'thisissupersafe'
|
|
}]
|
|
})
|
|
.expect(400);
|
|
|
|
expect(res.body).to.matchSnapshot({
|
|
errors: [{
|
|
id: any(String)
|
|
}]
|
|
});
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
|
|
it('reset password: generate reset token', async function () {
|
|
const res = await request
|
|
.post('authentication/passwordreset')
|
|
.set('Accept', 'application/json')
|
|
.send({
|
|
passwordreset: [{
|
|
email: user.email
|
|
}]
|
|
})
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Reset all passwords', function () {
|
|
let sendEmail;
|
|
before(async function () {
|
|
request = await framework.getAgent('/ghost/api/canary/admin/');
|
|
// NOTE: this order of fixture initialization boggles me. Ideally should not depend on agent/login sequence
|
|
await framework.initFixtures('invites');
|
|
await request.loginAsOwner();
|
|
});
|
|
|
|
after(async function () {
|
|
await framework.resetDb();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
emailStub = framework.stubMail();
|
|
});
|
|
|
|
afterEach(function () {
|
|
framework.restoreMocks();
|
|
});
|
|
|
|
it('reset all passwords returns 200', async function () {
|
|
const res = await request.post('authentication/reset_all_passwords')
|
|
.set('Accept', 'application/json')
|
|
.send({})
|
|
.expect(200);
|
|
|
|
expect(res.body).to.matchSnapshot();
|
|
expect(res.headers).to.matchSnapshot({
|
|
date: any(String),
|
|
etag: any(String)
|
|
});
|
|
|
|
// All users locked
|
|
const users = await models.User.fetchAll();
|
|
for (const user of users) {
|
|
expect(user.get('status')).to.equal('locked');
|
|
}
|
|
|
|
// No session left
|
|
const sessions = await models.Session.fetchAll();
|
|
expect(sessions.length).to.equal(0);
|
|
|
|
expect(emailStub.callCount).to.equal(2);
|
|
expect(emailStub.firstCall.args[0].subject).to.equal('Reset Password');
|
|
expect(emailStub.secondCall.args[0].subject).to.equal('Reset Password');
|
|
});
|
|
});
|
|
});
|