diff --git a/src/node/db/API.js b/src/node/db/API.js index 87b6d7473..237bcb0a7 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -307,6 +307,38 @@ exports.setText = function(padID, text, callback) }); } +/** +appendText(padID, text) appends text to a pad + +Example returns: + +{code: 0, message:"ok", data: null} +{code: 1, message:"padID does not exist", data: null} +{code: 1, message:"text too long", data: null} +*/ +exports.appendText = function(padID, text, callback) +{ + //text is required + if(typeof text != "string") + { + callback(new customError("text is no string","apierror")); + return; + } + + //get the pad + getPadSafe(padID, true, function(err, pad) + { + if(ERR(err, callback)) return; + + pad.appendText(text); + + //update the clients on the pad + padMessageHandler.updatePadClients(pad, callback); + }); +}; + + + /** getHTML(padID, [rev]) returns the html of a pad diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index eb6a3ed1b..83e15e6df 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -303,6 +303,19 @@ Pad.prototype.setText = function setText(newText) { this.appendRevision(changeset); }; +Pad.prototype.appendText = function appendText(newText) { + //clean the new text + newText = exports.cleanText(newText); + + var oldText = this.text(); + + //create the changeset + var changeset = Changeset.makeSplice(oldText, oldText.length, 0, newText); + + //append the changeset + this.appendRevision(changeset); +}; + Pad.prototype.appendChatMessage = function appendChatMessage(text, userId, time) { this.chatHead++; //save the chat entry in the database diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index b4d242011..179c2b404 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -444,10 +444,61 @@ var version = , "getChatHead" : ["padID"] , "restoreRevision" : ["padID", "rev"] } +, "1.2.13": + { "createGroup" : [] + , "createGroupIfNotExistsFor" : ["groupMapper"] + , "deleteGroup" : ["groupID"] + , "listPads" : ["groupID"] + , "listAllPads" : [] + , "createDiffHTML" : ["padID", "startRev", "endRev"] + , "createPad" : ["padID", "text"] + , "createGroupPad" : ["groupID", "padName", "text"] + , "createAuthor" : ["name"] + , "createAuthorIfNotExistsFor": ["authorMapper" , "name"] + , "listPadsOfAuthor" : ["authorID"] + , "createSession" : ["groupID", "authorID", "validUntil"] + , "deleteSession" : ["sessionID"] + , "getSessionInfo" : ["sessionID"] + , "listSessionsOfGroup" : ["groupID"] + , "listSessionsOfAuthor" : ["authorID"] + , "getText" : ["padID", "rev"] + , "setText" : ["padID", "text"] + , "getHTML" : ["padID", "rev"] + , "setHTML" : ["padID", "html"] + , "getAttributePool" : ["padID"] + , "getRevisionsCount" : ["padID"] + , "getSavedRevisionsCount" : ["padID"] + , "listSavedRevisions" : ["padID"] + , "saveRevision" : ["padID", "rev"] + , "getRevisionChangeset" : ["padID", "rev"] + , "getLastEdited" : ["padID"] + , "deletePad" : ["padID"] + , "copyPad" : ["sourceID", "destinationID", "force"] + , "movePad" : ["sourceID", "destinationID", "force"] + , "getReadOnlyID" : ["padID"] + , "getPadID" : ["roID"] + , "setPublicStatus" : ["padID", "publicStatus"] + , "getPublicStatus" : ["padID"] + , "setPassword" : ["padID", "password"] + , "isPasswordProtected" : ["padID"] + , "listAuthorsOfPad" : ["padID"] + , "padUsersCount" : ["padID"] + , "getAuthorName" : ["authorID"] + , "padUsers" : ["padID"] + , "sendClientsMessage" : ["padID", "msg"] + , "listAllGroups" : [] + , "checkToken" : [] + , "appendChatMessage" : ["padID", "text", "authorID", "time"] + , "getChatHistory" : ["padID"] + , "getChatHistory" : ["padID", "start", "end"] + , "getChatHead" : ["padID"] + , "restoreRevision" : ["padID", "rev"] + , "appendText" : ["padID", "text"] + } }; // set the latest available API version here -exports.latestApiVersion = '1.2.12'; +exports.latestApiVersion = '1.2.13'; // exports the versions so it can be used by the new Swagger endpoint exports.version = version; diff --git a/tests/backend/specs/api/pad.js b/tests/backend/specs/api/pad.js index 14e990911..e04033c04 100644 --- a/tests/backend/specs/api/pad.js +++ b/tests/backend/specs/api/pad.js @@ -79,6 +79,8 @@ describe('Permission', function(){ -> movePad(newPadID, originalPadId) -- Should provide consistant pad data -> getText(originalPadId) -- Should be "hello world" -> getLastEdited(padID) -- Should not be 0 + -> appendText(padID, "hello") + -> getText(padID) -- Should be "hello worldhello" -> setHTML(padID) -- Should fail on invalid HTML -> setHTML(padID) *3 -- Should fail on invalid HTML -> getHTML(padID) -- Should return HTML close to posted HTML @@ -483,6 +485,30 @@ describe('getLastEdited', function(){ }); }) +describe('appendText', function(){ + it('Append text to a pad Id', function(done) { + api.get(endPoint('appendText', '1.2.13')+"&padID="+testPadId+"&text=hello") + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Pad Append Text failed"); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); +}); + +describe('getText', function(){ + it('Gets text on a pad Id', function(done) { + api.get(endPoint('getText')+"&padID="+testPadId) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Pad Get Text failed"); + if(res.body.data.text !== text+"\nhello") throw new Error("Pad Text not set properly"); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); +}); + + describe('setHTML', function(){ it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) { var html = "