0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Merge pull request #5349 from acburdine/onboarding-api

Add PUT route to authentication setup
This commit is contained in:
Hannah Wolfe 2015-06-30 12:03:21 +01:00
commit b8415e8b90
4 changed files with 171 additions and 52 deletions

View file

@ -9,6 +9,45 @@ var _ = require('lodash'),
config = require('../config'), config = require('../config'),
authentication; authentication;
function setupTasks(object) {
var setupUser,
internal = {context: {internal: true}};
return utils.checkObject(object, 'setup').then(function (checkedSetupData) {
setupUser = {
name: checkedSetupData.setup[0].name,
email: checkedSetupData.setup[0].email,
password: checkedSetupData.setup[0].password,
blogTitle: checkedSetupData.setup[0].blogTitle,
status: 'active'
};
return dataProvider.User.findOne({role: 'Owner', status: 'all'});
}).then(function (ownerUser) {
if (ownerUser) {
return dataProvider.User.setup(setupUser, _.extend({id: ownerUser.id}, internal));
} else {
return dataProvider.Role.findOne({name: 'Owner'}).then(function (ownerRole) {
setupUser.roles = [ownerRole.id];
return dataProvider.User.add(setupUser, internal);
});
}
}).then(function (user) {
var userSettings = [];
// Handles the additional values set by the setup screen.
if (!_.isEmpty(setupUser.blogTitle)) {
userSettings.push({key: 'title', value: setupUser.blogTitle});
userSettings.push({key: 'description', value: 'Thoughts, stories and ideas.'});
}
setupUser = user.toJSON(internal);
return settings.edit({settings: userSettings}, {context: {user: setupUser.id}});
}).then(function () {
return Promise.resolve(setupUser);
});
}
/** /**
* ## Authentication API Methods * ## Authentication API Methods
* *
@ -153,7 +192,7 @@ authentication = {
* @param {string} options.email The email to check for an invitation on * @param {string} options.email The email to check for an invitation on
* @returns {Promise(Invitation}} An invitation status * @returns {Promise(Invitation}} An invitation status
*/ */
isInvitation: function (options) { isInvitation: function isInvitation(options) {
return authentication.isSetup().then(function (result) { return authentication.isSetup().then(function (result) {
var setup = result.setup[0].status; var setup = result.setup[0].status;
@ -175,7 +214,7 @@ authentication = {
}); });
}, },
isSetup: function () { isSetup: function isSetup() {
return dataProvider.User.query(function (qb) { return dataProvider.User.query(function (qb) {
qb.whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']); qb.whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']);
}).fetch().then(function (users) { }).fetch().then(function (users) {
@ -187,9 +226,8 @@ authentication = {
}); });
}, },
setup: function (object) { setup: function setup(object) {
var setupUser, var setupUser;
internal = {context: {internal: true}};
return authentication.isSetup().then(function (result) { return authentication.isSetup().then(function (result) {
var setup = result.setup[0].status; var setup = result.setup[0].status;
@ -198,37 +236,10 @@ authentication = {
return Promise.reject(new errors.NoPermissionError('Setup has already been completed.')); return Promise.reject(new errors.NoPermissionError('Setup has already been completed.'));
} }
return utils.checkObject(object, 'setup'); return setupTasks(object);
}).then(function (checkedSetupData) { }).then(function (result) {
setupUser = { setupUser = result;
name: checkedSetupData.setup[0].name,
email: checkedSetupData.setup[0].email,
password: checkedSetupData.setup[0].password,
blogTitle: checkedSetupData.setup[0].blogTitle,
status: 'active'
};
return dataProvider.User.findOne({role: 'Owner', status: 'all'});
}).then(function (ownerUser) {
if (ownerUser) {
return dataProvider.User.setup(setupUser, _.extend({id: ownerUser.id}, internal));
} else {
return dataProvider.Role.findOne({name: 'Owner'}).then(function (ownerRole) {
setupUser.roles = [ownerRole.id];
return dataProvider.User.add(setupUser, internal);
});
}
}).then(function (user) {
var userSettings = [];
// Handles the additional values set by the setup screen.
if (!_.isEmpty(setupUser.blogTitle)) {
userSettings.push({key: 'title', value: setupUser.blogTitle});
userSettings.push({key: 'description', value: 'Thoughts, stories and ideas.'});
}
setupUser = user.toJSON(internal);
return settings.edit({settings: userSettings}, {context: {user: setupUser.id}});
}).then(function () {
var data = { var data = {
ownerEmail: setupUser.email ownerEmail: setupUser.email
}; };
@ -260,22 +271,21 @@ authentication = {
}); });
}, },
revoke: function (object) { updateSetup: function updateSetup(object, options) {
var token; if (!options.context || !options.context.user) {
return Promise.reject(new errors.NoPermissionError('You are not logged in.'));
if (object.token_type_hint && object.token_type_hint === 'access_token') {
token = dataProvider.Accesstoken;
} else if (object.token_type_hint && object.token_type_hint === 'refresh_token') {
token = dataProvider.Refreshtoken;
} else {
return errors.BadRequestError('Invalid token_type_hint given.');
} }
return token.destroyByToken({token: object.token}).then(function () { return dataProvider.User.findOne({role: 'Owner', status: 'all'}).then(function (result) {
return Promise.resolve({token: object.token}); var user = result.toJSON();
}, function () {
// On error we still want a 200. See https://tools.ietf.org/html/rfc7009#page-5 if (user.id !== options.context.user) {
return Promise.resolve({token: object.token, error: 'Invalid token provided'}); return Promise.reject(new errors.NoPermissionError('You are not the blog owner.'));
}
return setupTasks(object);
}).then(function (result) {
return Promise.resolve({users: [result]});
}); });
} }
}; };

View file

@ -111,7 +111,8 @@ middleware = {
}); });
if (subPath.indexOf('/ghost/api/') === 0 if (subPath.indexOf('/ghost/api/') === 0
&& path.indexOf('/ghost/api/v0.1/authentication/') !== 0) { && (path.indexOf('/ghost/api/v0.1/authentication/') !== 0
|| (path.indexOf('/ghost/api/v0.1/authentication/') === 0 && req.method === 'PUT'))) {
return passport.authenticate('bearer', {session: false, failWithError: true}, return passport.authenticate('bearer', {session: false, failWithError: true},
function authenticate(err, user, info) { function authenticate(err, user, info) {
if (err) { if (err) {

View file

@ -77,6 +77,7 @@ apiRoutes = function apiRoutes(middleware) {
router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation)); router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation));
router.get('/authentication/invitation', api.http(api.authentication.isInvitation)); router.get('/authentication/invitation', api.http(api.authentication.isInvitation));
router.post('/authentication/setup', api.http(api.authentication.setup)); router.post('/authentication/setup', api.http(api.authentication.setup));
router.put('/authentication/setup', api.http(api.authentication.updateSetup));
router.get('/authentication/setup', api.http(api.authentication.isSetup)); router.get('/authentication/setup', api.http(api.authentication.isSetup));
router.post('/authentication/token', router.post('/authentication/token',
middleware.spamPrevention.signin, middleware.spamPrevention.signin,

View file

@ -7,7 +7,8 @@ var testUtils = require('../../utils'),
// Stuff we are testing // Stuff we are testing
mail = rewire('../../../server/api/mail'), mail = rewire('../../../server/api/mail'),
AuthAPI = require('../../../server/api/authentication'); AuthAPI = require('../../../server/api/authentication'),
context = testUtils.context;
describe('Authentication API', function () { describe('Authentication API', function () {
// Keep the DB clean // Keep the DB clean
@ -81,7 +82,7 @@ describe('Authentication API', function () {
name: 'test user', name: 'test user',
email: 'test@example.com', email: 'test@example.com',
password: 'areallygoodpassword', password: 'areallygoodpassword',
title: 'a test blog' blogTitle: 'a test blog'
}; };
AuthAPI.setup({setup: [setupData]}).then(function () { AuthAPI.setup({setup: [setupData]}).then(function () {
@ -98,6 +99,112 @@ describe('Authentication API', function () {
}); });
}); });
describe('Setup Update', function () {
describe('Setup not complete', function () {
beforeEach(testUtils.setup('roles', 'owner:pre', 'settings', 'perms:setting', 'perms:init'));
it('should report that setup has not been completed', function (done) {
AuthAPI.isSetup().then(function (result) {
should.exist(result);
result.setup[0].status.should.be.false;
done();
}).catch(done);
});
it('should not allow setup to be updated', function (done) {
var setupData = {
name: 'test user',
email: 'test@example.com',
password: 'areallygoodpassword',
blogTitle: 'a test blog'
};
AuthAPI.updateSetup({setup: [setupData]}, {}).then(function () {
done(new Error('Update was able to be run'));
}).catch(function (err) {
should.exist(err);
err.name.should.equal('NoPermissionError');
err.code.should.equal(403);
done();
});
});
});
describe('Not Owner', function () {
beforeEach(testUtils.setup('roles', 'users:roles', 'settings', 'perms:setting', 'perms:init', 'perms:user'));
it('should report that setup has been completed', function (done) {
AuthAPI.isSetup().then(function (result) {
should.exist(result);
result.setup[0].status.should.be.true;
done();
}).catch(done);
});
it('should not allow setup to be updated', function (done) {
var setupData = {
name: 'test user',
email: 'test@example.com',
password: 'areallygoodpassword',
blogTitle: 'a test blog'
};
AuthAPI.updateSetup({setup: [setupData]}, context.author).then(function () {
done(new Error('Update was able to be run'));
}).catch(function (err) {
should.exist(err);
err.name.should.equal('NoPermissionError');
err.code.should.equal(403);
done();
});
});
});
describe('Owner', function () {
beforeEach(testUtils.setup('roles', 'users:roles', 'settings', 'perms:setting', 'perms:init'));
it('should report that setup has been completed', function (done) {
AuthAPI.isSetup().then(function (result) {
should.exist(result);
result.setup[0].status.should.be.true;
done();
}).catch(done);
});
it('should allow setup to be updated', function (done) {
var setupData = {
name: 'test user',
email: 'test@example.com',
password: 'areallygoodpassword',
blogTitle: 'a test blog'
};
AuthAPI.updateSetup({setup: [setupData]}, context.owner).then(function (result) {
should.exist(result);
should.exist(result.users);
should.not.exist(result.meta);
result.users.should.have.length(1);
testUtils.API.checkResponse(result.users[0], 'user');
var newUser = result.users[0];
newUser.id.should.equal(1);
newUser.name.should.equal(setupData.name);
newUser.email.should.equal(setupData.email);
done();
}).catch(done);
});
});
});
// describe('Authentication', function () { // describe('Authentication', function () {
// describe('Setup not completed', function () { // describe('Setup not completed', function () {