From 215badc66388d730904ffc1e68ba6cf0b1feffa2 Mon Sep 17 00:00:00 2001 From: Sebastian Gierlinger Date: Thu, 10 Jul 2014 19:29:51 +0200 Subject: [PATCH] Setup hijacks owner user closes #3074 - user generated by fixture is hijacked - user is updated with name, email, password, slug and status - creates new user if db is migrated but no user exists - previously removed tests are back --- core/server/api/users.js | 19 ++++++++++-- core/server/controllers/admin.js | 5 ++-- core/server/models/user.js | 33 +++++++++++++++++---- core/server/routes/admin.js | 2 +- core/test/functional/client/content_test.js | 18 +++++------ core/test/functional/frontend/feed_test.js | 10 +++---- 6 files changed, 59 insertions(+), 28 deletions(-) diff --git a/core/server/api/users.js b/core/server/api/users.js index 64d1f10fc0..3e6345db47 100644 --- a/core/server/api/users.js +++ b/core/server/api/users.js @@ -242,10 +242,23 @@ users = { * @param {User} object the user to create * @returns {Promise(User}} Newly created user */ - // TODO: remove when setup is implemented + // TODO: update when setup is moved register: function register(object) { - // TODO: if we want to prevent users from being created with the signup form this is the right place to do it - return users.add(object, {context: {internal: true}}); + 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()]}; + }); }, /** diff --git a/core/server/controllers/admin.js b/core/server/controllers/admin.js index 72a05719de..cd0078b518 100644 --- a/core/server/controllers/admin.js +++ b/core/server/controllers/admin.js @@ -61,7 +61,7 @@ adminControllers = { // Route: doSignup // Path: /ghost/setup/ // Method: POST - 'doSignup': function (req, res) { + 'doSetup': function (req, res) { var name = req.body.name, email = req.body.email, password = req.body.password, @@ -69,7 +69,8 @@ adminControllers = { users = [{ name: name, email: email, - password: password + password: password, + status: 'active' }]; api.users.register({users: users}).then(function () { diff --git a/core/server/models/user.js b/core/server/models/user.js index 7e6e3b849c..5cd2012bf1 100644 --- a/core/server/models/user.js +++ b/core/server/models/user.js @@ -96,7 +96,8 @@ User = ghostBookshelf.Model.extend({ findOne: ['withRelated'], findAll: ['withRelated'], add: ['user'], - edit: ['user', 'withRelated'] + setup: ['user', 'id'], + edit: ['user', 'withRelated', 'id'] }; if (validOptions[methodName]) { @@ -160,11 +161,6 @@ User = ghostBookshelf.Model.extend({ options = this.filterOptions(options, 'add'); options.withRelated = _.union([ 'roles' ], options.include); - /** - * This only allows one user to be added to the database, otherwise fails. - * @param {object} user - * @author javorszky - */ return validatePasswordLength(userData.password).then(function () { return self.forge().fetch(); }).then(function () { @@ -194,6 +190,31 @@ 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); + }).then(function (hash) { + // Assign the hashed password + userData.password = hash; + // LookupGravatar + return self.gravatarLookup(userData); + }).then(function (userWithGravatar) { + userData = userWithGravatar; + // Generate a new slug + return ghostBookshelf.Model.generateSlug.call(this, User, userData.name, options); + }).then(function (slug) { + // Assign slug and save the updated user + userData.slug = slug; + return self.edit.call(self, userData, options); + }); + }, + permissable: function (userModelOrId, context, loadedPermissions, hasUserPermission, hasAppPermission) { var self = this, userModel = userModelOrId, diff --git a/core/server/routes/admin.js b/core/server/routes/admin.js index 63597e8741..38081fda2c 100644 --- a/core/server/routes/admin.js +++ b/core/server/routes/admin.js @@ -33,7 +33,7 @@ adminRoutes = function (middleware) { res.redirect(301, subdir + '/ghost/signup/'); }); - router.post('/ghost/setup/', admin.doSignup); + 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. diff --git a/core/test/functional/client/content_test.js b/core/test/functional/client/content_test.js index 673703239b..28b1db36ca 100644 --- a/core/test/functional/client/content_test.js +++ b/core/test/functional/client/content_test.js @@ -3,7 +3,7 @@ /*globals CasperTest, casper, testPost, newUser */ -CasperTest.begin('Content screen is correct', 20, function suite(test) { +CasperTest.begin('Content screen is correct', 21, function suite(test) { // First, create a sample post for testing (this should probably be a routine) CasperTest.Routines.createTestPost.run(false); @@ -32,10 +32,9 @@ CasperTest.begin('Content screen is correct', 20, function suite(test) { test.assertSelectorHasText( '.content-preview header .status', 'Written', 'preview header contains "Written" when post is a draft' ); - // TODO: Broken while setup doen't take over Owner user, please uncomment when fixed - // test.assertSelectorHasText( - // '.content-preview header .author', newUser.name, 'preview header contains author name' - // ); + test.assertSelectorHasText( + '.content-preview header .author', newUser.name, 'preview header contains author name' + ); }); casper.then(function testEditPostButton() { @@ -67,7 +66,7 @@ CasperTest.begin('Content screen is correct', 20, function suite(test) { }); }); -CasperTest.begin('Content list shows correct post status', 6, function testStaticPageStatus(test) { +CasperTest.begin('Content list shows correct post status', 7, function testStaticPageStatus(test) { CasperTest.Routines.createTestPost.run(true); // Begin test @@ -90,10 +89,9 @@ CasperTest.begin('Content list shows correct post status', 6, function testStati test.assertSelectorHasText( '.content-preview header .status', 'Published', 'preview header contains "Published" when post is published' ); - // TODO: Broken while setup doen't take over Owner user, please uncomment when fixed - // test.assertSelectorHasText( - // '.content-preview header .author', newUser.name, 'preview header contains author name' - // ); + test.assertSelectorHasText( + '.content-preview header .author', newUser.name, 'preview header contains author name' + ); }); // Change post to static page diff --git a/core/test/functional/frontend/feed_test.js b/core/test/functional/frontend/feed_test.js index 5090df972f..401d861c36 100644 --- a/core/test/functional/frontend/feed_test.js +++ b/core/test/functional/frontend/feed_test.js @@ -2,7 +2,7 @@ * Tests if RSS exists and is working */ /*globals url, CasperTest, casper */ -CasperTest.begin('Ensure that RSS is available', 10, function suite(test) { +CasperTest.begin('Ensure that RSS is available', 11, function suite(test) { CasperTest.Routines.togglePermalinks.run('off'); casper.thenOpen(url + 'rss/', function (response) { var content = this.getPageContent(), @@ -24,13 +24,12 @@ CasperTest.begin('Ensure that RSS is available', 10, function suite(test) { test.assert(content.indexOf(postStart) >= 0, 'Feed should contain start of welcome post content.'); test.assert(content.indexOf(postEnd) >= 0, 'Feed should contain end of welcome post content.'); test.assert(content.indexOf(postLink) >= 0, 'Feed should have link to the welcome post.'); - // TODO: Broken while setup doen't take over Owner user, please uncomment when fixed - // test.assert(content.indexOf(postCreator) >= 0, 'Welcome post should have Test User as the creator.'); + test.assert(content.indexOf(postCreator) >= 0, 'Welcome post should have Test User as the creator.'); test.assert(content.indexOf('') >= 0, 'Feed should contain '); }); }, false); -CasperTest.begin('Ensure that author element is not included. Only dc:creator', 2, function suite(test) { +CasperTest.begin('Ensure that author element is not included. Only dc:creator', 3, function suite(test) { CasperTest.Routines.togglePermalinks.run('off'); casper.thenOpen(url + 'rss/', function (response) { var content = this.getPageContent(), @@ -39,8 +38,7 @@ CasperTest.begin('Ensure that author element is not included. Only dc:creator', test.assertEqual(response.status, 200, 'Response status should be 200.'); test.assert(content.indexOf(author) < 0, 'Author element should not be included'); - // TODO: Broken while setup doen't take over Owner user, please uncomment when fixed - // test.assert(content.indexOf(postCreator) >= 0, 'Welcome post should have Test User as the creator.'); + test.assert(content.indexOf(postCreator) >= 0, 'Welcome post should have Test User as the creator.'); }); }, false);