Server: add user list sort/pagination

pull/10/head
Chocobozzz 2016-08-16 22:31:45 +02:00
parent 089ff2f204
commit 5c39adb731
11 changed files with 200 additions and 17 deletions

View File

@ -11,6 +11,10 @@ const logger = require('../../../helpers/logger')
const middlewares = require('../../../middlewares') const middlewares = require('../../../middlewares')
const admin = middlewares.admin const admin = middlewares.admin
const oAuth = middlewares.oauth const oAuth = middlewares.oauth
const pagination = middlewares.pagination
const sort = middlewares.sort
const validatorsPagination = middlewares.validators.pagination
const validatorsSort = middlewares.validators.sort
const validatorsUsers = middlewares.validators.users const validatorsUsers = middlewares.validators.users
const User = mongoose.model('User') const User = mongoose.model('User')
@ -18,9 +22,16 @@ const Video = mongoose.model('Video')
const router = express.Router() const router = express.Router()
router.get('/', listUsers)
router.get('/me', oAuth.authenticate, getUserInformation) router.get('/me', oAuth.authenticate, getUserInformation)
router.get('/',
validatorsPagination.pagination,
validatorsSort.usersSort,
sort.setUsersSort,
pagination.setPagination,
listUsers
)
router.post('/', router.post('/',
oAuth.authenticate, oAuth.authenticate,
admin.ensureIsAdmin, admin.ensureIsAdmin,
@ -73,10 +84,10 @@ function getUserInformation (req, res, next) {
} }
function listUsers (req, res, next) { function listUsers (req, res, next) {
User.list(function (err, usersList) { User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) {
if (err) return next(err) if (err) return next(err)
res.json(getFormatedUsers(usersList)) res.json(getFormatedUsers(usersList, usersTotal))
}) })
} }
@ -145,7 +156,7 @@ function success (req, res, next) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function getFormatedUsers (users) { function getFormatedUsers (users, usersTotal) {
const formatedUsers = [] const formatedUsers = []
users.forEach(function (user) { users.forEach(function (user) {
@ -153,6 +164,7 @@ function getFormatedUsers (users) {
}) })
return { return {
total: usersTotal,
data: formatedUsers data: formatedUsers
} }
} }

View File

@ -39,7 +39,7 @@ function clientsExist (callback) {
} }
function usersExist (callback) { function usersExist (callback) {
User.count(function (err, totalUsers) { User.countTotal(function (err, totalUsers) {
if (err) return callback(err) if (err) return callback(err)
return callback(null, totalUsers !== 0) return callback(null, totalUsers !== 0)

View File

@ -63,6 +63,7 @@ const SEEDS_IN_PARALLEL = 3
// Sortable columns per schema // Sortable columns per schema
const SORTABLE_COLUMNS = { const SORTABLE_COLUMNS = {
USERS: [ 'username', '-username', 'createdDate', '-createdDate' ],
VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ] VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ]
} }

View File

@ -1,9 +1,16 @@
'use strict' 'use strict'
const sortMiddleware = { const sortMiddleware = {
setUsersSort: setUsersSort,
setVideosSort: setVideosSort setVideosSort: setVideosSort
} }
function setUsersSort (req, res, next) {
if (!req.query.sort) req.query.sort = '-createdDate'
return next()
}
function setVideosSort (req, res, next) { function setVideosSort (req, res, next) {
if (!req.query.sort) req.query.sort = '-createdDate' if (!req.query.sort) req.query.sort = '-createdDate'

View File

@ -5,9 +5,20 @@ const constants = require('../../initializers/constants')
const logger = require('../../helpers/logger') const logger = require('../../helpers/logger')
const validatorsSort = { const validatorsSort = {
usersSort: usersSort,
videosSort: videosSort videosSort: videosSort
} }
function usersSort (req, res, next) {
const sortableColumns = constants.SORTABLE_COLUMNS.USERS
req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns)
logger.debug('Checking sort parameters', { parameters: req.query })
checkErrors(req, res, next)
}
function videosSort (req, res, next) { function videosSort (req, res, next) {
const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS

View File

@ -1,10 +1,15 @@
const mongoose = require('mongoose') const mongoose = require('mongoose')
const customUsersValidators = require('../helpers/custom-validators').users const customUsersValidators = require('../helpers/custom-validators').users
const modelUtils = require('./utils')
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const UserSchema = mongoose.Schema({ const UserSchema = mongoose.Schema({
createdDate: {
type: Date,
default: Date.now
},
password: String, password: String,
username: String, username: String,
role: String role: String
@ -19,9 +24,9 @@ UserSchema.methods = {
} }
UserSchema.statics = { UserSchema.statics = {
count: count, countTotal: countTotal,
getByUsernameAndPassword: getByUsernameAndPassword, getByUsernameAndPassword: getByUsernameAndPassword,
list: list, listForApi: listForApi,
loadById: loadById, loadById: loadById,
loadByUsername: loadByUsername loadByUsername: loadByUsername
} }
@ -30,7 +35,7 @@ mongoose.model('User', UserSchema)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function count (callback) { function countTotal (callback) {
return this.count(callback) return this.count(callback)
} }
@ -38,8 +43,9 @@ function getByUsernameAndPassword (username, password) {
return this.findOne({ username: username, password: password }) return this.findOne({ username: username, password: password })
} }
function list (callback) { function listForApi (start, count, sort, callback) {
return this.find(callback) const query = {}
return modelUtils.listForApiWithCount.call(this, query, start, count, sort, callback)
} }
function loadById (id, callback) { function loadById (id, callback) {

30
server/models/utils.js Normal file
View File

@ -0,0 +1,30 @@
'use strict'
const parallel = require('async/parallel')
const utils = {
listForApiWithCount: listForApiWithCount
}
function listForApiWithCount (query, start, count, sort, callback) {
const self = this
parallel([
function (asyncCallback) {
self.find(query).skip(start).limit(count).sort(sort).exec(asyncCallback)
},
function (asyncCallback) {
self.count(query, asyncCallback)
}
], function (err, results) {
if (err) return callback(err)
const data = results[0]
const total = results[1]
return callback(null, data, total)
})
}
// ---------------------------------------------------------------------------
module.exports = utils

View File

@ -197,7 +197,7 @@ function getDurationFromFile (videoPath, callback) {
function listForApi (start, count, sort, callback) { function listForApi (start, count, sort, callback) {
const query = {} const query = {}
return modelUtils.findWithCount.call(this, query, start, count, sort, callback) return modelUtils.listForApiWithCount.call(this, query, start, count, sort, callback)
} }
function listByUrlAndMagnet (fromUrl, magnetUri, callback) { function listByUrlAndMagnet (fromUrl, magnetUri, callback) {
@ -234,7 +234,7 @@ function search (value, field, start, count, sort, callback) {
query[field] = new RegExp(value) query[field] = new RegExp(value)
} }
modelUtils.findWithCount.call(this, query, start, count, sort, callback) modelUtils.listForApiWithCount.call(this, query, start, count, sort, callback)
} }
function seedAllExisting (callback) { function seedAllExisting (callback) {

View File

@ -459,6 +459,32 @@ describe('Test parameters validator', function () {
let userId = null let userId = null
let userAccessToken = null let userAccessToken = null
describe('When listing users', function () {
it('Should fail with a bad start pagination', function (done) {
request(server.url)
.get(path)
.query({ start: 'hello' })
.set('Accept', 'application/json')
.expect(400, done)
})
it('Should fail with a bad count pagination', function (done) {
request(server.url)
.get(path)
.query({ count: 'hello' })
.set('Accept', 'application/json')
.expect(400, done)
})
it('Should fail with an incorrect sort', function (done) {
request(server.url)
.get(path)
.query({ sort: 'hello' })
.set('Accept', 'application/json')
.expect(400, done)
})
})
describe('When adding a new user', function () { describe('When adding a new user', function () {
it('Should fail with a too small username', function (done) { it('Should fail with a too small username', function (done) {
const data = { const data = {

View File

@ -209,22 +209,97 @@ describe('Test users', function () {
usersUtils.getUsersList(server.url, function (err, res) { usersUtils.getUsersList(server.url, function (err, res) {
if (err) throw err if (err) throw err
const users = res.body.data const result = res.body
const total = result.total
const users = result.data
expect(total).to.equal(2)
expect(users).to.be.an('array') expect(users).to.be.an('array')
expect(users.length).to.equal(2) expect(users.length).to.equal(2)
const rootUser = users[0] const user = users[0]
expect(rootUser.username).to.equal('root')
const user = users[1]
expect(user.username).to.equal('user_1') expect(user.username).to.equal('user_1')
const rootUser = users[1]
expect(rootUser.username).to.equal('root')
userId = user.id userId = user.id
done() done()
}) })
}) })
it('Should list only the first user by username asc', function (done) {
usersUtils.getUsersListPaginationAndSort(server.url, 0, 1, 'username', function (err, res) {
if (err) throw err
const result = res.body
const total = result.total
const users = result.data
expect(total).to.equal(2)
expect(users.length).to.equal(1)
const user = users[0]
expect(user.username).to.equal('root')
done()
})
})
it('Should list only the first user by username desc', function (done) {
usersUtils.getUsersListPaginationAndSort(server.url, 0, 1, '-username', function (err, res) {
if (err) throw err
const result = res.body
const total = result.total
const users = result.data
expect(total).to.equal(2)
expect(users.length).to.equal(1)
const user = users[0]
expect(user.username).to.equal('user_1')
done()
})
})
it('Should list only the second user by createdDate desc', function (done) {
usersUtils.getUsersListPaginationAndSort(server.url, 0, 1, '-createdDate', function (err, res) {
if (err) throw err
const result = res.body
const total = result.total
const users = result.data
expect(total).to.equal(2)
expect(users.length).to.equal(1)
const user = users[0]
expect(user.username).to.equal('user_1')
done()
})
})
it('Should list all the users by createdDate asc', function (done) {
usersUtils.getUsersListPaginationAndSort(server.url, 0, 2, 'createdDate', function (err, res) {
if (err) throw err
const result = res.body
const total = result.total
const users = result.data
expect(total).to.equal(2)
expect(users.length).to.equal(2)
expect(users[0].username).to.equal('root')
expect(users[1].username).to.equal('user_1')
done()
})
})
it('Should update the user password', function (done) { it('Should update the user password', function (done) {
usersUtils.updateUser(server.url, userId, accessTokenUser, 'new password', function (err, res) { usersUtils.updateUser(server.url, userId, accessTokenUser, 'new password', function (err, res) {
if (err) throw err if (err) throw err

View File

@ -6,6 +6,7 @@ const usersUtils = {
createUser: createUser, createUser: createUser,
getUserInformation: getUserInformation, getUserInformation: getUserInformation,
getUsersList: getUsersList, getUsersList: getUsersList,
getUsersListPaginationAndSort: getUsersListPaginationAndSort,
removeUser: removeUser, removeUser: removeUser,
updateUser: updateUser updateUser: updateUser
} }
@ -52,6 +53,20 @@ function getUsersList (url, end) {
.end(end) .end(end)
} }
function getUsersListPaginationAndSort (url, start, count, sort, end) {
const path = '/api/v1/users'
request(url)
.get(path)
.query({ start: start })
.query({ count: count })
.query({ sort: sort })
.set('Accept', 'application/json')
.expect(200)
.expect('Content-Type', /json/)
.end(end)
}
function removeUser (url, userId, accessToken, expectedStatus, end) { function removeUser (url, userId, accessToken, expectedStatus, end) {
if (!end) { if (!end) {
end = expectedStatus end = expectedStatus