mirror of https://github.com/TryGhost/Ghost.git
Move setup to API
closes #3136 - moved setup to authentication API - added `POST /ghost/api/v0.1/authentication/setup` to execute the setup process - added `GET /ghost/api/v0.1/authentication/setup` to check if blog is already set up (needed for #3145) - removed unused methods from api/users.js
This commit is contained in:
parent
2658e8ea13
commit
8c2258dc4c
|
@ -13,16 +13,24 @@ var SetupController = Ember.ObjectController.extend(ValidationEngine, {
|
|||
|
||||
actions: {
|
||||
setup: function () {
|
||||
var self = this;
|
||||
var self = this,
|
||||
data = self.getProperties('blogTitle', 'name', 'email', 'password');
|
||||
|
||||
self.notifications.closePassive();
|
||||
|
||||
this.toggleProperty('submitting');
|
||||
this.validate({ format: false }).then(function () {
|
||||
ajax({
|
||||
url: self.get('ghostPaths').adminUrl('setup'),
|
||||
url: self.get('ghostPaths').apiUrl('authentication', 'setup'),
|
||||
type: 'POST',
|
||||
data: self.getProperties('blogTitle', 'name', 'email', 'password')
|
||||
data: {
|
||||
setup: [{
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
password: data.password,
|
||||
blogTitle: data.blogTitle
|
||||
}]
|
||||
}
|
||||
}).then(function () {
|
||||
self.get('session').authenticate('ember-simple-auth-authenticator:oauth2-password-grant', {
|
||||
identification: self.get('email'),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var dataProvider = require('../models'),
|
||||
var _ = require('lodash'),
|
||||
dataProvider = require('../models'),
|
||||
settings = require('./settings'),
|
||||
mail = require('./mail'),
|
||||
utils = require('./utils'),
|
||||
|
@ -123,6 +124,84 @@ authentication = {
|
|||
return when.reject(new errors.UnauthorizedError(error.message));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
isSetup: function () {
|
||||
return dataProvider.User.findOne({status: 'active'}).then(function (user) {
|
||||
if (user) {
|
||||
return when.resolve({ setup: [{status: true}]});
|
||||
} else {
|
||||
return when.resolve({ setup: [{status: false}]});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setup: function (object) {
|
||||
var setupUser;
|
||||
|
||||
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.findAll();
|
||||
}).then(function (users) {
|
||||
if (users.length > 0) {
|
||||
return dataProvider.User.setup(setupUser, {id: 1});
|
||||
} else {
|
||||
// TODO: needs to pass owner role when role endpoint is finished!
|
||||
return dataProvider.User.add(setupUser);
|
||||
}
|
||||
}).then(function (user) {
|
||||
var userSettings = [];
|
||||
|
||||
userSettings.push({key: 'email', value: setupUser.email});
|
||||
|
||||
// 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 by ' + setupUser.name});
|
||||
}
|
||||
setupUser = user.toJSON();
|
||||
return settings.edit({settings: userSettings}, {context: {user: 1}});
|
||||
}).then(function () {
|
||||
var message = {
|
||||
to: setupUser.email,
|
||||
subject: 'Your New Ghost Blog',
|
||||
html: '<p><strong>Hello!</strong></p>' +
|
||||
'<p>Good news! You\'ve successfully created a brand new Ghost blog over on ' + config().url + '</p>' +
|
||||
'<p>You can log in to your admin account with the following details:</p>' +
|
||||
'<p> Email Address: ' + setupUser.email + '<br>' +
|
||||
'Password: The password you chose when you signed up</p>' +
|
||||
'<p>Keep this email somewhere safe for future reference, and have fun!</p>' +
|
||||
'<p>xoxo</p>' +
|
||||
'<p>Team Ghost<br>' +
|
||||
'<a href="https://ghost.org">https://ghost.org</a></p>'
|
||||
},
|
||||
payload = {
|
||||
mail: [{
|
||||
message: message,
|
||||
options: {}
|
||||
}]
|
||||
};
|
||||
|
||||
return mail.send(payload).otherwise(function (error) {
|
||||
errors.logError(
|
||||
error.message,
|
||||
"Unable to send welcome email, your blog will continue to function.",
|
||||
"Please see http://docs.ghost.org/mail/ for instructions on configuring email."
|
||||
);
|
||||
});
|
||||
}).then(function () {
|
||||
return when.resolve({ users: [setupUser]});
|
||||
}).otherwise(function (error) {
|
||||
console.log('error');
|
||||
console.log(error);
|
||||
return when.reject(new errors.UnauthorizedError(error.message));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -110,37 +110,6 @@ users = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* ### Add
|
||||
* @param {User} object the user to create
|
||||
* @param {{context}} options
|
||||
* @returns {Promise(User}} Newly created user
|
||||
*/
|
||||
// TODO: remove and rename invite to add when setup is implemented
|
||||
add: function add(object, options) {
|
||||
options = options || {};
|
||||
|
||||
return canThis(options.context).add.user().then(function () {
|
||||
return utils.checkObject(object, docName).then(function (checkedUserData) {
|
||||
// if the user is created by users.register(), use id: 1 as the creator for now
|
||||
if (options.include) {
|
||||
options.include = prepareInclude(options.include);
|
||||
}
|
||||
|
||||
if (options.context.internal) {
|
||||
options.context.user = 1;
|
||||
}
|
||||
|
||||
return dataProvider.User.add(checkedUserData.users[0], options);
|
||||
}).then(function (result) {
|
||||
if (result) {
|
||||
return { users: [result.toJSON()]};
|
||||
}
|
||||
});
|
||||
}, function () {
|
||||
return when.reject(new errors.NoPermissionError('You do not have permission to add a users.'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* ### Destroy
|
||||
* @param {{id, context}} options
|
||||
|
@ -159,11 +128,12 @@ users = {
|
|||
},
|
||||
|
||||
/**
|
||||
* ### Invite user
|
||||
* ### Add user
|
||||
* The newly added user is invited to join the blog via email.
|
||||
* @param {User} object the user to create
|
||||
* @returns {Promise(User}} Newly created user
|
||||
*/
|
||||
invite: function invite(object, options) {
|
||||
add: function add(object, options) {
|
||||
var newUser,
|
||||
user;
|
||||
|
||||
|
@ -236,31 +206,6 @@ users = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* ### Register
|
||||
* Allow to register a user using the API without beeing authenticated in. Needed to set up the first user.
|
||||
* @param {User} object the user to create
|
||||
* @returns {Promise(User}} Newly created user
|
||||
*/
|
||||
// TODO: update when setup is moved
|
||||
register: function register(object) {
|
||||
var newUser;
|
||||
|
||||
return utils.checkObject(object, docName).then(function (checkedUserData) {
|
||||
newUser = checkedUserData.users[0];
|
||||
return dataProvider.User.findAll();
|
||||
}).then(function (users) {
|
||||
if (users.length > 0) {
|
||||
return dataProvider.User.setup(newUser, {id: 1});
|
||||
} else {
|
||||
// TODO: needs to pass owner role when role endpoint is finished!
|
||||
return dataProvider.User.add(newUser);
|
||||
}
|
||||
}).then(function (user) {
|
||||
return { users: [user.toJSON()]};
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* ### Change Password
|
||||
* @param {password} object
|
||||
|
@ -284,45 +229,6 @@ users = {
|
|||
});
|
||||
},
|
||||
|
||||
// TODO: remove when old admin is removed, functionality lives now in api/authentication
|
||||
generateResetToken: function generateResetToken(email) {
|
||||
var expires = Date.now() + ONE_DAY;
|
||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||
var dbHash = response.settings[0].value;
|
||||
return dataProvider.User.generateResetToken(email, expires, dbHash);
|
||||
});
|
||||
},
|
||||
|
||||
// TODO: remove when old admin is removed -> not needed anymore
|
||||
validateToken: function validateToken(token) {
|
||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||
var dbHash = response.settings[0].value;
|
||||
return dataProvider.User.validateToken(token, dbHash);
|
||||
});
|
||||
},
|
||||
|
||||
// TODO: remove when old admin is removed, functionality lives now in api/authentication
|
||||
resetPassword: function resetPassword(token, newPassword, ne2Password) {
|
||||
return settings.read({context: {internal: true}, key: 'dbHash'}).then(function (response) {
|
||||
var dbHash = response.settings[0].value;
|
||||
return dataProvider.User.resetPassword(token, newPassword, ne2Password, dbHash);
|
||||
});
|
||||
},
|
||||
|
||||
// TODO: move to authentication endpoint with issue #3136
|
||||
doesUserExist: function doesUserExist() {
|
||||
return dataProvider.User.findAll().then(function (users) {
|
||||
if (users.length > 0) {
|
||||
var activeUsers = _.remove(users.toJSON(), function (user) {
|
||||
return user.status !== 'inactive';
|
||||
});
|
||||
if (activeUsers.length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = users;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
var config = require('../config'),
|
||||
_ = require('lodash'),
|
||||
path = require('path'),
|
||||
when = require('when'),
|
||||
api = require('../api'),
|
||||
errors = require('../errors'),
|
||||
storage = require('../storage'),
|
||||
updateCheck = require('../update-check'),
|
||||
|
@ -56,70 +54,6 @@ adminControllers = {
|
|||
errors.logError(e);
|
||||
return res.send(500, e.message);
|
||||
});
|
||||
},
|
||||
|
||||
// Route: doSignup
|
||||
// Path: /ghost/setup/
|
||||
// Method: POST
|
||||
'doSetup': function (req, res) {
|
||||
var name = req.body.name,
|
||||
email = req.body.email,
|
||||
password = req.body.password,
|
||||
blogTitle = req.body.blogTitle,
|
||||
users = [{
|
||||
name: name,
|
||||
email: email,
|
||||
password: password,
|
||||
status: 'active'
|
||||
}];
|
||||
|
||||
api.users.register({users: users}).then(function () {
|
||||
var settings = [];
|
||||
|
||||
settings.push({key: 'email', value: email});
|
||||
|
||||
// Handles the additional values set by the setup screen.
|
||||
if (!_.isEmpty(blogTitle)) {
|
||||
settings.push({key: 'title', value: blogTitle});
|
||||
settings.push({key: 'description', value: 'Thoughts, stories and ideas by ' + name});
|
||||
}
|
||||
|
||||
api.settings.edit({settings: settings}, {context: {user: 1}}).then(function () {
|
||||
var message = {
|
||||
to: email,
|
||||
subject: 'Your New Ghost Blog',
|
||||
html: '<p><strong>Hello!</strong></p>' +
|
||||
'<p>Good news! You\'ve successfully created a brand new Ghost blog over on ' + config().url + '</p>' +
|
||||
'<p>You can log in to your admin account with the following details:</p>' +
|
||||
'<p> Email Address: ' + email + '<br>' +
|
||||
'Password: The password you chose when you signed up</p>' +
|
||||
'<p>Keep this email somewhere safe for future reference, and have fun!</p>' +
|
||||
'<p>xoxo</p>' +
|
||||
'<p>Team Ghost<br>' +
|
||||
'<a href="https://ghost.org">https://ghost.org</a></p>'
|
||||
},
|
||||
payload = {
|
||||
mail: [{
|
||||
message: message,
|
||||
options: {}
|
||||
}]
|
||||
};
|
||||
|
||||
api.mail.send(payload).otherwise(function (error) {
|
||||
errors.logError(
|
||||
error.message,
|
||||
"Unable to send welcome email, your blog will continue to function.",
|
||||
"Please see http://docs.ghost.org/mail/ for instructions on configuring email."
|
||||
);
|
||||
});
|
||||
res.json(200, {
|
||||
redirect: config().paths.subdir + '/ghost/'
|
||||
});
|
||||
|
||||
});
|
||||
}).otherwise(function (error) {
|
||||
res.json(401, {error: error.message});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -140,8 +140,8 @@ function updateActiveTheme(req, res, next) {
|
|||
function redirectToSetup(req, res, next) {
|
||||
/*jslint unparam:true*/
|
||||
|
||||
api.users.doesUserExist().then(function (exists) {
|
||||
if (!exists && !req.path.match(/\/ghost\/setup\//)) {
|
||||
api.authentication.isSetup().then(function (exists) {
|
||||
if (!exists.setup[0].status && !req.path.match(/\/ghost\/setup\//)) {
|
||||
return res.redirect(config().paths.subdir + '/ghost/setup/');
|
||||
}
|
||||
next();
|
||||
|
|
|
@ -192,10 +192,11 @@ User = ghostBookshelf.Model.extend({
|
|||
|
||||
setup: function (data, options) {
|
||||
var self = this,
|
||||
// Clone the _user so we don't expose the hashed password unnecessarily
|
||||
userData = this.filterData(data);
|
||||
|
||||
options = this.filterOptions(options, 'setup');
|
||||
options.withRelated = _.union([ 'roles' ], options.include);
|
||||
|
||||
return validatePasswordLength(userData.password).then(function () {
|
||||
// Generate a new password hash
|
||||
return generatePasswordHash(data.password);
|
||||
|
|
|
@ -33,7 +33,6 @@ adminRoutes = function (middleware) {
|
|||
res.redirect(301, subdir + '/ghost/signup/');
|
||||
});
|
||||
|
||||
router.post('/ghost/setup/', admin.doSetup);
|
||||
router.post('/ghost/upload/', middleware.busboy, admin.upload);
|
||||
|
||||
// redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
|
||||
|
|
|
@ -28,7 +28,7 @@ apiRoutes = function (middleware) {
|
|||
router.get('/users/email/:email', api.http(api.users.read));
|
||||
router.put('/users/password', api.http(api.users.changePassword));
|
||||
router.put('/users/:id', api.http(api.users.edit));
|
||||
router.post('/users', api.http(api.users.invite));
|
||||
router.post('/users', api.http(api.users.add));
|
||||
router.del('/users/:id', api.http(api.users.destroy));
|
||||
|
||||
// ## Tags
|
||||
|
@ -70,6 +70,8 @@ apiRoutes = function (middleware) {
|
|||
router.post('/authentication/passwordreset', api.http(api.authentication.generateResetToken));
|
||||
router.put('/authentication/passwordreset', api.http(api.authentication.resetPassword));
|
||||
router.post('/authentication/invitation', api.http(api.authentication.acceptInvitation));
|
||||
router.post('/authentication/setup', api.http(api.authentication.setup));
|
||||
router.get('/authentication/setup', api.http(api.authentication.isSetup));
|
||||
router.post('/authentication/token',
|
||||
middleware.addClientSecret,
|
||||
middleware.authenticateClient,
|
||||
|
|
|
@ -7,6 +7,7 @@ var testUtils = require('../../utils'),
|
|||
|
||||
// Stuff we are testing
|
||||
UsersAPI = require('../../../server/api/users');
|
||||
AuthAPI = require('../../../server/api/authentication');
|
||||
|
||||
describe('Users API', function () {
|
||||
|
||||
|
@ -32,7 +33,7 @@ describe('Users API', function () {
|
|||
});
|
||||
|
||||
it('can add with internal user', function (done) {
|
||||
UsersAPI.register({ users: [{
|
||||
AuthAPI.setup({ setup: [{
|
||||
'name': 'Hello World',
|
||||
'email': 'hello@world.com',
|
||||
'password': 'password'
|
||||
|
|
Loading…
Reference in New Issue