diff --git a/src/node/db/API.js b/src/node/db/API.js index 5bb83f02..39b37959 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -440,8 +440,8 @@ exports.getChatHistory = function(padID, start, end, callback) // fall back to getting the whole chat-history if a parameter is missing if(!start || !end) { - start = 0; - end = pad.chatHead; + start = 0; + end = pad.chatHead; } if(start >= chatHead && chatHead > 0) @@ -552,6 +552,44 @@ exports.deletePad = function(padID, callback) }); } +/** +copyPad(padID, newID) copies a pad + +Example returns: + +{code: 0, message:"ok", data: null} +{code: 1, message:"padID does not exist", data: null} +*/ +exports.copyPad = function(padID, newID, callback) +{ + getPadSafe(padID, true, function(err, pad) + { + if(ERR(err, callback)) return; + + pad.copy(newID, callback); + }); +} + +/** +movePad(padID, newID) moves a pad + +Example returns: + +{code: 0, message:"ok", data: null} +{code: 1, message:"padID does not exist", data: null} +*/ +exports.movePad = function(padID, newID, callback) +{ + getPadSafe(padID, true, function(err, pad) + { + if(ERR(err, callback)) return; + + pad.copy(newID, function(err) { + if(ERR(err, callback)) return; + pad.remove(callback); + }); + }); +} /** getReadOnlyLink(padID) returns the read only link of a pad diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 4701e82a..7c2f63aa 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -13,6 +13,8 @@ var settings = require('../utils/Settings'); var authorManager = require("./AuthorManager"); var padManager = require("./PadManager"); var padMessageHandler = require("../handler/PadMessageHandler"); +var groupManager = require("./GroupManager"); +var customError = require("../utils/customError"); var readOnlyManager = require("./ReadOnlyManager"); var crypto = require("crypto"); var randomString = require("../utils/randomstring"); @@ -404,6 +406,118 @@ Pad.prototype.init = function init(text, callback) { }); }; +Pad.prototype.copy = function copy(newID, callback) { + var padID = this.id; + var _this = this; + + //kick everyone from this pad + // TODO: this presents a message on the client saying that the pad was 'deleted'. Fix this? + padMessageHandler.kickSessionsFromPad(padID); + + // flush the source pad: + _this.saveToDatabase(); + + async.series([ + // if it's a group pad, let's make sure the group exists. + function(callback) + { + if (newID.indexOf("$") != -1) + { + groupManager.doesGroupExist(newID.split("$")[0], function (err, exists) + { + if(ERR(err, callback)) return; + + //group does not exist + if(exists == false) + { + callback(new customError("groupID does not exist","apierror")); + } + //everything is fine, continue + else + { + callback(); + } + }); + } + callback(); + }, + // if the pad exists, we should abort. + function(callback) + { + padManager.doesPadExists(newID, function (err, exists) + { + if(ERR(err, callback)) return; + + if(exists == true) + { + callback(new customError("new padID already exists","apierror")); + } + //everything is fine, continue + else + { + db.get("pad:"+padID, function(err, pad) { + db.set("pad:"+newID, pad); + callback(); + }); + } + }); + }, + //delete all relations + function(callback) + { + async.parallel([ + //copy all chat messages + function(callback) + { + var chatHead = _this.chatHead; + + for(var i=0;i<=chatHead;i++) + { + db.get("pad:"+padID+":chat:"+i, function (err, chat) { + db.set("pad:"+newID+":chat:"+i, chat); + }); + } + + callback(); + }, + //copy all revisions + function(callback) + { + var revHead = _this.head; + + for(var i=0;i<=revHead;i++) + { + db.get("pad:"+padID+":revs:"+i, function (err, rev) { + if (ERR(err, callback)) return; + db.set("pad:"+newID+":revs:"+i, rev); + }); + } + + callback(); + }, + //add the new pad to all authors who contributed to the old one + function(callback) + { + var authorIDs = _this.getAllAuthors(); + + authorIDs.forEach(function (authorID) + { + authorManager.addPad(authorID, newID); + }); + + callback(); + }, + // parallel + ], callback); + }, + // series + ], function(err) + { + if(ERR(err, callback)) return; + callback(null, {padID: newID}); + }); +}; + Pad.prototype.remove = function remove(callback) { var padID = this.id; var _this = this; diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index cba13f9b..7df0864d 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -240,6 +240,8 @@ var version = , "getRevisionChangeset" : ["padID", "rev"] , "getLastEdited" : ["padID"] , "deletePad" : ["padID"] + , "copyPad" : ["padID", "newID"] + , "movePad" : ["padID", "newID"] , "getReadOnlyID" : ["padID"] , "setPublicStatus" : ["padID", "publicStatus"] , "getPublicStatus" : ["padID"]