Delete tokens before deleting a user

fixes #3750

- Updated tests to create tokens for one user. This caused the tests to
  fail for MySQL exposing the bug.
- Delete user's tokens along with posts
This commit is contained in:
Hannah Wolfe 2014-08-23 18:59:36 +01:00
parent 0005c1b88c
commit 74c6a341be
5 changed files with 65 additions and 11 deletions

View File

@ -290,7 +290,12 @@ users = {
return users.read(_.merge(options, { status: 'all'})).then(function (result) {
return dataProvider.Base.transaction(function (t) {
options.transacting = t;
dataProvider.Post.destroyByAuthor(options).then(function () {
Promise.all([
dataProvider.Accesstoken.destroyByUser(options),
dataProvider.Refreshtoken.destroyByUser(options),
dataProvider.Post.destroyByAuthor(options)
]).then(function () {
return dataProvider.User.destroy(options);
}).then(function () {
t.commit();

View File

@ -1,4 +1,6 @@
var ghostBookshelf = require('./base'),
var Promise = require('bluebird'),
ghostBookshelf = require('./base'),
errors = require('../errors'),
Basetoken;
@ -31,11 +33,32 @@ Basetoken = ghostBookshelf.Model.extend({
options = this.filterOptions(options, 'destroyAll');
return ghostBookshelf.Collection.forge([], {model: this})
.query('where', 'expires', '<', Date.now())
.fetch()
.fetch(options)
.then(function (collection) {
collection.invokeThen('destroy', options);
});
},
/**
* ### destroyByUser
* @param {[type]} options has context and id. Context is the user doing the destroy, id is the user to destroy
*/
destroyByUser: function (options) {
var userId = options.id;
options = this.filterOptions(options, 'destroyByUser');
if (userId) {
return ghostBookshelf.Collection.forge([], {model: this})
.query('where', 'user_id', '=', userId)
.fetch(options)
.then(function (collection) {
collection.invokeThen('destroy', options);
});
}
return Promise.reject(new errors.NotFoundError('No user found'));
}
});
module.exports = Basetoken;

View File

@ -20,7 +20,7 @@ describe('Users API', function () {
// Keep the DB clean
before(testUtils.teardown);
beforeEach(testUtils.setup('users:roles', 'users', 'perms:user', 'perms:role', 'perms:setting', 'perms:init'));
beforeEach(testUtils.setup('users:roles', 'users', 'user:token', 'perms:user', 'perms:role', 'perms:setting', 'perms:init'));
afterEach(testUtils.teardown);
it('dateTime fields are returned as Date objects', function (done) {
@ -85,7 +85,6 @@ describe('Users API', function () {
}).catch(done);
});
it('Can browse invited/invited-pending (admin)', function (done) {
testUtils.fixtures.createInvitedUsers().then(function () {
UserAPI.browse(_.extend(testUtils.context.admin, { status: 'invited' })).then(function (response) {

View File

@ -1,5 +1,6 @@
var _ = require('lodash'),
uuid = require('node-uuid'),
var _ = require('lodash'),
uuid = require('node-uuid'),
globalUtils = require('../../../server/utils'),
DataGenerator = {};
DataGenerator.Content = {
@ -232,7 +233,8 @@ DataGenerator.forKnex = (function () {
app_fields,
roles,
users,
roles_users;
roles_users,
clients;
function createBasic(overrides) {
return _.defaults(overrides, {
@ -327,6 +329,14 @@ DataGenerator.forKnex = (function () {
});
}
function createToken(overrides) {
return _.defaults(overrides, {
token: uuid.v4(),
client_id: 1,
expires:Date.now() + globalUtils.ONE_DAY_MS
});
}
posts = [
createPost(DataGenerator.Content.posts[0]),
createPost(DataGenerator.Content.posts[1]),
@ -349,14 +359,18 @@ DataGenerator.forKnex = (function () {
createBasic(DataGenerator.Content.roles[0]),
createBasic(DataGenerator.Content.roles[1]),
createBasic(DataGenerator.Content.roles[2]),
createBasic(DataGenerator.Content.roles[3]),
createBasic(DataGenerator.Content.roles[3])
];
users = [
createUser(DataGenerator.Content.users[0]),
createUser(DataGenerator.Content.users[1]),
createUser(DataGenerator.Content.users[2]),
createUser(DataGenerator.Content.users[3]),
createUser(DataGenerator.Content.users[3])
];
clients = [
createBasic({name: 'Ghost Admin', slug: 'ghost-admin', secret: 'not_available'})
];
roles_users = [
@ -399,6 +413,7 @@ DataGenerator.forKnex = (function () {
createApp: createBasic,
createAppField: createAppField,
createAppSetting: createAppSetting,
createToken: createToken,
posts: posts,
tags: tags,
@ -407,7 +422,8 @@ DataGenerator.forKnex = (function () {
app_fields: app_fields,
roles: roles,
users: users,
roles_users: roles_users
roles_users: roles_users,
clients: clients
};
}());

View File

@ -231,6 +231,16 @@ fixtures = {
});
},
// Creates a client, and access and refresh tokens for user 3 (author)
createTokensForUser: function createTokensForUser() {
var knex = config.database.knex;
return knex('clients').insert(DataGenerator.forKnex.clients).then(function () {
return knex('accesstokens').insert(DataGenerator.forKnex.createToken({user_id: 3}));
}).then(function () {
return knex('refreshtokens').insert(DataGenerator.forKnex.createToken({user_id: 3}));
});
},
createInvitedUsers: function createInvitedUser() {
var knex = config.database.knex,
// grab 3 more users
@ -361,6 +371,7 @@ toDoList = {
},
'users:roles': function createUsersWithRoles() { return fixtures.createUsersWithRoles(); },
'users': function createExtraUsers() { return fixtures.createExtraUsers(); },
'user:token': function createTokensForUser() { return fixtures.createTokensForUser(); },
'owner': function insertOwnerUser() { return fixtures.insertOwnerUser(); },
'owner:pre': function initOwnerUser() { return fixtures.initOwnerUser(); },
'owner:post': function overrideOwnerUser() { return fixtures.overrideOwnerUser(); },