2015-07-20 00:09:47 -07:00
'use strict' ;
exports = module . exports = {
2016-04-17 18:27:11 +02:00
get : get ,
2015-07-20 00:09:47 -07:00
update : update ,
2016-04-17 18:27:11 +02:00
list : list ,
create : create ,
remove : remove ,
2018-08-31 14:30:00 -07:00
changePassword : changePassword ,
2015-07-20 00:09:47 -07:00
verifyPassword : verifyPassword ,
2018-08-17 09:49:58 -07:00
createInvite : createInvite ,
2016-02-09 15:47:02 -08:00
sendInvite : sendInvite ,
2018-06-28 16:48:04 -07:00
setGroups : setGroups ,
2018-10-30 20:19:28 -07:00
transferOwnership : transferOwnership
2015-07-20 00:09:47 -07:00
} ;
2018-04-30 23:03:28 -07:00
var assert = require ( 'assert' ) ,
2019-03-25 15:07:06 -07:00
auditSource = require ( '../auditsource.js' ) ,
2015-07-20 00:09:47 -07:00
HttpError = require ( 'connect-lastmile' ) . HttpError ,
HttpSuccess = require ( 'connect-lastmile' ) . HttpSuccess ,
2018-04-29 10:58:45 -07:00
users = require ( '../users.js' ) ,
2018-04-29 17:37:53 -07:00
UsersError = users . UsersError ;
2015-07-20 00:09:47 -07:00
2016-04-17 18:27:11 +02:00
function create ( req , res , next ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof req . body , 'object' ) ;
if ( typeof req . body . email !== 'string' ) return next ( new HttpError ( 400 , 'email must be string' ) ) ;
2016-04-01 16:48:50 +02:00
if ( 'username' in req . body && typeof req . body . username !== 'string' ) return next ( new HttpError ( 400 , 'username must be string' ) ) ;
2016-01-20 00:05:06 -08:00
if ( 'displayName' in req . body && typeof req . body . displayName !== 'string' ) return next ( new HttpError ( 400 , 'displayName must be string' ) ) ;
2018-04-26 13:58:21 -07:00
if ( 'password' in req . body && typeof req . body . password !== 'string' ) return next ( new HttpError ( 400 , 'password must be string' ) ) ;
2018-08-21 16:41:42 +02:00
if ( 'admin' in req . body && typeof req . body . admin !== 'boolean' ) return next ( new HttpError ( 400 , 'admin flag must be a boolean' ) ) ;
2015-07-20 00:09:47 -07:00
2018-06-11 12:59:52 -07:00
var password = req . body . password || null ;
2015-07-20 00:09:47 -07:00
var email = req . body . email ;
2017-02-02 00:23:11 -08:00
var username = 'username' in req . body ? req . body . username : null ;
2016-01-19 23:34:49 -08:00
var displayName = req . body . displayName || '' ;
2015-07-20 00:09:47 -07:00
2019-03-25 15:07:06 -07:00
users . create ( username , password , email , displayName , { invitor : req . user , admin : req . body . admin } , auditSource . fromRequest ( req ) , function ( error , user ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . BAD _FIELD ) return next ( new HttpError ( 400 , error . message ) ) ;
if ( error && error . reason === UsersError . ALREADY _EXISTS ) return next ( new HttpError ( 409 , error . message ) ) ;
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
var userInfo = {
id : user . id ,
username : user . username ,
2016-04-01 16:48:50 +02:00
displayName : user . displayName ,
2015-07-20 00:09:47 -07:00
email : user . email ,
2018-01-21 14:25:39 +01:00
fallbackEmail : user . fallbackEmail ,
2016-05-31 11:49:59 -07:00
groupIds : [ ] ,
2015-07-20 00:09:47 -07:00
resetToken : user . resetToken
} ;
2018-06-15 16:26:14 -07:00
next ( new HttpSuccess ( 201 , userInfo ) ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
function update ( req , res , next ) {
2016-01-25 14:58:02 +01:00
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof req . user , 'object' ) ;
assert . strictEqual ( typeof req . body , 'object' ) ;
2016-01-25 14:12:09 +01:00
if ( 'email' in req . body && typeof req . body . email !== 'string' ) return next ( new HttpError ( 400 , 'email must be string' ) ) ;
2018-01-21 14:25:39 +01:00
if ( 'fallbackEmail' in req . body && typeof req . body . fallbackEmail !== 'string' ) return next ( new HttpError ( 400 , 'fallbackEmail must be string' ) ) ;
2016-01-25 14:08:11 +01:00
if ( 'displayName' in req . body && typeof req . body . displayName !== 'string' ) return next ( new HttpError ( 400 , 'displayName must be string' ) ) ;
2016-06-02 23:53:06 -07:00
if ( 'username' in req . body && typeof req . body . username !== 'string' ) return next ( new HttpError ( 400 , 'username must be a string' ) ) ;
2015-07-20 00:09:47 -07:00
2018-07-26 17:17:52 -07:00
if ( 'admin' in req . body ) {
if ( typeof req . body . admin !== 'boolean' ) return next ( new HttpError ( 400 , 'admin must be a boolean' ) ) ;
// this route is only allowed for admins, so req.user has to be an admin
2018-07-26 23:42:57 -07:00
if ( req . user . id === req . params . userId && ! req . body . admin ) return next ( new HttpError ( 409 , 'Cannot remove admin flag on self' ) ) ;
2018-07-26 17:17:52 -07:00
}
2019-03-25 15:07:06 -07:00
users . update ( req . params . userId , req . body , auditSource . fromRequest ( req ) , function ( error ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . BAD _FIELD ) return next ( new HttpError ( 400 , error . message ) ) ;
if ( error && error . reason === UsersError . ALREADY _EXISTS ) return next ( new HttpError ( 409 , error . message ) ) ;
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'User not found' ) ) ;
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2016-06-02 23:53:06 -07:00
next ( new HttpSuccess ( 204 ) ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2016-04-17 18:27:11 +02:00
function list ( req , res , next ) {
2019-01-14 16:39:20 +01:00
var page = typeof req . query . page !== 'undefined' ? parseInt ( req . query . page ) : 1 ;
if ( ! page || page < 0 ) return next ( new HttpError ( 400 , 'page query param has to be a postive number' ) ) ;
var perPage = typeof req . query . per _page !== 'undefined' ? parseInt ( req . query . per _page ) : 25 ;
if ( ! perPage || perPage < 0 ) return next ( new HttpError ( 400 , 'per_page query param has to be a postive number' ) ) ;
2019-01-15 17:21:40 +01:00
if ( req . query . search && typeof req . query . search !== 'string' ) return next ( new HttpError ( 400 , 'search must be a string' ) ) ;
users . getAllPaged ( req . query . search || null , page , perPage , function ( error , results ) {
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2016-06-03 00:04:17 -07:00
2018-06-25 15:54:24 -07:00
results = results . map ( users . removeRestrictedFields ) ;
2016-06-03 00:04:17 -07:00
2018-04-29 10:58:45 -07:00
next ( new HttpSuccess ( 200 , { users : results } ) ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2016-04-17 18:27:11 +02:00
function get ( req , res , next ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
2016-02-25 14:03:42 +01:00
assert . strictEqual ( typeof req . user , 'object' ) ;
2015-07-20 00:09:47 -07:00
2018-04-29 10:58:45 -07:00
users . get ( req . params . userId , function ( error , result ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'No such user' ) ) ;
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2018-04-29 10:58:45 -07:00
next ( new HttpSuccess ( 200 , users . removePrivateFields ( result ) ) ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2016-04-17 18:27:11 +02:00
function remove ( req , res , next ) {
2015-07-20 00:09:47 -07:00
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
2018-06-15 20:51:26 -07:00
if ( req . user . id === req . params . userId ) return next ( new HttpError ( 409 , 'Not allowed to remove yourself.' ) ) ;
2015-07-20 00:09:47 -07:00
2019-03-25 15:07:06 -07:00
users . remove ( req . params . userId , auditSource . fromRequest ( req ) , function ( error ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . BAD _FIELD ) return next ( new HttpError ( 400 , error . message ) ) ;
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'No such user' ) ) ;
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2016-06-02 22:25:48 -07:00
next ( new HttpSuccess ( 204 ) ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
function verifyPassword ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
2018-06-17 15:17:39 -07:00
if ( req . authInfo . skipPasswordVerification ) return next ( ) ; // using an 'sdk' token we skip password checks
2015-07-20 00:09:47 -07:00
if ( typeof req . body . password !== 'string' ) return next ( new HttpError ( 400 , 'API call requires user password' ) ) ;
2018-04-29 10:58:45 -07:00
users . verifyWithUsername ( req . user . username , req . body . password , function ( error ) {
2019-03-23 14:07:37 -07:00
if ( error && error . reason === UsersError . WRONG _PASSWORD ) return next ( new HttpError ( 403 , 'Password incorrect' ) ) ; // not 401 intentionally since the UI redirects for 401
2018-06-15 20:51:26 -07:00
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'No such user' ) ) ;
2015-07-20 00:09:47 -07:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2017-05-05 15:36:47 -07:00
req . body . password = '<redacted>' ; // this will prevent logs from displaying plain text password
2016-04-17 19:17:01 +02:00
next ( ) ;
2015-07-20 00:09:47 -07:00
} ) ;
}
2018-08-17 09:49:58 -07:00
function createInvite ( req , res , next ) {
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
users . createInvite ( req . params . userId , function ( error , resetToken ) {
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'User not found' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
next ( new HttpSuccess ( 200 , { resetToken : resetToken } ) ) ;
} ) ;
}
2016-01-18 15:37:03 +01:00
function sendInvite ( req , res , next ) {
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
2018-08-17 09:49:58 -07:00
users . sendInvite ( req . params . userId , { invitor : req . user } , function ( error ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'User not found' ) ) ;
2018-08-17 09:49:58 -07:00
if ( error && error . reason === UsersError . BAD _FIELD ) return next ( new HttpError ( 409 , 'Call createInvite API first' ) ) ;
2016-01-18 15:37:03 +01:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
2018-08-17 09:49:58 -07:00
next ( new HttpSuccess ( 200 , { } ) ) ;
2016-01-18 15:37:03 +01:00
} ) ;
}
2016-02-09 15:47:02 -08:00
function setGroups ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
if ( ! Array . isArray ( req . body . groupIds ) ) return next ( new HttpError ( 400 , 'API call requires a groups array.' ) ) ;
2018-06-18 13:57:17 -07:00
users . setMembership ( req . params . userId , req . body . groupIds , function ( error ) {
2018-04-29 17:37:53 -07:00
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'One or more groups not found' ) ) ;
2016-02-09 15:47:02 -08:00
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
next ( new HttpSuccess ( 204 ) ) ;
} ) ;
}
2018-06-28 16:48:04 -07:00
function transferOwnership ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
if ( typeof req . body . ownerId !== 'string' ) return next ( new HttpError ( 400 , 'ownerId must be a string' ) ) ;
2019-03-25 15:07:06 -07:00
users . transferOwnership ( req . params . userId , req . body . ownerId , auditSource . fromRequest ( req ) , function ( error ) {
2018-06-28 16:48:04 -07:00
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'No such user' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
next ( new HttpSuccess ( 200 , { } ) ) ;
} ) ;
2018-08-31 14:30:00 -07:00
}
function changePassword ( req , res , next ) {
assert . strictEqual ( typeof req . body , 'object' ) ;
assert . strictEqual ( typeof req . params . userId , 'string' ) ;
if ( typeof req . body . password !== 'string' ) return next ( new HttpError ( 400 , 'password must be a string' ) ) ;
users . setPassword ( req . params . userId , req . body . password , function ( error ) {
if ( error && error . reason === UsersError . BAD _FIELD ) return next ( new HttpError ( 400 , error . message ) ) ;
if ( error && error . reason === UsersError . NOT _FOUND ) return next ( new HttpError ( 404 , 'User not found' ) ) ;
if ( error ) return next ( new HttpError ( 500 , error ) ) ;
next ( new HttpSuccess ( 204 ) ) ;
} ) ;
}