Validate users routes

master
Mark Moffat 2019-11-16 20:07:48 +10:30
parent 5b3ee2a734
commit f45698088a
4 changed files with 113 additions and 7 deletions

24
lib/schemas/editUser.json Normal file
View File

@ -0,0 +1,24 @@
{
"$id": "editUser",
"type": "object",
"properties": {
"usersName": {
"type": "string"
},
"userEmail": {
"type": "string",
"format": "emailAddress"
},
"userPassword": {
"type": "string"
},
"isAdmin": {
"type": "boolean"
}
},
"required": [
"usersName",
"userEmail",
"isAdmin"
]
}

25
lib/schemas/newUser.json Normal file
View File

@ -0,0 +1,25 @@
{
"$id": "newUser",
"type": "object",
"properties": {
"usersName": {
"type": "string"
},
"userEmail": {
"type": "string",
"format": "emailAddress"
},
"userPassword": {
"type": "string"
},
"isAdmin": {
"type": "boolean"
}
},
"required": [
"usersName",
"userEmail",
"userPassword",
"isAdmin"
]
}

View File

@ -3,6 +3,7 @@ const common = require('../lib/common');
const { restrict } = require('../lib/auth'); const { restrict } = require('../lib/auth');
const colors = require('colors'); const colors = require('colors');
const bcrypt = require('bcryptjs'); const bcrypt = require('bcryptjs');
const { validateJson } = require('../lib/schema');
const router = express.Router(); const router = express.Router();
router.get('/admin/users', restrict, async (req, res) => { router.get('/admin/users', restrict, async (req, res) => {
@ -212,6 +213,19 @@ router.post('/admin/user/update', restrict, async (req, res) => {
updateDoc.userPassword = bcrypt.hashSync(req.body.userPassword); updateDoc.userPassword = bcrypt.hashSync(req.body.userPassword);
} }
// Validate update user
const schemaResult = validateJson('editUser', updateDoc);
if(!schemaResult.result){
if(req.apiAuthenticated){
res.status(400).json(schemaResult.errors);
return;
}
req.session.message = 'Please check your inputs.';
req.session.messageType = 'danger';
res.redirect('/admin/user/edit/' + req.body.userId);
return;
}
try{ try{
await db.users.updateOne( await db.users.updateOne(
{ _id: common.getId(req.body.userId) }, { _id: common.getId(req.body.userId) },
@ -220,11 +234,11 @@ router.post('/admin/user/update', restrict, async (req, res) => {
}, { multi: false } }, { multi: false }
); );
if(req.apiAuthenticated){ if(req.apiAuthenticated){
res.status(200).json({ message: 'User account updated.' }); res.status(200).json({ message: 'User account updated' });
return; return;
} }
// show the view // show the view
req.session.message = 'User account updated.'; req.session.message = 'User account updated';
req.session.messageType = 'success'; req.session.messageType = 'success';
res.redirect('/admin/user/edit/' + req.body.userId); res.redirect('/admin/user/edit/' + req.body.userId);
}catch(ex){ }catch(ex){
@ -244,7 +258,7 @@ router.post('/admin/user/insert', restrict, async (req, res) => {
const db = req.app.db; const db = req.app.db;
// set the account to admin if using the setup form. Eg: First user account // set the account to admin if using the setup form. Eg: First user account
const urlParts = new URL(req.header('Referer')); const urlParts = req.get('Referrer');
// Check number of users // Check number of users
const userCount = await db.users.countDocuments({}); const userCount = await db.users.countDocuments({});
@ -255,13 +269,26 @@ router.post('/admin/user/insert', restrict, async (req, res) => {
isAdmin = true; isAdmin = true;
} }
const doc = { const userObj = {
usersName: req.body.usersName, usersName: req.body.usersName,
userEmail: req.body.userEmail, userEmail: req.body.userEmail,
userPassword: bcrypt.hashSync(req.body.userPassword, 10), userPassword: bcrypt.hashSync(req.body.userPassword, 10),
isAdmin: isAdmin isAdmin: isAdmin
}; };
// Validate new user
const schemaResult = validateJson('newUser', userObj);
if(!schemaResult.result){
if(req.apiAuthenticated){
res.status(400).json(schemaResult.errors);
return;
}
req.session.message = 'Invalid new user. Please check your inputs.';
req.session.messageType = 'danger';
res.redirect('/admin/user/new');
return;
}
// check for existing user // check for existing user
const user = await db.users.findOne({ userEmail: req.body.userEmail }); const user = await db.users.findOne({ userEmail: req.body.userEmail });
if(user){ if(user){
@ -278,10 +305,10 @@ router.post('/admin/user/insert', restrict, async (req, res) => {
} }
// email is ok to be used. // email is ok to be used.
try{ try{
await db.users.insertOne(doc); await db.users.insertOne(userObj);
// if from setup we add user to session and redirect to login. // if from setup we add user to session and redirect to login.
// Otherwise we show users screen // Otherwise we show users screen
if(urlParts.path === '/admin/setup'){ if(urlParts && urlParts.path === '/admin/setup'){
req.session.user = req.body.userEmail; req.session.user = req.body.userEmail;
res.redirect('/admin/login'); res.redirect('/admin/login');
return; return;
@ -295,11 +322,11 @@ router.post('/admin/user/insert', restrict, async (req, res) => {
req.session.messageType = 'success'; req.session.messageType = 'success';
res.redirect('/admin/users'); res.redirect('/admin/users');
}catch(ex){ }catch(ex){
console.error(colors.red('Failed to insert user: ' + ex));
if(req.apiAuthenticated){ if(req.apiAuthenticated){
res.status(400).json({ message: 'New user creation failed' }); res.status(400).json({ message: 'New user creation failed' });
return; return;
} }
console.error(colors.red('Failed to insert user: ' + ex));
req.session.message = 'New user creation failed'; req.session.message = 'New user creation failed';
req.session.messageType = 'danger'; req.session.messageType = 'danger';
res.redirect('/admin/user/new'); res.redirect('/admin/user/new');

View File

@ -60,3 +60,33 @@ test('[Fail] Delete invalid user ID', async t => {
.expect(302); .expect(302);
t.deepEqual(res.header['location'], '/admin/users'); t.deepEqual(res.header['location'], '/admin/users');
}); });
test('[Success] Create new user', async t => {
const user = {
usersName: 'Jim Smith',
userEmail: 'jim.smith@gmail.com',
userPassword: 'test',
isAdmin: false
};
const res = await g.request
.post('/admin/user/insert')
.send(user)
.set('apiKey', g.users[0].apiKey)
.expect(200);
t.deepEqual(res.body.message, 'User account inserted');
});
test('[Fail] Create new user with invalid email', async t => {
const user = {
usersName: 'Jim Smith',
userEmail: 'jim.smith@gmail',
userPassword: 'test',
isAdmin: false
};
const res = await g.request
.post('/admin/user/insert')
.send(user)
.set('apiKey', g.users[0].apiKey)
.expect(400);
t.deepEqual(res.body[0].message, 'should match format "emailAddress"');
});