mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-01 23:37:43 +03:00
Merge pull request #3337 from morficus/issue-3222
Pagination on the Users Management screen
This commit is contained in:
commit
90880469f6
@ -1,6 +1,6 @@
|
||||
import { getRequestErrorMessage } from 'ghost/utils/ajax';
|
||||
import PaginationControllerMixin from 'ghost/mixins/pagination-controller';
|
||||
|
||||
var PostsController = Ember.ArrayController.extend({
|
||||
var PostsController = Ember.ArrayController.extend(PaginationControllerMixin, {
|
||||
// this will cause the list to re-sort when any of these properties change on any of the models
|
||||
sortProperties: ['status', 'published_at', 'updated_at'],
|
||||
|
||||
@ -66,64 +66,11 @@ var PostsController = Ember.ArrayController.extend({
|
||||
return statusResult;
|
||||
},
|
||||
|
||||
// set from PostsRoute
|
||||
paginationSettings: null,
|
||||
|
||||
// holds the next page to load during infinite scroll
|
||||
nextPage: null,
|
||||
|
||||
// indicates whether we're currently loading the next page
|
||||
isLoading: null,
|
||||
|
||||
init: function () {
|
||||
this._super();
|
||||
//let the PaginationControllerMixin know what type of model we will be paginating
|
||||
//this is necesariy because we do not have access to the model inside the Controller::init method
|
||||
this._super({'modelType': 'post'});
|
||||
|
||||
var metadata = this.store.metadataFor('post');
|
||||
this.set('nextPage', metadata.pagination.next);
|
||||
},
|
||||
|
||||
/**
|
||||
* Takes an ajax response, concatenates any error messages, then generates an error notification.
|
||||
* @param {jqXHR} response The jQuery ajax reponse object.
|
||||
* @return
|
||||
*/
|
||||
reportLoadError: function (response) {
|
||||
var message = 'A problem was encountered while loading more posts';
|
||||
|
||||
if (response) {
|
||||
// Get message from response
|
||||
message += ': ' + getRequestErrorMessage(response, true);
|
||||
} else {
|
||||
message += '.';
|
||||
}
|
||||
|
||||
this.notifications.showError(message);
|
||||
},
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Loads the next paginated page of posts into the ember-data store. Will cause the posts list UI to update.
|
||||
* @return
|
||||
*/
|
||||
loadNextPage: function () {
|
||||
var self = this,
|
||||
store = this.get('store'),
|
||||
nextPage = this.get('nextPage'),
|
||||
paginationSettings = this.get('paginationSettings');
|
||||
|
||||
if (nextPage) {
|
||||
this.set('isLoading', true);
|
||||
this.set('paginationSettings.page', nextPage);
|
||||
store.find('post', paginationSettings).then(function () {
|
||||
var metadata = store.metadataFor('post');
|
||||
|
||||
self.set('nextPage', metadata.pagination.next);
|
||||
self.set('isLoading', false);
|
||||
}, function (response) {
|
||||
self.reportLoadError(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,12 @@
|
||||
var UsersIndexController = Ember.ArrayController.extend({
|
||||
import PaginationControllerMixin from 'ghost/mixins/pagination-controller';
|
||||
|
||||
var UsersIndexController = Ember.ArrayController.extend(PaginationControllerMixin, {
|
||||
init: function () {
|
||||
//let the PaginationControllerMixin know what type of model we will be paginating
|
||||
//this is necesariy because we do not have access to the model inside the Controller::init method
|
||||
this._super({'modelType': 'user'});
|
||||
},
|
||||
|
||||
users: Ember.computed.alias('model'),
|
||||
|
||||
activeUsers: Ember.computed.filterBy('users', 'active', true).property('users'),
|
||||
|
76
core/client/mixins/pagination-controller.js
Normal file
76
core/client/mixins/pagination-controller.js
Normal file
@ -0,0 +1,76 @@
|
||||
import { getRequestErrorMessage } from 'ghost/utils/ajax';
|
||||
|
||||
var PaginationControllerMixin = Ember.Mixin.create({
|
||||
|
||||
// set from PaginationRouteMixin
|
||||
paginationSettings: null,
|
||||
|
||||
// holds the next page to load during infinite scroll
|
||||
nextPage: null,
|
||||
|
||||
// indicates whether we're currently loading the next page
|
||||
isLoading: null,
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options: {
|
||||
* modelType: <String> name of the model that will be paginated
|
||||
* }
|
||||
*/
|
||||
init: function (options) {
|
||||
this._super();
|
||||
|
||||
var metadata = this.store.metadataFor(options.modelType);
|
||||
this.set('nextPage', metadata.pagination.next);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Takes an ajax response, concatenates any error messages, then generates an error notification.
|
||||
* @param {jqXHR} response The jQuery ajax reponse object.
|
||||
* @return
|
||||
*/
|
||||
reportLoadError: function (response) {
|
||||
var message = 'A problem was encountered while loading more records';
|
||||
|
||||
if (response) {
|
||||
// Get message from response
|
||||
message += ': ' + getRequestErrorMessage(response, true);
|
||||
} else {
|
||||
message += '.';
|
||||
}
|
||||
|
||||
this.notifications.showError(message);
|
||||
},
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Loads the next paginated page of posts into the ember-data store. Will cause the posts list UI to update.
|
||||
* @return
|
||||
*/
|
||||
loadNextPage: function () {
|
||||
|
||||
var self = this,
|
||||
store = this.get('store'),
|
||||
recordType = this.get('model').get('type'),
|
||||
nextPage = this.get('nextPage'),
|
||||
paginationSettings = this.get('paginationSettings');
|
||||
|
||||
if (nextPage) {
|
||||
this.set('isLoading', true);
|
||||
this.set('paginationSettings.page', nextPage);
|
||||
store.find(recordType, paginationSettings).then(function () {
|
||||
var metadata = store.metadataFor(recordType);
|
||||
|
||||
self.set('nextPage', metadata.pagination.next);
|
||||
self.set('isLoading', false);
|
||||
}, function (response) {
|
||||
self.reportLoadError(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default PaginationControllerMixin;
|
23
core/client/mixins/pagination-route.js
Normal file
23
core/client/mixins/pagination-route.js
Normal file
@ -0,0 +1,23 @@
|
||||
var defaultPaginationSettings = {
|
||||
page: 1,
|
||||
limit: 15
|
||||
};
|
||||
|
||||
var PaginationRoute = Ember.Mixin.create({
|
||||
|
||||
/**
|
||||
* Sets up pagination details
|
||||
* @param {settings}: object that specifies additional pagination details
|
||||
*/
|
||||
setupPagination: function (settings) {
|
||||
|
||||
settings = settings || {};
|
||||
settings = _.defaults(settings, defaultPaginationSettings);
|
||||
|
||||
this.set('paginationSettings', settings);
|
||||
this.controller.set('paginationSettings', settings);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
export default PaginationRoute;
|
39
core/client/mixins/pagination-view-infinite-scroll.js
Normal file
39
core/client/mixins/pagination-view-infinite-scroll.js
Normal file
@ -0,0 +1,39 @@
|
||||
var PaginationViewInfiniteScrollMixin = Ember.Mixin.create({
|
||||
|
||||
/**
|
||||
* Determines if we are past a scroll point where we need to fetch the next page
|
||||
* @param event The scroll event
|
||||
*/
|
||||
checkScroll: function (event) {
|
||||
var element = event.target,
|
||||
triggerPoint = 100,
|
||||
controller = this.get('controller'),
|
||||
isLoading = controller.get('isLoading');
|
||||
|
||||
// If we haven't passed our threshold or we are already fetching content, exit
|
||||
if (isLoading || (element.scrollTop + element.clientHeight + triggerPoint <= element.scrollHeight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
controller.send('loadNextPage');
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind to the scroll event once the element is in the DOM
|
||||
*/
|
||||
didInsertElement: function () {
|
||||
var el = this.$();
|
||||
|
||||
el.on('scroll', Ember.run.bind(this, this.checkScroll));
|
||||
},
|
||||
|
||||
/**
|
||||
* Unbind from the scroll event when the element is no longer in the DOM
|
||||
*/
|
||||
willDestroyElement: function () {
|
||||
var el = this.$();
|
||||
el.off('scroll');
|
||||
}
|
||||
});
|
||||
|
||||
export default PaginationViewInfiniteScrollMixin;
|
@ -1,6 +1,7 @@
|
||||
import styleBody from 'ghost/mixins/style-body';
|
||||
import ShortcutsRoute from 'ghost/mixins/shortcuts-route';
|
||||
import loadingIndicator from 'ghost/mixins/loading-indicator';
|
||||
import PaginationRouteMixin from 'ghost/mixins/pagination-route';
|
||||
|
||||
var paginationSettings = {
|
||||
status: 'all',
|
||||
@ -9,7 +10,7 @@ var paginationSettings = {
|
||||
page: 1
|
||||
};
|
||||
|
||||
var PostsRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, ShortcutsRoute, styleBody, loadingIndicator, {
|
||||
var PostsRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, ShortcutsRoute, styleBody, loadingIndicator, PaginationRouteMixin, {
|
||||
classNames: ['manage'],
|
||||
|
||||
model: function () {
|
||||
@ -22,7 +23,7 @@ var PostsRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, Sh
|
||||
|
||||
setupController: function (controller, model) {
|
||||
this._super(controller, model);
|
||||
controller.set('paginationSettings', paginationSettings);
|
||||
this.setupPagination(paginationSettings);
|
||||
},
|
||||
|
||||
shortcuts: {
|
||||
|
@ -1,7 +1,34 @@
|
||||
var UsersIndexRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, {
|
||||
import PaginationRouteMixin from 'ghost/mixins/pagination-route';
|
||||
|
||||
var activeUsersPaginationSettings = {
|
||||
include: 'roles',
|
||||
page: 1,
|
||||
limit: 20
|
||||
};
|
||||
|
||||
var invitedUsersPaginationSettings = {
|
||||
include: 'roles',
|
||||
limit: 'all',
|
||||
status: 'invited'
|
||||
};
|
||||
|
||||
var UsersIndexRoute = Ember.Route.extend(Ember.SimpleAuth.AuthenticatedRouteMixin, PaginationRouteMixin, {
|
||||
setupController: function (controller, model) {
|
||||
this._super(controller, model.active);
|
||||
this.setupPagination(activeUsersPaginationSettings);
|
||||
},
|
||||
|
||||
model: function () {
|
||||
return this.store.find('user');
|
||||
// using `.filter` allows the template to auto-update when new models are pulled in from the server.
|
||||
// we just need to 'return true' to allow all models by default.
|
||||
return Ember.RSVP.hash({
|
||||
inactive: this.store.filter('user', invitedUsersPaginationSettings, function () {
|
||||
return true;
|
||||
}),
|
||||
active: this.store.filter('user', activeUsersPaginationSettings, function () {
|
||||
return true;
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
</section>
|
||||
</header>
|
||||
|
||||
<section class="content settings-users">
|
||||
{{#view "settings/users/users-list-view" tagName="section" class="content settings-users" }}
|
||||
{{#if invitedUsers}}
|
||||
|
||||
<section class="object-list invited-users">
|
||||
@ -62,4 +62,4 @@
|
||||
{{/each}}
|
||||
|
||||
</section>
|
||||
</section>
|
||||
{{/view}}
|
||||
|
@ -1,34 +1,17 @@
|
||||
import setScrollClassName from 'ghost/utils/set-scroll-classname';
|
||||
import PaginationViewMixin from 'ghost/mixins/pagination-view-infinite-scroll';
|
||||
|
||||
var PostsListView = Ember.View.extend({
|
||||
|
||||
var PostsListView = Ember.View.extend(PaginationViewMixin, {
|
||||
classNames: ['content-list-content'],
|
||||
|
||||
checkScroll: function (event) {
|
||||
var element = event.target,
|
||||
triggerPoint = 100,
|
||||
controller = this.get('controller'),
|
||||
isLoading = controller.get('isLoading');
|
||||
|
||||
// If we haven't passed our threshold, exit
|
||||
if (isLoading || (element.scrollTop + element.clientHeight + triggerPoint <= element.scrollHeight)) {
|
||||
return;
|
||||
}
|
||||
|
||||
controller.send('loadNextPage');
|
||||
},
|
||||
|
||||
didInsertElement: function () {
|
||||
this._super();
|
||||
var el = this.$();
|
||||
el.on('scroll', Ember.run.bind(this, this.checkScroll));
|
||||
el.on('scroll', Ember.run.bind(el, setScrollClassName, {
|
||||
target: el.closest('.content-list'),
|
||||
offset: 10
|
||||
}));
|
||||
},
|
||||
|
||||
willDestroyElement: function () {
|
||||
var el = this.$();
|
||||
el.off('scroll');
|
||||
}
|
||||
});
|
||||
|
||||
|
8
core/client/views/settings/users/users-list-view.js
Normal file
8
core/client/views/settings/users/users-list-view.js
Normal file
@ -0,0 +1,8 @@
|
||||
//import setScrollClassName from 'ghost/utils/set-scroll-classname';
|
||||
import PaginationViewMixin from 'ghost/mixins/pagination-view-infinite-scroll';
|
||||
|
||||
var UsersListView = Ember.View.extend(PaginationViewMixin, {
|
||||
classNames: ['settings-users']
|
||||
});
|
||||
|
||||
export default UsersListView;
|
@ -42,9 +42,7 @@ users = {
|
||||
if (options.include) {
|
||||
options.include = prepareInclude(options.include);
|
||||
}
|
||||
return dataProvider.User.findAll(options).then(function (result) {
|
||||
return { users: result.toJSON() };
|
||||
});
|
||||
return dataProvider.User.findPage(options);
|
||||
}, function () {
|
||||
return when.reject(new errors.NoPermissionError('You do not have permission to browse users.'));
|
||||
});
|
||||
|
@ -109,7 +109,8 @@ User = ghostBookshelf.Model.extend({
|
||||
findOne: ['withRelated'],
|
||||
findAll: ['withRelated'],
|
||||
setup: ['id'],
|
||||
edit: ['withRelated', 'id']
|
||||
edit: ['withRelated', 'id'],
|
||||
findPage: ['page', 'limit', 'status']
|
||||
};
|
||||
|
||||
if (validOptions[methodName]) {
|
||||
@ -131,6 +132,144 @@ User = ghostBookshelf.Model.extend({
|
||||
return ghostBookshelf.Model.findAll.call(this, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* #### findPage
|
||||
* Find results by page - returns an object containing the
|
||||
* information about the request (page, limit), along with the
|
||||
* info needed for pagination (pages, total).
|
||||
*
|
||||
* **response:**
|
||||
*
|
||||
* {
|
||||
* users: [
|
||||
* {...}, {...}, {...}
|
||||
* ],
|
||||
* meta: {
|
||||
* page: __,
|
||||
* limit: __,
|
||||
* pages: __,
|
||||
* total: __
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @params {Object} options
|
||||
*/
|
||||
findPage: function (options) {
|
||||
options = options || {};
|
||||
|
||||
var userCollection = Users.forge(),
|
||||
userQuery;
|
||||
|
||||
if (options.limit && options.limit !== 'all') {
|
||||
options.limit = parseInt(options.limit) || 15;
|
||||
}
|
||||
|
||||
options = this.filterOptions(options, 'findPage');
|
||||
|
||||
// Set default settings for options
|
||||
options = _.extend({
|
||||
page: 1, // pagination page
|
||||
limit: 15,
|
||||
status: 'active',
|
||||
where: {}
|
||||
}, options);
|
||||
|
||||
//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 "invited" statuses" invited, invited-pending
|
||||
|
||||
// the status provided.
|
||||
if (options.status) {
|
||||
// make sure that status is valid
|
||||
//TODO: need a better way of getting a list of statuses other than hard-coding them...
|
||||
options.status = _.indexOf(['active', 'warn-1', 'warn-2', 'warn-3', 'locked', 'invited'], options.status) !== -1 ? options.status : 'active';
|
||||
options.where.status = options.status;
|
||||
}
|
||||
|
||||
// If there are where conditionals specified, add those
|
||||
// to the query.
|
||||
if (options.where) {
|
||||
userCollection.query('where', options.where);
|
||||
}
|
||||
|
||||
// Add related objects
|
||||
options.withRelated = _.union([ 'roles' ], options.include);
|
||||
|
||||
//only include a limit-query if a numeric limit is provided
|
||||
if (_.isNumber(options.limit)) {
|
||||
userCollection
|
||||
.query('limit', options.limit)
|
||||
.query('offset', options.limit * (options.page - 1));
|
||||
}
|
||||
|
||||
userQuery = userCollection
|
||||
.query('orderBy', 'last_login', 'DESC')
|
||||
.query('orderBy', 'name', 'ASC')
|
||||
.query('orderBy', 'created_at', 'DESC')
|
||||
.fetch(_.omit(options, 'page', 'limit'));
|
||||
|
||||
|
||||
return when(userQuery)
|
||||
|
||||
// Fetch pagination information
|
||||
.then(function () {
|
||||
var qb,
|
||||
tableName = _.result(userCollection, 'tableName'),
|
||||
idAttribute = _.result(userCollection, 'idAttribute');
|
||||
|
||||
// After we're done, we need to figure out what
|
||||
// the limits are for the pagination values.
|
||||
qb = ghostBookshelf.knex(tableName);
|
||||
|
||||
if (options.where) {
|
||||
qb.where(options.where);
|
||||
}
|
||||
|
||||
return qb.count(tableName + '.' + idAttribute + ' as aggregate');
|
||||
})
|
||||
|
||||
// Format response of data
|
||||
.then(function (resp) {
|
||||
var totalUsers = parseInt(resp[0].aggregate, 10),
|
||||
calcPages = Math.ceil(totalUsers / options.limit),
|
||||
pagination = {},
|
||||
meta = {},
|
||||
data = {};
|
||||
|
||||
pagination.page = parseInt(options.page, 10);
|
||||
pagination.limit = options.limit;
|
||||
pagination.pages = calcPages === 0 ? 1 : calcPages;
|
||||
pagination.total = totalUsers;
|
||||
pagination.next = null;
|
||||
pagination.prev = null;
|
||||
|
||||
// Pass include to each model so that toJSON works correctly
|
||||
if (options.include) {
|
||||
_.each(userCollection.models, function (item) {
|
||||
item.include = options.include;
|
||||
});
|
||||
}
|
||||
|
||||
data.users = userCollection.toJSON();
|
||||
data.meta = meta;
|
||||
meta.pagination = pagination;
|
||||
|
||||
if (pagination.pages > 1) {
|
||||
if (pagination.page === 1) {
|
||||
pagination.next = pagination.page + 1;
|
||||
} else if (pagination.page === pagination.pages) {
|
||||
pagination.prev = pagination.page - 1;
|
||||
} else {
|
||||
pagination.next = pagination.page + 1;
|
||||
pagination.prev = pagination.page - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
})
|
||||
.catch(errors.logAndThrowError);
|
||||
},
|
||||
|
||||
/**
|
||||
* ### Find One
|
||||
* @extends ghostBookshelf.Model.findOne to include roles
|
||||
|
@ -117,7 +117,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -138,7 +138,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -159,7 +159,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -180,7 +180,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -201,7 +201,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -223,7 +223,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -247,7 +247,7 @@ describe('User API', function () {
|
||||
should.not.exist(res.headers['x-cache-invalidate']);
|
||||
var jsonResponse = res.body;
|
||||
jsonResponse.users.should.exist;
|
||||
testUtils.API.checkResponse(jsonResponse, 'users');
|
||||
should.not.exist(jsonResponse.meta);
|
||||
|
||||
jsonResponse.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(jsonResponse.users[0], 'user', ['roles']);
|
||||
@ -366,4 +366,4 @@ describe('User API', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -58,8 +58,8 @@ describe('Authentication API', function () {
|
||||
AuthAPI.setup({ setup: [setupData] }).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');
|
||||
testUtils.API.checkResponse(result.users[0], 'user', ['roles']);
|
||||
|
||||
var newUser = result.users[0];
|
||||
|
@ -1,19 +1,53 @@
|
||||
/*globals describe, before, beforeEach, afterEach, it */
|
||||
/*jshint expr:true*/
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
var testUtils = require('../../utils'),
|
||||
should = require('should'),
|
||||
|
||||
permissions = require('../../../server/permissions'),
|
||||
UserModel = require('../../../server/models').User;
|
||||
|
||||
// Stuff we are testing
|
||||
permissions = require('../../../server/permissions'),
|
||||
UserModel = require('../../../server/models').User,
|
||||
UsersAPI = require('../../../server/api/users');
|
||||
UsersAPI = require('../../../server/api/users');
|
||||
AuthAPI = require('../../../server/api/authentication');
|
||||
|
||||
describe('Users API', function () {
|
||||
// Keep the DB clean
|
||||
before(testUtils.teardown);
|
||||
afterEach(testUtils.teardown);
|
||||
|
||||
should.exist(UsersAPI);
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
describe('No User', function () {
|
||||
beforeEach(function (done) {
|
||||
testUtils.initData().then(function () {
|
||||
return permissions.init();
|
||||
}).then(function () {
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('can add with internal user', function (done) {
|
||||
AuthAPI.setup({ setup: [{
|
||||
'name': 'Hello World',
|
||||
'email': 'hello@world.com',
|
||||
'password': 'password'
|
||||
}]}).then(function (results) {
|
||||
should.exist(results);
|
||||
should.not.exist(results.meta);
|
||||
should.exist(results.users);
|
||||
results.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(results.users[0], 'user', ['roles']);
|
||||
results.users[0].name.should.equal('Hello World');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('With Users', function () {
|
||||
beforeEach(function (done) {
|
||||
@ -95,7 +129,8 @@ describe('Users API', function () {
|
||||
it('admin can read', function (done) {
|
||||
UsersAPI.read({id: 1, context: {user: 1}}).then(function (results) {
|
||||
should.exist(results);
|
||||
testUtils.API.checkResponse(results, 'users');
|
||||
should.not.exist(results.meta);
|
||||
should.exist(results.users);
|
||||
results.users[0].id.should.eql(1);
|
||||
testUtils.API.checkResponse(results.users[0], 'user', ['roles']);
|
||||
|
||||
@ -108,7 +143,8 @@ describe('Users API', function () {
|
||||
it('editor can read', function (done) {
|
||||
UsersAPI.read({id: 1, context: {user: 2}}).then(function (results) {
|
||||
should.exist(results);
|
||||
testUtils.API.checkResponse(results, 'users');
|
||||
should.not.exist(results.meta);
|
||||
should.exist(results.users);
|
||||
results.users[0].id.should.eql(1);
|
||||
testUtils.API.checkResponse(results.users[0], 'user', ['roles']);
|
||||
done();
|
||||
@ -118,7 +154,8 @@ describe('Users API', function () {
|
||||
it('author can read', function (done) {
|
||||
UsersAPI.read({id: 1, context: {user: 3}}).then(function (results) {
|
||||
should.exist(results);
|
||||
testUtils.API.checkResponse(results, 'users');
|
||||
should.not.exist(results.meta);
|
||||
should.exist(results.users);
|
||||
results.users[0].id.should.eql(1);
|
||||
testUtils.API.checkResponse(results.users[0], 'user', ['roles']);
|
||||
done();
|
||||
@ -128,7 +165,8 @@ describe('Users API', function () {
|
||||
it('no-auth can read', function (done) {
|
||||
UsersAPI.read({id: 1}).then(function (results) {
|
||||
should.exist(results);
|
||||
testUtils.API.checkResponse(results, 'users');
|
||||
should.not.exist(results.meta);
|
||||
should.exist(results.users);
|
||||
results.users[0].id.should.eql(1);
|
||||
testUtils.API.checkResponse(results.users[0], 'user', ['roles']);
|
||||
done();
|
||||
@ -138,7 +176,8 @@ describe('Users API', function () {
|
||||
it('admin can edit', function (done) {
|
||||
UsersAPI.edit({users: [{name: 'Joe Blogger'}]}, {id: 1, context: {user: 1}}).then(function (response) {
|
||||
should.exist(response);
|
||||
testUtils.API.checkResponse(response, 'users');
|
||||
should.not.exist(response.meta);
|
||||
should.exist(response.users);
|
||||
response.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
||||
response.users[0].name.should.equal('Joe Blogger');
|
||||
@ -150,7 +189,8 @@ describe('Users API', function () {
|
||||
it('editor can edit', function (done) {
|
||||
UsersAPI.edit({users: [{name: 'Joe Blogger'}]}, {id: 1, context: {user: 2}}).then(function (response) {
|
||||
should.exist(response);
|
||||
testUtils.API.checkResponse(response, 'users');
|
||||
should.not.exist(response.meta);
|
||||
should.exist(response.users);
|
||||
response.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
||||
response.users[0].name.should.eql('Joe Blogger');
|
||||
@ -170,7 +210,8 @@ describe('Users API', function () {
|
||||
return UsersAPI.edit({users: [{name: 'Timothy Bogendath'}]}, {id: 3, context: {user: 3}})
|
||||
.then(function (response) {
|
||||
should.exist(response);
|
||||
testUtils.API.checkResponse(response, 'users');
|
||||
should.not.exist(response.meta);
|
||||
should.exist(response.users);
|
||||
response.users.should.have.length(1);
|
||||
testUtils.API.checkResponse(response.users[0], 'user', ['roles']);
|
||||
response.users[0].name.should.eql('Timothy Bogendath');
|
||||
@ -179,4 +220,4 @@ describe('Users API', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -6,7 +6,7 @@ var url = require('url'),
|
||||
schema = 'http://',
|
||||
expectedProperties = {
|
||||
posts: ['posts', 'meta'],
|
||||
users: ['users'],
|
||||
users: ['users', 'meta'],
|
||||
pagination: ['page', 'limit', 'pages', 'total', 'next', 'prev'],
|
||||
post: ['id', 'uuid', 'title', 'slug', 'markdown', 'html', 'meta_title', 'meta_description',
|
||||
'featured', 'image', 'status', 'language', 'created_at', 'created_by', 'updated_at',
|
||||
|
Loading…
Reference in New Issue
Block a user