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 @@ <> <> - <> + <> - + @@ -18,22 +18,24 @@ var btn = $(btn); currentEditHost = btn.data('host'); $('.editWindow').slideDown('fast'); - $('.editWindow .panel-body').slideDown('fast'); - $('.editWindow .panel-title .pull-left').html("Edit "+btn.data('host')) + $('.editWindow .panel-title .pull-left').html("Edit "+ btn.data('host')) $('div.editWindow .panel-body span').html($('#addHost').html()) $('div.editWindow .panel-body span button').remove() - app.hosts.get(currentEditHost, function(error, data){ - console.log(data) - $.each( data.results, function( key, val ) { + $(".editWindow input[name='edit_host']").val(btn.data('host')); - $(".editWindow input[name='" + key + "']").val(val); + app.host.get(currentEditHost, function(error, data){ + console.log(data) + $.each( data.results, function( key, value ) { + if(typeof value == "boolean"){ + $(".editWindow #"+ key +"-"+ value).prop('checked', true) + }else{ + $(".editWindow input[name='" + key + "']").val(value); + } + $('.editWindow .panel-body').slideDown('fast'); }); }); - // $.getJSON('api/hosts/' + btn.data('host'), function( data ) { - // $("input[name='old_host']").attr('value', btn.data('host')); - // }); } function tableAJAX(actionMessage){ @@ -41,16 +43,17 @@ $('#tableAJAX').html('').hide(); app.util.actionMessage('') - app.hosts.list(function(err, data){ - if(err) return app.util.actionMessage(err); + app.host.list(function(err, data){ + if(err) return app.util.actionMessage(err, {type: 'danger'}); if(data){ $.each(data, function( key, value ) { host_row = ich.rowTemplate(value); $('#tableAJAX').append(host_row); }); + app.util.actionMessage(actionMessage || '', {type: 'info'}); $('#tableAJAX').fadeIn('slow'); }else{ - app.util.actionMessage('No hosts...') + app.util.actionMessage('No hosts...', {type: 'info'}); } }); } @@ -59,16 +62,33 @@ tableAJAX(); //populate the table setInterval(tableAJAX, 30000); - $('#addHost').on('submit', function(){ + $('form.addHost').on('submit', function(){ event.preventDefault(); $form = $(this); + + var action = $($form.find('button[type="submit"]')[0]).data('type') + app.util.actionMessage('') if($form.attr('isValid') === 'true'){ - app.hosts.add($form.serializeObject(), function(error, data){ - app.util.actionMessage(data.message || 'Error!'); - if(!error) $form.trigger('reset'); + var formdata = $form.serializeObject(); + if(formdata.targetport) formdata.targetport = Number(formdata.targetport); + if(formdata.targetssl) formdata.targetssl = formdata.targetssl == 'true' ? true : false; + if(formdata.forcessl) formdata.forcessl = formdata.forcessl == 'true' ? true : false; + + app.host[action](formdata, function(error, data){ + if(error){ + console.log('error data',data) + app.util.actionMessage(error + data.message, {type: 'danger'}); + return; + } + + if(action == 'edit') $('.editWindow').slideUp('fast'); + + app.util.actionMessage(data.message || 'Error!', {type: 'info'}); + tableAJAX("Added "+ formdata.host); + $form.trigger('reset'); }) } }); @@ -88,9 +108,10 @@
-
+ - + +
@@ -106,19 +127,19 @@
-
+
@@ -126,38 +147,38 @@
- +

- +
- +
- +
@@ -195,4 +216,4 @@ -<%- include('bottom') %> \ No newline at end of file +<%- include('bottom') %> diff --git a/nodejs/views/login.ejs b/nodejs/views/login.ejs index f25800e..0a01dc8 100755 --- a/nodejs/views/login.ejs +++ b/nodejs/views/login.ejs @@ -1,27 +1,32 @@ <%- include('top') %> @@ -35,7 +40,7 @@
-
+
diff --git a/nodejs/views/login.ejs_org b/nodejs/views/login.ejs_org deleted file mode 100755 index 561815f..0000000 --- a/nodejs/views/login.ejs_org +++ /dev/null @@ -1,27 +0,0 @@ -<% include top %> -
-
-
-
-
Log in
-
-
- - - -
- - -
-
- - -
- - -
-
-
-
-<% include bottom %> \ No newline at end of file diff --git a/nodejs/views/top.ejs b/nodejs/views/top.ejs index 75af38f..ffa743d 100755 --- a/nodejs/views/top.ejs +++ b/nodejs/views/top.ejs @@ -13,7 +13,7 @@ - + @@ -21,7 +21,6 @@ -
diff --git a/nodejs/views/users.ejs b/nodejs/views/users.ejs index 88185ab..92d84d1 100755 --- a/nodejs/views/users.ejs +++ b/nodejs/views/users.ejs @@ -1,38 +1,45 @@ -<% include top %> +<%- include('top') %> - - -<% include bottom %> \ No newline at end of file