import express from 'express'; import mongoose from 'mongoose'; import bcrypt from 'bcryptjs'; import UserValidate from './validate/user'; import UserModel from '../models/user'; import mail from '../helpers/mail'; const router = express.Router(); router.get('/users', (req, res) => { if (!req.auth(res, ['admin'], 'basic')) return; UserModel.find({}).lean().exec( (err, data:any) => { res.json(data.map(e => UserValidate.output(e)).filter(e => e !== null)); // validate all and filter null values from validation errors }); }); router.get('/user:username([/](?!key|new).?*|/?)', (req, res, next) => { // this path matches /user, /user/ and /user/xxx, but not /user/key or user/new. See https://forbeslindesay.github.io/express-route-tester/ for the generated regex req.params.username = req.params[0]; if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return; let username = req.authDetails.username; if (req.params.username !== undefined) { if (!req.auth(res, ['admin'], 'basic')) return; username = req.params.username; } UserModel.findOne({name: username}).lean().exec( (err, data:any) => { if (err) next(err); if (data) { res.json(UserValidate.output(data)); // validate all and filter null values from validation errors } else { res.status(404).json({status: 'Not found'}); } }); }); router.put('/user:username([/](?!key|new).?*|/?)', (req, res, next) => { // this path matches /user, /user/ and /user/xxx, but not /user/key or user/new console.log(req.authDetails); if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return; let username = req.authDetails.username; if (req.params.username !== undefined) { if (!req.auth(res, ['admin'], 'basic')) return; username = req.params.username; } const {error, value: user} = UserValidate.input(req.body, 'change' + (req.authDetails.level === 'admin'? 'admin' : '')); console.log(error); console.log(user); if(error !== undefined) { res.status(400).json({status: 'Invalid body format'}); return; } if (user.hasOwnProperty('pass')) { user.pass = bcrypt.hashSync(user.pass, 10); } // check that user does not already exist if new name was specified if (user.hasOwnProperty('name') && user.name !== username) { UserModel.find({name: user.name}).lean().exec( (err, data:any) => { if (err) next(err); if (data.length > 0) { res.status(400).json({status: 'Username already taken'}); return; } UserModel.findOneAndUpdate({name: username}, user, {new: true}).lean().exec( (err, data:any) => { if (err) next(err); if (data) { res.json(UserValidate.output(data)); // validate all and filter null values from validation errors } else { res.status(404).json({status: 'Not found'}); } }); }); } else { UserModel.findOneAndUpdate({name: username}, user, {new: true}).lean().exec( (err, data:any) => { if (err) next(err); if (data) { res.json(UserValidate.output(data)); // validate all and filter null values from validation errors } else { res.status(404).json({status: 'Not found'}); } }); } }); router.get('/user/key', (req, res, next) => { console.log('hmm'); if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'basic')) return; UserModel.findOne({name: req.authDetails.username}).lean().exec( (err, data:any) => { if (err) next(err); res.json({key: data.key}); }); }); router.post('/user/new', (req, res, next) => { if (!req.auth(res, ['admin'], 'basic')) return; // validate input const {error, value: user} = UserValidate.input(req.body, 'new'); if(error !== undefined) { res.status(400).json({status: 'Invalid body format'}); return; } // check that user does not already exist UserModel.find({name: user.name}).lean().exec( (err, data:any) => { if (err) next(err); if (data.length > 0) { res.status(400).json({status: 'Username already taken'}); return; } user.key = mongoose.Types.ObjectId(); // use object id as unique API key bcrypt.hash(user.pass, 10, (err, hash) => { // password hashing user.pass = hash; new UserModel(user).save((err, data) => { // store user if (err) next(err); res.json(UserValidate.output(data.toObject())); }); }); }); }); router.post('/user/passreset', (req, res, next) => { // check if user/email combo exists UserModel.find({name: req.body.name, email: req.body.email}).lean().exec( (err, data: any) => { if (err) next(err); if (data.length === 1) { // it exists const newPass = Math.random().toString(36).substring(2); bcrypt.hash(newPass, 10, (err, hash) => { // password hashing if (err) next(err); UserModel.findByIdAndUpdate(data[0]._id, {pass: hash}, err => { // write new password if (err) next(err); mail(data[0].email, 'Your new password for the DFOP database', 'Hi,

You requested to reset your password.
Your new password is:

' + newPass + '

If you did not request a password reset, talk to the sysadmin quickly!

Have a nice day.

The DFOP team', err => { if (err) next(err); res.json({status: 'OK'}); }); }); }); } else { res.status(404).json({status: 'Not found'}); } }); }); module.exports = router;