diff --git a/node/db/API.js b/node/db/API.js index 3fcaafeb5..c55385d85 100644 --- a/node/db/API.js +++ b/node/db/API.js @@ -289,7 +289,14 @@ exports.setPublicStatus = function(padID, publicStatus, callback) return; } + //convert string to boolean + if(typeof publicStatus == "string") + publicStatus = publicStatus == "true" ? true : false; + //set the password + pad.setPublicStatus(publicStatus); + + callback(); }); } @@ -312,7 +319,7 @@ exports.getPublicStatus = function(padID, callback) return; } - + callback(null, {publicStatus: pad.getPublicStatus()}); }); } @@ -335,7 +342,10 @@ exports.setPassword = function(padID, password, callback) return; } + //set the password + pad.setPassword(password); + callback(); }); } @@ -358,7 +368,7 @@ exports.isPasswordProtected = function(padID, callback) return; } - + callback(null, {isPasswordProtected: pad.isPasswordProtected()}); }); } diff --git a/node/db/Pad.js b/node/db/Pad.js index 982ba1c35..3511728fe 100644 --- a/node/db/Pad.js +++ b/node/db/Pad.js @@ -8,6 +8,7 @@ var db = require("./DB").db; var async = require("async"); var settings = require('../utils/Settings'); var authorManager = require("./AuthorManager"); +var crypto = require("crypto"); /** * Copied from the Etherpad source code. It converts Windows line breaks to Unix line breaks and convert Tabs to spaces @@ -44,6 +45,17 @@ Class('Pad', { init: -1 }, // chatHead + publicStatus : { + is: 'rw', + init: false, + getterName : 'getPublicStatus' + }, //publicStatus + + passwordHash : { + is: 'rw', + init: null + }, // passwordHash + id : { is : 'r' } }, @@ -82,7 +94,12 @@ Class('Pad', { } db.set("pad:"+this.id+":revs:"+newRev, newRevData); - db.set("pad:"+this.id, {atext: this.atext, pool: this.pool.toJsonable(), head: this.head, chatHead: this.chatHead}); + db.set("pad:"+this.id, {atext: this.atext, + pool: this.pool.toJsonable(), + head: this.head, + chatHead: this.chatHead, + publicStatus: this.publicStatus, + passwordHash: this.passwordHash}); }, //appendRevision getRevisionChangeset : function(revNum, callback) @@ -336,10 +353,23 @@ Class('Pad', { _this.atext = value.atext; _this.pool = _this.pool.fromJsonable(value.pool); + //ensure we have a local chatHead variable if(value.chatHead != null) _this.chatHead = value.chatHead; else _this.chatHead = -1; + + //ensure we have a local publicStatus variable + if(value.publicStatus != null) + _this.publicStatus = value.publicStatus; + else + _this.publicStatus = false; + + //ensure we have a local passwordHash variable + if(value.passwordHash != null) + _this.passwordHash = value.passwordHash; + else + _this.passwordHash = null; } //this pad doesn't exist, so create it else @@ -351,7 +381,52 @@ Class('Pad', { callback(null); }); - } - + }, + //set in db + setPublicStatus: function(publicStatus) + { + this.publicStatus = publicStatus; + db.setSub("pad:"+this.id, ["publicStatus"], this.publicStatus); + }, + setPassword: function(password) + { + this.passwordHash = password == null ? null : hash(password, generateSalt()); + db.setSub("pad:"+this.id, ["passwordHash"], this.passwordHash); + }, + isCorrectPassword: function(password) + { + return compare(this.passwordHash, password) + }, + isPasswordProtected: function() + { + return this.passwordHash != null; + } }, // methods }); + +/* Crypto helper methods */ + +function hash(password, salt) +{ + var shasum = crypto.createHash('sha512'); + shasum.update(password + salt); + return shasum.digest("hex") + "$" + salt; +} + +function generateSalt() +{ + var len = 86; + var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; + var randomstring = ''; + for (var i = 0; i < len; i++) + { + var rnum = Math.floor(Math.random() * chars.length); + randomstring += chars.substring(rnum, rnum + 1); + } + return randomstring; +} + +function compare(hashStr, password) +{ + return hash(password, hashStr.split("$")[1]) === hashStr; +} diff --git a/node/handler/APIHandler.js b/node/handler/APIHandler.js index 102178556..fc457f808 100644 --- a/node/handler/APIHandler.js +++ b/node/handler/APIHandler.js @@ -52,11 +52,11 @@ var functions = { "setText" : ["padID", "text"], "getRevisionsCount" : ["padID"], // "deletePad" : ["padID"], - "getReadOnlyID" : ["padID"] -// "setPublicStatus" : ["padID", "publicStatus"], -// "getPublicStatus" : ["padID"], -// "setPassword" : ["padID", "password"], -// "isPasswordProtected" : ["padID"] + "getReadOnlyID" : ["padID"], + "setPublicStatus" : ["padID", "publicStatus"], + "getPublicStatus" : ["padID"], + "setPassword" : ["padID", "password"], + "isPasswordProtected" : ["padID"] }; /** diff --git a/static/tests.html b/static/tests.html index 855d1ca45..f15f4567e 100644 --- a/static/tests.html +++ b/static/tests.html @@ -156,7 +156,7 @@
getRevisionsCount(padID)
deletePad(padID)
getReadOnlyID(padID)
-
setPublicStatus(padID,publicStatud)
+
setPublicStatus(padID,publicStatus)
getPublicStatus(padID)
setPassword(padID,password)
isPasswordProtected(padID)