mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Users API advanced browsing
closes #3085 - active and invited include multiple statuses when fetching - adjusted data generator
This commit is contained in:
parent
99cc855f55
commit
d4fdb07d9c
4 changed files with 86 additions and 38 deletions
|
@ -180,20 +180,28 @@ User = ghostBookshelf.Model.extend({
|
||||||
page: 1, // pagination page
|
page: 1, // pagination page
|
||||||
limit: 15,
|
limit: 15,
|
||||||
status: 'active',
|
status: 'active',
|
||||||
where: {}
|
where: {},
|
||||||
|
whereIn: {}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
//TODO: there are multiple statuses that make a user "active" or "invited" - we a way to translate/map them:
|
//TODO: there are multiple statuses that make a user "active" or "invited" - we a way to translate/map them:
|
||||||
//TODO (cont'd from above): * valid "active" statuses: active, warn-1, warn-2, warn-3, warn-4, locked
|
//TODO (cont'd from above): * valid "active" statuses: active, warn-1, warn-2, warn-3, warn-4, locked
|
||||||
//TODO (cont'd from above): * valid "invited" statuses" invited, invited-pending
|
//TODO (cont'd from above): * valid "invited" statuses" invited, invited-pending
|
||||||
|
|
||||||
// Filter on the status. A status of 'all' translates to no filter since we want all statuses
|
// Filter on the status. A status of 'all' translates to no filter since we want all statuses
|
||||||
if (options.status && options.status !== 'all') {
|
if (options.status && options.status !== 'all') {
|
||||||
// make sure that status is valid
|
// make sure that status is valid
|
||||||
//TODO: need a better way of getting a list of statuses other than hard-coding them...
|
//TODO: need a better way of getting a list of statuses other than hard-coding them...
|
||||||
options.status = _.indexOf(
|
options.status = _.indexOf(
|
||||||
['active', 'warn-1', 'warn-2', 'warn-3', 'locked', 'invited'],
|
['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked', 'invited', 'inactive'],
|
||||||
options.status) !== -1 ? options.status : 'active';
|
options.status) !== -1 ? options.status : 'active';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.status === 'active') {
|
||||||
|
userCollection.query().whereIn('status', ['active', 'warn-1', 'warn-2', 'warn-3', 'warn-4', 'locked']);
|
||||||
|
} else if (options.status === 'invited') {
|
||||||
|
userCollection.query().whereIn('status', ['invited', 'invited-pending']);
|
||||||
|
} else if (options.status !== 'all') {
|
||||||
options.where.status = options.status;
|
options.where.status = options.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,41 +38,69 @@ describe('Users API', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Browse', function () {
|
describe('Browse', function () {
|
||||||
function checkBrowseResponse(response) {
|
function checkBrowseResponse(response, count) {
|
||||||
should.exist(response);
|
should.exist(response);
|
||||||
testUtils.API.checkResponse(response, 'users');
|
testUtils.API.checkResponse(response, 'users');
|
||||||
should.exist(response.users);
|
should.exist(response.users);
|
||||||
response.users.should.have.length(7);
|
response.users.should.have.length(count);
|
||||||
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
||||||
testUtils.API.checkResponse(response.users[1], 'user', ['roles']);
|
testUtils.API.checkResponse(response.users[1], 'user', ['roles']);
|
||||||
testUtils.API.checkResponse(response.users[2], 'user', ['roles']);
|
testUtils.API.checkResponse(response.users[2], 'user', ['roles']);
|
||||||
testUtils.API.checkResponse(response.users[3], 'user', ['roles']);
|
testUtils.API.checkResponse(response.users[3], 'user', ['roles']);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('Owner can browse', function (done) {
|
it('Owner can browse', function (done) {
|
||||||
UserAPI.browse(context.owner).then(function (response) {
|
UserAPI.browse(context.owner).then(function (response) {
|
||||||
checkBrowseResponse(response);
|
checkBrowseResponse(response, 5);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Admin can browse', function (done) {
|
it('Admin can browse', function (done) {
|
||||||
UserAPI.browse(context.admin).then(function (response) {
|
UserAPI.browse(context.admin).then(function (response) {
|
||||||
checkBrowseResponse(response);
|
checkBrowseResponse(response, 5);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Editor can browse', function (done) {
|
||||||
|
UserAPI.browse(context.editor).then(function (response) {
|
||||||
|
checkBrowseResponse(response, 5);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Author can browse active', function (done) {
|
||||||
|
UserAPI.browse(context.author).then(function (response) {
|
||||||
|
checkBrowseResponse(response, 5);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('No-auth CANNOT browse', function (done) {
|
||||||
|
UserAPI.browse().then(function () {
|
||||||
|
done(new Error('Browse users is not denied without authentication.'));
|
||||||
|
}, function () {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Can browse invited/invited-pending (admin)', function (done) {
|
||||||
|
UserAPI.browse(_.extend(testUtils.context.admin, { status: 'invited' })).then(function (response) {
|
||||||
|
should.exist(response);
|
||||||
|
testUtils.API.checkResponse(response, 'users');
|
||||||
|
should.exist(response.users);
|
||||||
|
response.users.should.have.length(1);
|
||||||
|
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
||||||
|
response.users[0].status.should.equal('invited-pending');
|
||||||
|
|
||||||
it('Editor can browse', function (done) {
|
|
||||||
UserAPI.browse(context.editor).then(function (response) {
|
|
||||||
checkBrowseResponse(response);
|
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Author can browse', function (done) {
|
it('Author can browse', function (done) {
|
||||||
UserAPI.browse(context.author).then(function (response) {
|
UserAPI.browse(context.author).then(function (response) {
|
||||||
checkBrowseResponse(response);
|
checkBrowseResponse(response, 5);
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
@ -84,6 +112,13 @@ describe('Users API', function () {
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Can browse all', function (done) {
|
||||||
|
UserAPI.browse(_.extend(testUtils.context.admin, { status: 'all'})).then(function (response) {
|
||||||
|
checkBrowseResponse(response, 7);
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Read', function () {
|
describe('Read', function () {
|
||||||
|
@ -450,6 +485,7 @@ describe('Users API', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('Destroy', function () {
|
describe('Destroy', function () {
|
||||||
function checkDestroyResponse(response) {
|
function checkDestroyResponse(response) {
|
||||||
|
@ -478,7 +514,6 @@ describe('Users API', function () {
|
||||||
UserAPI.destroy(_.extend({}, context.owner, {id: userIdFor.admin}))
|
UserAPI.destroy(_.extend({}, context.owner, {id: userIdFor.admin}))
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
checkDestroyResponse(response);
|
checkDestroyResponse(response);
|
||||||
|
|
||||||
// Editor
|
// Editor
|
||||||
return UserAPI.destroy(_.extend({}, context.owner, {id: userIdFor.editor}));
|
return UserAPI.destroy(_.extend({}, context.owner, {id: userIdFor.editor}));
|
||||||
}).then(function (response) {
|
}).then(function (response) {
|
||||||
|
|
|
@ -179,7 +179,7 @@ describe('User Model', function run() {
|
||||||
results.meta.pagination.page.should.equal(1);
|
results.meta.pagination.page.should.equal(1);
|
||||||
results.meta.pagination.limit.should.equal(15);
|
results.meta.pagination.limit.should.equal(15);
|
||||||
results.meta.pagination.pages.should.equal(1);
|
results.meta.pagination.pages.should.equal(1);
|
||||||
results.users.length.should.equal(4);
|
results.users.length.should.equal(3);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).catch(done);
|
}).catch(done);
|
||||||
|
@ -193,7 +193,7 @@ describe('User Model', function run() {
|
||||||
results.meta.pagination.limit.should.equal(15);
|
results.meta.pagination.limit.should.equal(15);
|
||||||
results.meta.pagination.pages.should.equal(1);
|
results.meta.pagination.pages.should.equal(1);
|
||||||
results.meta.pagination.total.should.equal(2);
|
results.meta.pagination.total.should.equal(2);
|
||||||
results.users.length.should.equal(2);
|
results.users.length.should.equal(1);
|
||||||
|
|
||||||
return UserModel.findPage({role: 'Owner'});
|
return UserModel.findPage({role: 'Owner'});
|
||||||
}).then(function (results) {
|
}).then(function (results) {
|
||||||
|
|
|
@ -75,31 +75,36 @@ DataGenerator.Content = {
|
||||||
name: 'Joe Bloggs',
|
name: 'Joe Bloggs',
|
||||||
slug: 'joe-blogs',
|
slug: 'joe-blogs',
|
||||||
email: 'jbloggs@example.com',
|
email: 'jbloggs@example.com',
|
||||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6',
|
||||||
|
status: 'active'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Smith Wellingsworth',
|
name: 'Smith Wellingsworth',
|
||||||
slug: 'smith-wellingsworth',
|
slug: 'smith-wellingsworth',
|
||||||
email: 'swellingsworth@example.com',
|
email: 'swellingsworth@example.com',
|
||||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6',
|
||||||
|
status: 'invited-pending'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Jimothy Bogendath',
|
name: 'Jimothy Bogendath',
|
||||||
slug: 'jimothy-bogendath',
|
slug: 'jimothy-bogendath',
|
||||||
email: 'jbOgendAth@example.com',
|
email: 'jbOgendAth@example.com',
|
||||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6',
|
||||||
|
status: 'warn-1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Slimer McEctoplasm',
|
name: 'Slimer McEctoplasm',
|
||||||
slug: 'slimer-mcectoplasm',
|
slug: 'slimer-mcectoplasm',
|
||||||
email: 'smcectoplasm@example.com',
|
email: 'smcectoplasm@example.com',
|
||||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6',
|
||||||
|
status: 'warn-2'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Ivan Email',
|
name: 'Ivan Email',
|
||||||
slug: 'ivan-email',
|
slug: 'ivan-email',
|
||||||
email: 'info@ghost.org',
|
email: 'info@ghost.org',
|
||||||
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6'
|
password: '$2a$10$.pZeeBE0gHXd0PTnbT/ph.GEKgd0Wd3q2pWna3ynTGBkPKnGIKZL6',
|
||||||
|
status: 'inactive'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue