2019-07-17 17:43:07 +03:00
|
|
|
const should = require('should');
|
2019-07-30 15:44:56 +03:00
|
|
|
const sinon = require('sinon');
|
2019-07-17 17:43:07 +03:00
|
|
|
const supertest = require('supertest');
|
|
|
|
const localUtils = require('./utils');
|
2019-07-30 23:48:59 +03:00
|
|
|
const testUtils = require('../../../../utils/index');
|
2020-03-30 18:26:47 +03:00
|
|
|
const models = require('../../../../../core/server/models/index');
|
2020-08-11 16:01:16 +03:00
|
|
|
const security = require('@tryghost/security');
|
2021-06-30 16:56:57 +03:00
|
|
|
const settingsCache = require('../../../../../core/shared/settings-cache');
|
2020-05-27 20:47:53 +03:00
|
|
|
const config = require('../../../../../core/shared/config/index');
|
2020-03-30 18:26:47 +03:00
|
|
|
const mailService = require('../../../../../core/server/services/mail/index');
|
2019-08-20 13:13:43 +03:00
|
|
|
const configUtils = require('../../../../utils/configUtils');
|
2019-07-17 17:43:07 +03:00
|
|
|
|
|
|
|
let ghost = testUtils.startGhost;
|
|
|
|
let request;
|
|
|
|
|
2019-07-30 23:48:59 +03:00
|
|
|
describe('Authentication API v2', function () {
|
2019-07-25 18:10:46 +03:00
|
|
|
let ghostServer;
|
2019-07-17 17:43:07 +03:00
|
|
|
|
2019-08-20 13:13:43 +03:00
|
|
|
describe('Blog setup: default config', function () {
|
2019-07-17 17:43:07 +03:00
|
|
|
before(function () {
|
|
|
|
return ghost({forceStart: true})
|
|
|
|
.then(function (_ghostServer) {
|
|
|
|
ghostServer = _ghostServer;
|
|
|
|
request = supertest.agent(config.get('url'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-07-30 17:09:54 +03:00
|
|
|
beforeEach(function () {
|
|
|
|
sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
2019-07-17 17:43:07 +03:00
|
|
|
it('is setup? no', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.setup[0].status.should.be.false();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('complete setup', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
setup: [{
|
|
|
|
name: 'test user',
|
|
|
|
email: 'test@example.com',
|
|
|
|
password: 'thisissupersafe',
|
|
|
|
blogTitle: 'a test blog'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(201)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.users);
|
|
|
|
should.not.exist(jsonResponse.meta);
|
|
|
|
|
|
|
|
jsonResponse.users.should.have.length(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.users[0], 'user');
|
|
|
|
|
|
|
|
const newUser = jsonResponse.users[0];
|
|
|
|
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
|
|
|
newUser.name.should.equal('test user');
|
|
|
|
newUser.email.should.equal('test@example.com');
|
2019-07-30 15:44:56 +03:00
|
|
|
|
|
|
|
mailService.GhostMailer.prototype.send.called.should.be.true();
|
|
|
|
mailService.GhostMailer.prototype.send.args[0][0].to.should.equal('test@example.com');
|
2019-07-17 17:43:07 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-08-20 13:13:43 +03:00
|
|
|
it('is setup? yes', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.setup[0].status.should.be.true();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('complete setup again', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.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', function () {
|
|
|
|
return localUtils.doAuth(request)
|
|
|
|
.then(() => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
setup: [{
|
|
|
|
name: 'test user edit',
|
|
|
|
email: 'test-edit@example.com',
|
|
|
|
password: 'thisissupersafe',
|
|
|
|
blogTitle: 'a test blog'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.users);
|
|
|
|
should.not.exist(jsonResponse.meta);
|
|
|
|
|
|
|
|
jsonResponse.users.should.have.length(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.users[0], 'user');
|
|
|
|
|
|
|
|
const newUser = jsonResponse.users[0];
|
|
|
|
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
|
|
|
newUser.name.should.equal('test user edit');
|
|
|
|
newUser.email.should.equal('test-edit@example.com');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('Blog setup: custom config', function () {
|
|
|
|
before(function () {
|
|
|
|
return ghost({forceStart: true})
|
|
|
|
.then(function (_ghostServer) {
|
|
|
|
ghostServer = _ghostServer;
|
|
|
|
request = supertest.agent(config.get('url'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function () {
|
|
|
|
configUtils.set({
|
|
|
|
sendWelcomeEmail: false // Default value is false in pro
|
|
|
|
});
|
|
|
|
sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
configUtils.restore();
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('is setup? no', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.setup[0].status.should.be.false();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('complete setup', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
setup: [{
|
|
|
|
name: 'test user',
|
|
|
|
email: 'test@example.com',
|
|
|
|
password: 'thisissupersafe',
|
|
|
|
blogTitle: 'a test blog'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(201)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.users);
|
|
|
|
should.not.exist(jsonResponse.meta);
|
|
|
|
|
|
|
|
jsonResponse.users.should.have.length(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.users[0], 'user');
|
|
|
|
|
|
|
|
const newUser = jsonResponse.users[0];
|
|
|
|
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
|
|
|
newUser.name.should.equal('test user');
|
|
|
|
newUser.email.should.equal('test@example.com');
|
|
|
|
|
|
|
|
mailService.GhostMailer.prototype.send.called.should.be.false();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-07-17 17:43:07 +03:00
|
|
|
it('is setup? yes', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.setup[0].status.should.be.true();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('complete setup again', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
setup: [{
|
|
|
|
name: 'test user',
|
|
|
|
email: 'test-leo@example.com',
|
|
|
|
password: 'thisissupersafe',
|
|
|
|
blogTitle: 'a test blog'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(403);
|
|
|
|
});
|
2019-07-25 18:10:46 +03:00
|
|
|
|
|
|
|
it('update setup', function () {
|
|
|
|
return localUtils.doAuth(request)
|
|
|
|
.then(() => {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('authentication/setup'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
setup: [{
|
|
|
|
name: 'test user edit',
|
|
|
|
email: 'test-edit@example.com',
|
|
|
|
password: 'thisissupersafe',
|
|
|
|
blogTitle: 'a test blog'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200);
|
|
|
|
})
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.users);
|
|
|
|
should.not.exist(jsonResponse.meta);
|
|
|
|
|
|
|
|
jsonResponse.users.should.have.length(1);
|
|
|
|
localUtils.API.checkResponse(jsonResponse.users[0], 'user');
|
|
|
|
|
|
|
|
const newUser = jsonResponse.users[0];
|
|
|
|
newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
|
|
|
|
newUser.name.should.equal('test user edit');
|
|
|
|
newUser.email.should.equal('test-edit@example.com');
|
|
|
|
});
|
|
|
|
});
|
2019-07-17 17:43:07 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('Invitation', function () {
|
|
|
|
before(function () {
|
|
|
|
return ghost()
|
|
|
|
.then(function (_ghostServer) {
|
|
|
|
ghostServer = _ghostServer;
|
|
|
|
request = supertest.agent(config.get('url'));
|
|
|
|
|
|
|
|
// simulates blog setup (initialises the owner)
|
|
|
|
return localUtils.doAuth(request, 'invites');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-07-24 15:53:09 +03:00
|
|
|
it('check invite with invalid email', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery('authentication/invitation?email=invalidemail'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(400);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('check valid invite', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`authentication/invitation?email=${testUtils.DataGenerator.forKnex.invites[0].email}`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.invitation[0].valid.should.equal(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('check invalid invite', function () {
|
|
|
|
return request
|
|
|
|
.get(localUtils.API.getApiQuery(`authentication/invitation?email=notinvited@example.org`))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.invitation[0].valid.should.equal(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-07-17 17:43:07 +03:00
|
|
|
it('try to accept without invite', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/invitation'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.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', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/invitation'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.send({
|
|
|
|
invitation: [{
|
|
|
|
token: testUtils.DataGenerator.forKnex.invites[0].token,
|
|
|
|
password: '12345678910',
|
|
|
|
email: testUtils.DataGenerator.forKnex.invites[0].email,
|
|
|
|
name: 'invited'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
2019-07-24 13:40:18 +03:00
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
res.body.invitation[0].message.should.equal('Invitation accepted.');
|
|
|
|
});
|
2019-07-17 17:43:07 +03:00
|
|
|
});
|
|
|
|
});
|
2019-07-30 23:48:59 +03:00
|
|
|
|
|
|
|
describe('Password reset', function () {
|
|
|
|
const user = testUtils.DataGenerator.forModel.users[0];
|
|
|
|
|
|
|
|
before(function () {
|
|
|
|
return ghost({forceStart: true})
|
2019-08-19 14:41:09 +03:00
|
|
|
.then(() => {
|
2019-07-30 23:48:59 +03:00
|
|
|
request = supertest.agent(config.get('url'));
|
|
|
|
})
|
|
|
|
.then(() => {
|
|
|
|
return localUtils.doAuth(request);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function () {
|
|
|
|
sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function () {
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('reset password', function (done) {
|
|
|
|
models.User.getOwnerUser(testUtils.context.internal)
|
|
|
|
.then(function (ownerUser) {
|
2020-04-29 18:44:27 +03:00
|
|
|
const token = security.tokens.resetToken.generateHash({
|
2019-07-30 23:48:59 +03:00
|
|
|
expires: Date.now() + (1000 * 60),
|
|
|
|
email: user.email,
|
|
|
|
dbHash: settingsCache.get('db_hash'),
|
|
|
|
password: ownerUser.get('password')
|
|
|
|
});
|
|
|
|
|
|
|
|
request.put(localUtils.API.getApiQuery('authentication/passwordreset'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.send({
|
|
|
|
passwordreset: [{
|
|
|
|
token: token,
|
|
|
|
newPassword: 'thisissupersafe',
|
|
|
|
ne2Password: 'thisissupersafe'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.end(function (err, res) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.passwordreset[0].message);
|
|
|
|
jsonResponse.passwordreset[0].message.should.equal('Password changed successfully.');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch(done);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('reset password: invalid token', function () {
|
|
|
|
return request
|
|
|
|
.put(localUtils.API.getApiQuery('authentication/passwordreset'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.send({
|
|
|
|
passwordreset: [{
|
|
|
|
token: 'invalid',
|
|
|
|
newPassword: 'thisissupersafe',
|
|
|
|
ne2Password: 'thisissupersafe'
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
2020-09-16 05:24:20 +03:00
|
|
|
.expect(401)
|
|
|
|
.then((res) => {
|
|
|
|
should.exist(res.body.errors);
|
|
|
|
res.body.errors[0].type.should.eql('UnauthorizedError');
|
2020-09-22 07:13:57 +03:00
|
|
|
res.body.errors[0].message.should.eql('Cannot reset password.');
|
2020-09-16 05:24:20 +03:00
|
|
|
});
|
2019-07-30 23:48:59 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
it('reset password: generate reset token', function () {
|
|
|
|
return request
|
|
|
|
.post(localUtils.API.getApiQuery('authentication/passwordreset'))
|
|
|
|
.set('Origin', config.get('url'))
|
|
|
|
.set('Accept', 'application/json')
|
|
|
|
.send({
|
|
|
|
passwordreset: [{
|
|
|
|
email: user.email
|
|
|
|
}]
|
|
|
|
})
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect('Cache-Control', testUtils.cacheRules.private)
|
|
|
|
.expect(200)
|
|
|
|
.then((res) => {
|
|
|
|
const jsonResponse = res.body;
|
|
|
|
should.exist(jsonResponse.passwordreset[0].message);
|
|
|
|
jsonResponse.passwordreset[0].message.should.equal('Check your email for further instructions.');
|
|
|
|
mailService.GhostMailer.prototype.send.args[0][0].to.should.equal(user.email);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2019-07-17 17:43:07 +03:00
|
|
|
});
|