diff --git a/nodejs/app.js b/nodejs/app.js index f54c228..08fddb7 100755 --- a/nodejs/app.js +++ b/nodejs/app.js @@ -21,7 +21,7 @@ app.set('view engine', 'ejs'); app.use('/static', express.static(path.join(__dirname, 'public'))) // Routes for front end content. -app.use('/', require('./routes/index')); +app.use('/', require('./routes/index')); // API routes for authentication. app.use('/api/auth', require('./routes/auth')); diff --git a/nodejs/models/user.js b/nodejs/models/user.js index b157335..b68e768 100755 --- a/nodejs/models/user.js +++ b/nodejs/models/user.js @@ -110,13 +110,17 @@ User.addByInvite = async function(data){ }; +User.remove = async function(data){ + try{ + return await linuxUser.removeUser(this.username); + }catch(error){ + throw error; + } +}; + User.setPassword = async function(data){ try{ - if(!data.password1 || data.password1 !== data.password2){ - throw new Error('PasswordMismatch'); - } - - await linuxUser.setPassword(this.username, data.password1); + await linuxUser.setPassword(this.username, data.password); return this; }catch(error){ diff --git a/nodejs/public/js/layout.js b/nodejs/public/js/app.js similarity index 54% rename from nodejs/public/js/layout.js rename to nodejs/public/js/app.js index 111df6d..6c333b6 100755 --- a/nodejs/public/js/layout.js +++ b/nodejs/public/js/app.js @@ -23,6 +23,45 @@ app.api = (function(app){ }); } + function put(url, data, callack){ + $.ajax({ + type: 'PUT', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callack( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + + function remove(url, callack){ + $.ajax({ + type: 'delete', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callack( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + function get(url, callack){ $.ajax({ type: 'GET', @@ -42,7 +81,7 @@ app.api = (function(app){ }); } - return {post: post, get: get} + return {post: post, get: get, put: put, delete: remove} })(app) app.auth = (function(app) { @@ -56,11 +95,11 @@ app.auth = (function(app) { function isLoggedIn(callack){ if(getToken()){ - return app.api.get('users/me', function(error, data){ + return app.api.get('user/me', function(error, data){ return callack(error, data.username); }) }else{ - callack(false, false); + callack(null, false); } } @@ -73,20 +112,50 @@ app.auth = (function(app) { }); } + function logOut(){ + localStorage.removeItem('APIToken'); + } + return { getToken: getToken, isLoggedIn: isLoggedIn, - logIn:logIn + logIn: logIn, + logOut: logOut, } })(app); -app.users = (function(app){ +app.user = (function(app){ + function list(callack){ + app.api.get('user/?detail=true', function(error, data){ + callack(error, data); + }) + } + + function add(args, callack){ + app.api.post('user/', args, function(error, data){ + callack(error, data); + }); + } + + function remove(args, callack){ + app.api.delete('user/'+ args.username, function(error, data){ + callack(error, data); + }); + } + + function changePassword(args, callack){ + app.api.put('users/'+ arg.username || '', args, function(error, data){ + callack(error, data); + }); + } + function createInvite(callack){ - app.api.post('users/invite', function(error, data, status){ + app.api.post('user/invite', function(error, data, status){ callack(error, data.token); }); } + function consumeInvite(args){ app.api.post('/auth/invite/'+args.token, args, function(error, data){ if(data.token){ @@ -96,31 +165,48 @@ app.users = (function(app){ callack(error) }); } + + return {list, remove}; + })(app); -app.hosts = (function(app){ +app.host = (function(app){ function list(callack){ - app.api.get('hosts/?detail=true', function(error, data){ + app.api.get('host/?detail=true', function(error, data){ callack(error, data.hosts) }); } function get(host, callack){ - app.api.get('hosts/' + host, function(error, data){ + app.api.get('host/' + host, function(error, data){ callack(error, data) }); } function add(args, callack){ - app.api.post('hosts/', args, function(error, data){ + app.api.post('host/', args, function(error, data){ callack(error, data); }); } + function edit(args, callack){ + app.api.put('host/' + args.edit_host, args, function(error, data){ + callack(error, data); + }); + } + + function remove(args, callack){ + app.api.delete('host/'+ args.host, function(error, data){ + callack(error, data); + }) + } + return { list: list, get: get, - add: add + add: add, + edit: edit, + remove: remove, } })(app); @@ -133,18 +219,21 @@ app.util = (function(app){ return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); }; - function actionMessage(message, $target){ - $target = $target || $('div.actionMessage'); + function actionMessage(message, options){ + options = options || {}; + $target = options.$target || $('div.actionMessage'); + message = message || ''; if($target.html() === message) return; if($target.html()){ $target.slideUp('fast', function(){ $target.html('') - if(message) actionMessage(message); + if(message) actionMessage(message, options); }) return; }else{ + if(options.type) $target.addClass('alert-' + options.type); $target.html(message).slideDown('fast'); } } @@ -173,7 +262,18 @@ app.util = (function(app){ } })(app); - +$.holdReady( true ); +if(!location.pathname.includes('/login')){ + app.auth.isLoggedIn(function(error, isLoggedIn){ + if(error || !isLoggedIn){ + location.replace('/login/?redirect='+location.pathname); + }else{ + $.holdReady( false ); + } + }) +}else{ + $.holdReady( false ); +} $( document ).ready( function () { @@ -195,9 +295,14 @@ $( document ).ready( function () { //ajax form submit function formAJAX( btn, del ) { - var $form = $(btn).closest( '[action]' ), // gets the 'form' parent - str = $form.find( '[name]' ).serialize(); // builds query string - /*if( !$form.validate( + event.preventDefault(); // avoid to execute the actual submit of the form. + var $form = $(btn).closest( '[action]' ); // gets the 'form' parent + var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing + var method = $form.attr('method') || 'post'; + + console.log('formAJAX method', method) + + if( !$form.validate( { form: { alertCount: true, @@ -205,21 +310,11 @@ function formAJAX( btn, del ) { } }) ) { return false; - }*/ - if( del ){ // delete request - if( confirm( 'Are you sure?' ) ) { - str += "&deleteThis=true"; // adds delete to query string - }else{ - event.preventDefault(); // avoid to execute the actual submit of the form - return false; //cancels function - } } - $.post( $form.attr( 'action' ), str, function ( data ) { // sends post data to server validate - tableAJAX( data.action_message ); //re-populate table + app.api[method]($form.attr( 'action' ), formData, function(error, data){ + tableAJAX( data.message ); //re-populate table + eval( $form.attr( 'evalAJAX' ) ); //gets JS to run after completion }); - eval( $form.attr( 'evalAJAX' ) ); //gets JS to run after completion - event.preventDefault(); // avoid to execute the actual submit of the form. - return false; // avoid to execute the actual submit of the form. } diff --git a/nodejs/public/js/val.js b/nodejs/public/js/val.js index e71e987..d5a75bc 100755 --- a/nodejs/public/js/val.js +++ b/nodejs/public/js/val.js @@ -140,7 +140,7 @@ $.validateSettings({ password: function( value ) { var reg = /^(?=[^\d_].*?\d)\w(\w|[!@#$%]){1,48}/; if ( reg.test( value ) === false ) { - return "Try again"; + return "Weak password, Try again"; } } } diff --git a/nodejs/routes/auth.js b/nodejs/routes/auth.js index 0f1d1a4..3c5aa0d 100755 --- a/nodejs/routes/auth.js +++ b/nodejs/routes/auth.js @@ -17,6 +17,18 @@ router.post('/login', async function(req, res, next){ } }); +router.all('/logout', async function(req, res, next){ + try{ + if(req.user){ + await req.user.logout(); + } + + res.json({message: 'Bye'}) + }catch(error){ + next(error); + } +}); + router.post('/invite/:token', async function(req, res, next) { try{ req.body.token = req.params.token; diff --git a/nodejs/routes/host.js b/nodejs/routes/host.js index d7e7839..3139adb 100755 --- a/nodejs/routes/host.js +++ b/nodejs/routes/host.js @@ -30,7 +30,8 @@ router.get('/', async function(req, res, next){ router.put('/:host', async function(req, res, next){ try{ req.body.updated_by = req.user.username; - await Host.update(req.body, req.params.host); + let host = await Host.get(req.params.host); + await host.update(req.body); return res.json({ message: `Host "${req.params.host}" updated.` diff --git a/nodejs/routes/user.js b/nodejs/routes/user.js index 65c5947..7a09a4b 100755 --- a/nodejs/routes/user.js +++ b/nodejs/routes/user.js @@ -3,8 +3,33 @@ const router = require('express').Router(); const {User} = require('../models/user'); +router.get('/', async function(req, res, next){ + try{ + return res.json({results: await User.list()}); + }catch(error){ + next(error); + } +}); -router.get('/me', async function(req, res){ +router.post('/', async function(req, res, next){ + try{ + return res.json({results: await User.add(req.body)}); + }catch(error){ + next(error); + } +}); + +router.delete('/:username', async function(req, res, next){ + try{ + let user = await User.get(req.params.username); + + return res.json({username: req.params.username, results: await user.remove()}) + }catch(error){ + next(error); + } +}); + +router.get('/me', async function(req, res, next){ try{ return res.json({username: req.user.username}); }catch(error){ @@ -12,6 +37,23 @@ router.get('/me', async function(req, res){ } }); +router.put('/password', async function(req, res, next){ + try{ + return res.json({results: await req.user.setPassword(req.body)}) + }catch(error){ + next(error); + } +}); + +router.put('/password/:username', async function(req, res, next){ + try{ + let user = await User.get(req.params.username); + return res.json({results: await user.setPassword(req.body)}); + }catch(error){ + next(error); + } +}); + router.post('/invite', async function(req, res, next){ try{ let token = await req.user.invite(); diff --git a/nodejs/utils/object_validate.js b/nodejs/utils/object_validate.js index cbbf648..6295c48 100644 --- a/nodejs/utils/object_validate.js +++ b/nodejs/utils/object_validate.js @@ -27,7 +27,7 @@ function processKeys(map, data, partial){ continue; } - if(data.hasOwnProperty(key) && typeof(data[key]) !== map[key].type){ + if(data.hasOwnProperty(key) && map[key].type && typeof(data[key]) !== map[key].type){ errors.push({key, message:`${key} is not ${map[key].type} type.`}); continue; } diff --git a/nodejs/views/hosts.ejs b/nodejs/views/hosts.ejs index d87e542..8542c45 100755 --- a/nodejs/views/hosts.ejs +++ b/nodejs/views/hosts.ejs @@ -4,10 +4,10 @@