diff --git a/README.md b/README.md index 51cbd46..ae01822 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,10 @@ they will be visible to forever, via sudo only. [\[1\]][1] ## Add a users.json file -Add a `users.json` to the root of forever-webui -``` [{ - "username" : "here the name of your user", - "password" : "here the password for your user" -}] ``` + node add_user +``` +this will create a users.json file if it doesn't exist yet and adds a new user via prompt. ## Run Tests diff --git a/add_user.js b/add_user.js new file mode 100644 index 0000000..0c5b427 --- /dev/null +++ b/add_user.js @@ -0,0 +1,71 @@ +var colors = require('colors/safe'); +var fs = require('fs'); +var readline = require('readline'); +var CryptoJS = require("crypto-js"); + +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false +}); + +var ticker = 0; +var user = {}; +var users; +var usersFile; + +if (fs.existsSync('users.json')) { + try { + var usersFile = fs.readFileSync('users.json', 'utf8'); + users = JSON.parse(usersFile); + console.info(colors.green('Found users.json file')); + console.info(colors.green('Contains '+ users.length + ' users')); + } catch (e) { + console.error(colors.red('users.json is not a valid json')); + } +} else { + var fd = fs.openSync('users.json', 'w'); + console.info(colors.green('users.json file created')); + users = []; +} + + +console.log(colors.yellow.underline('Create a user:')); +console.log(colors.yellow('Enter the username:')); + +// found on http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript +function generateUUID(){ + var d = new Date().getTime(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c=='x' ? r : (r&0x3|0x8)).toString(16); + }); + return uuid; +} + + +rl.on('line', function(line){ + switch (ticker) { + case 0: + user.username = line; + console.log(colors.yellow('Enter the password:')); + + break; + case 1: + user.password = CryptoJS.SHA256(line).toString(CryptoJS.enc.Hex); + user.id = generateUUID(); + users.push(user); + fs.writeFile("users.json", JSON.stringify(users), function(err) { + if(err) { + return console.log(err); + } + + console.log("The file was saved!"); + }); + rl.close(); + break; + } + ticker++; +}); + diff --git a/app.js b/app.js index 89881fe..0766b04 100644 --- a/app.js +++ b/app.js @@ -23,15 +23,20 @@ session = require('express-session'); errorhandler = require('errorhandler'); router = express.Router(); + CryptoJS = require("crypto-js"); var users; try { var usersFile = fs.readFileSync('users.json', 'utf8'); users = JSON.parse(usersFile); + if (users.length === 0) { + throw new Error('no users in users.json'); + } logger.info('Loaded users'); } catch (e) { - logger.warn('Make a users.json file in the root of the project'); + logger.warn('Run: node add_user.js to add a user.'); logger.error(e); + process.exit(0); } process.on("uncaughtException", function(err) { @@ -125,9 +130,9 @@ }; function findById(id, fn) { - var idx = id - 1; - if (users[idx]) { - fn(null, users[idx]); + var user = _.findWhere(users,{id:id}); + if (user) { + fn(null, user); } else { fn(new Error('User ' + id + ' does not exist')); } @@ -183,13 +188,16 @@ passport.use(new LocalStrategy( function(username, password, done) { + if (!users) { + return done(null, false, { message: 'The system has no users'}); + } process.nextTick(function () { findByUsername(username, function(err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Unknown user ' + username }); } - if (user.password != password) { return done(null, false, { message: 'Invalid password' }); } + if (user.password != CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex)) { return done(null, false, { message: 'Invalid password' }); } return done(null, user); }); }); diff --git a/package.json b/package.json index 261c4ad..059ff64 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "coffee-script": "1.5.0", "colors": "^1.0.3", "cookie-parser": "^1.3.4", + "crypto-js": "^3.1.4", "ejs": "0.8.3", "errorhandler": "^1.3.5", "express": "4.12.2", diff --git a/public/dist/foreverui.min.css b/public/dist/foreverui.min.css index afd3f4a..4173940 100644 --- a/public/dist/foreverui.min.css +++ b/public/dist/foreverui.min.css @@ -1,4 +1,4 @@ -/*! forever-webui - v0.2.1 - 2015-04-28 +/*! forever-webui - v0.2.1 - 2015-05-04 * Copyright (c) 2015 ; */ html,body{margin:0;padding:0;} h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,cite,code,del,dfn,em,img,q,s,samp,small,strike,strong,sub,sup,tt,var,dd,dl,dt,li,ol,ul,fieldset,form,label,legend,button,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;} diff --git a/public/dist/foreverui.min.js b/public/dist/foreverui.min.js index 5498dd7..7404b7b 100644 --- a/public/dist/foreverui.min.js +++ b/public/dist/foreverui.min.js @@ -1,3 +1,3 @@ -/*! forever-webui - v0.2.1 - 2015-04-28 +/*! forever-webui - v0.2.1 - 2015-05-04 * Copyright (c) 2015 ; */ App.Process=Backbone.Model.extend({defaults:{uid:"",ctime:0,command:"",pid:0,foreverPid:0,logFile:"",options:[],file:"",pidFile:"",outFile:"",errFile:"",sourceDir:""},initialize:function(e){this.attributes.time=prettyDate(e.ctime),_.each(["info","stop","restart"],this._makeMethod,this)},_makeMethod:function(e){this[e]=function(t){$.ajax("/"+e+"/"+this.get("uid")).complete(function(e){t(JSON.parse(e.responseText))})}}}),App.ProcessList=Backbone.Collection.extend({model:App.Process,url:"/processes",comparator:function(e){return e.get("file")},getByPID:function(e){return this.detect(function(t){return t.get("pid")==e})}}),App.ProcessView=Backbone.View.extend({tagName:"div",className:"row",tmpl:$("#process-tmpl").html(),tmplInfo:$("#tplInfo"),events:{"click .info":"info","click .restart":"restart","click .stop":"stop"},initialize:function(){this.model.bind("destroy",this.remove,this)},render:function(){return $(this.el).html(Mustache.to_html(this.tmpl,this.model.toJSON())),this},info:function(e){e&&e.preventDefault();var t=$(this.el);t.addClass("load"),this.model.info(function(e){this._showInfo(t,e),t.removeClass("load")}.bind(this))},restart:function(e){e&&e.preventDefault();var t=$(this.el);t.addClass("load"),this.model.restart(function(){t.removeClass("load"),_.delay(this.model.collection.fetch.bind(this.model.collection),1e3)}.bind(this))},stop:function(e){e&&e.preventDefault();var t=$(this.el);t.addClass("load"),this.model.stop(function(){t.removeClass("load"),_.delay(this.model.collection.fetch.bind(this.model.collection),1e3)}.bind(this))},remove:function(){$(this.el).remove()},_formatInfo:function(e){if("error"==e.status)return $(""+e.details+"");var t=$("
");return e.details.forEach(function(e){var s="";t.append(e[0]);for(var o=0,i=e[1].length;i>o;o++)s+=""+e[1][o].text+"";t.append('
'+s+"
")}),t},_showInfo:function(e,t){var s=e.next();(0==s.length||s.is(".row"))&&(s=this.tmplInfo.clone().removeClass("hidden").insertAfter(e).alert()),"error"==t.status&&s.removeClass("info").addClass("error"),s.find(".alert-message-content").html(this._formatInfo(t)).find("pre").each(function(){this.scrollTop=9e5})}}),App.AppView=Backbone.View.extend({el:$(".container"),events:{"click .refresh":"refresh"},initialize:function(e){this.Processes=new App.ProcessList,this.Processes.bind("all",this.updateAll,this),this.Processes.reset(e),this.$("#app-version").text(App.version),document.title+=App.version},addOne:function(e){var t=new App.ProcessView({model:e});this.$("#process-list").append(t.render().el)},updateAll:function(){this.$("#process-list").empty(),this.Processes.each(this.addOne,this),this.render()},refresh:function(){this.Processes.fetch()},render:function(){this.$("#process-count").text(this.Processes.length)}}),App.ModalView=Backbone.View.extend({tmpl:$("#modal-template").html(),events:{"click .closeProcess":"close","click .addProcess":"addProcess"},initialize:function(){this.model=new Backbone.Model,this.model.bind("destroy",this.remove,this)},render:function(){return $(this.el).html(Mustache.to_html(this.tmpl,this.model.toJSON())),this},show:function(){$(document.body).append(this.render().el),$("#process-args-input").focus()},close:function(){this.remove()},addProcess:function(){if($("#process-args-input").val()){var e=$.ajax({url:"/addProcess",type:"post",data:{args:encodeURIComponent($("#process-args-input").val())}});e.success(function(){var e=setTimeout(function(){$(".refresh").trigger("click"),clearTimeout(e)},3e3)}),e.error(function(e,t,s){console.error("The following error occured: "+t,s)})}this.remove()}}),App.AddProcess=Backbone.View.extend({el:$("body"),events:{"click #addProcess-modal":"showmodal","click .closeProcess":"closemodal","click .addProcess":"addProcess"},initialize:function(){this.addProcessModal=new App.ModalView},showmodal:function(){this.addProcessModal.show()},closemodal:function(){this.addProcessModal.close()},addProcess:function(){this.addProcessModal.addProcess()}}); \ No newline at end of file