Index: lams_build/conf/whiteboard/readme.txt =================================================================== diff -u -r6583579862c8623515c9861dd8edec09b6d1898f -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_build/conf/whiteboard/readme.txt (.../readme.txt) (revision 6583579862c8623515c9861dd8edec09b6d1898f) +++ lams_build/conf/whiteboard/readme.txt (.../readme.txt) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -13,4 +13,7 @@ 3.2 In server.js we set up default port to 9003 instead of 8080, so it does not collide with WildFly development mode. - 3.3 In server-backend.js we introduce hashing of wid + accesstoken to improve security \ No newline at end of file + 3.3 In server-backend.js we introduce hashing of wid + accesstoken to improve security. + Also an API method is added to copy Whiteboard canvas on tool content copy. + + 3.4 In s_whiteboard.js we introduce methods for copying canvas contents. \ No newline at end of file Index: lams_build/conf/whiteboard/scripts/s_whiteboard.js =================================================================== diff -u --- lams_build/conf/whiteboard/scripts/s_whiteboard.js (revision 0) +++ lams_build/conf/whiteboard/scripts/s_whiteboard.js (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -0,0 +1,140 @@ +//This file is only for saving the whiteboard. +const fs = require("fs"); +const config = require("./config/config"); + +var savedBoards = {}; +var savedUndos = {}; +var saveDelay = false; + +if (config.backend.enableFileDatabase) { + //read saved boards from file + fs.readFile("savedBoards.json", (err, data) => { + if (err) { + return console.log( + "No persistend Whiteboard Datafile found... this is not a problem on the first start!" + ); + } + savedBoards = JSON.parse(data); + }); +} + +module.exports = { + handleEventsAndData: function (content) { + var tool = content["t"]; //Tool witch is used + var wid = content["wid"]; //whiteboard ID + var username = content["username"]; + if (tool === "clear") { + //Clear the whiteboard + delete savedBoards[wid]; + delete savedUndos[wid]; + } else if (tool === "undo") { + //Undo an action + if (!savedUndos[wid]) { + savedUndos[wid] = []; + } + if (savedBoards[wid]) { + for (var i = savedBoards[wid].length - 1; i >= 0; i--) { + if (savedBoards[wid][i]["username"] == username) { + var drawId = savedBoards[wid][i]["drawId"]; + for (var i = savedBoards[wid].length - 1; i >= 0; i--) { + if ( + savedBoards[wid][i]["drawId"] == drawId && + savedBoards[wid][i]["username"] == username + ) { + savedUndos[wid].push(savedBoards[wid][i]); + savedBoards[wid].splice(i, 1); + } + } + break; + } + } + if (savedUndos[wid].length > 1000) { + savedUndos[wid].splice(0, savedUndos[wid].length - 1000); + } + } + } else if (tool === "redo") { + if (!savedUndos[wid]) { + savedUndos[wid] = []; + } + if (!savedBoards[wid]) { + savedBoards[wid] = []; + } + for (var i = savedUndos[wid].length - 1; i >= 0; i--) { + if (savedUndos[wid][i]["username"] == username) { + var drawId = savedUndos[wid][i]["drawId"]; + for (var i = savedUndos[wid].length - 1; i >= 0; i--) { + if ( + savedUndos[wid][i]["drawId"] == drawId && + savedUndos[wid][i]["username"] == username + ) { + savedBoards[wid].push(savedUndos[wid][i]); + savedUndos[wid].splice(i, 1); + } + } + break; + } + } + } else if ( + [ + "line", + "pen", + "rect", + "circle", + "eraser", + "addImgBG", + "recSelect", + "eraseRec", + "addTextBox", + "setTextboxText", + "removeTextbox", + "setTextboxPosition", + "setTextboxFontSize", + "setTextboxFontColor", + ].includes(tool) + ) { + //Save all this actions + savedBoards[wid] = savedBoards[wid] ? savedBoards[wid] : []; + delete content["wid"]; //Delete id from content so we don't store it twice + if (tool === "setTextboxText") { + for (var i = savedBoards[wid].length - 1; i >= 0; i--) { + //Remove old textbox tex -> dont store it twice + if ( + savedBoards[wid][i]["t"] === "setTextboxText" && + savedBoards[wid][i]["d"][0] === content["d"][0] + ) { + savedBoards[wid].splice(i, 1); + } + } + } + savedBoards[wid].push(content); + } + this.saveToDB(); + }, + saveToDB : function(){ + if (config.backend.enableFileDatabase) { + //Save whiteboard to file + if (!saveDelay) { + saveDelay = true; + setTimeout(function () { + saveDelay = false; + fs.writeFile("savedBoards.json", JSON.stringify(savedBoards), (err) => { + if (err) { + return console.log(err); + } + }); + }, 1000 * 10); //Save after 10 sec + } + } + }, + loadStoredData: function (wid) { + //Load saved whiteboard + return savedBoards[wid] ? savedBoards[wid] : []; + }, + copyStoredData : function(sourceWid, targetWid) { + const sourceData = this.loadStoredData(sourceWid); + if (sourceData.length === 0 || this.loadStoredData(targetWid).lenght > 0) { + return; + } + savedBoards[targetWid] = sourceData.slice(); + } +}; Index: lams_build/conf/whiteboard/scripts/server-backend.js =================================================================== diff -u -r6583579862c8623515c9861dd8edec09b6d1898f -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_build/conf/whiteboard/scripts/server-backend.js (.../server-backend.js) (revision 6583579862c8623515c9861dd8edec09b6d1898f) +++ lams_build/conf/whiteboard/scripts/server-backend.js (.../server-backend.js) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -78,6 +78,22 @@ } }); + // added by LAMS + app.get("/api/copywhiteboard", function (req, res) { + const sourceWid = req["query"]["sourceWid"]; + const at = req["query"]["at"]; //accesstoken + const targetWid = req["query"]["targetWid"]; + + if (accessToken === "" || hashAccessToken(sourceWid) == at) { + s_whiteboard.copyStoredData(sourceWid, targetWid); + res.end(); + } else { + res.status(401); //Unauthorized + res.end(); + } + }); + + /** * @api {get} /api/getReadOnlyWid Get the readOnlyWhiteboardId * @apiDescription This returns the readOnlyWhiteboardId for a given WhiteboardId Index: lams_tool_whiteboard/db/sql/create_lams_tool_whiteboard.sql =================================================================== diff -u -rb5f4a44b664ee18ed97ef77d512c6480eb500826 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/db/sql/create_lams_tool_whiteboard.sql (.../create_lams_tool_whiteboard.sql) (revision b5f4a44b664ee18ed97ef77d512c6480eb500826) +++ lams_tool_whiteboard/db/sql/create_lams_tool_whiteboard.sql (.../create_lams_tool_whiteboard.sql) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -5,7 +5,6 @@ CREATE TABLE tl_lawhiteboard11_whiteboard ( uid bigint not null auto_increment, content_id bigint unique, - source_wid varchar(64), create_date datetime, update_date datetime, create_by bigint, Index: lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/model/Whiteboard.java =================================================================== diff -u -r6583579862c8623515c9861dd8edec09b6d1898f -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/model/Whiteboard.java (.../Whiteboard.java) (revision 6583579862c8623515c9861dd8edec09b6d1898f) +++ lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/model/Whiteboard.java (.../Whiteboard.java) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -60,9 +60,6 @@ @Column(name = "content_id") private Long contentId; - @Column(name = "source_wid") - private String sourceWid; - @Column private String title; @@ -230,14 +227,6 @@ this.uid = uid; } - public String getSourceWid() { - return sourceWid; - } - - public void setSourceWid(String sourceWid) { - this.sourceWid = sourceWid; - } - /** * @return Returns the title. */ Index: lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/IWhiteboardService.java =================================================================== diff -u -r4c4fe77d887f75b6dad30ab974aba88a1fa34e25 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/IWhiteboardService.java (.../IWhiteboardService.java) (revision 4c4fe77d887f75b6dad30ab974aba88a1fa34e25) +++ lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/IWhiteboardService.java (.../IWhiteboardService.java) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -139,5 +139,4 @@ String getWhiteboardAccessTokenHash(String wid, String sourceWid); String getWhiteboardReadOnlyWid(String wid) throws WhiteboardApplicationException; - } \ No newline at end of file Index: lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/WhiteboardService.java =================================================================== diff -u -r4c4fe77d887f75b6dad30ab974aba88a1fa34e25 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/WhiteboardService.java (.../WhiteboardService.java) (revision 4c4fe77d887f75b6dad30ab974aba88a1fa34e25) +++ lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/service/WhiteboardService.java (.../WhiteboardService.java) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -328,11 +328,9 @@ group.setWid(wid); group.setAccessToken(getWhiteboardAccessTokenHash(wid, null)); - if (StringUtils.isNotBlank(whiteboard.getSourceWid())) { - String whiteboardCopyAccessToken = getWhiteboardAccessTokenHash(wid, whiteboard.getSourceWid()); - // since each wid is different for a different session, copy access token is also different - group.setCopyAccessToken(whiteboardCopyAccessToken); - } + String whiteboardCopyAccessToken = getWhiteboardAccessTokenHash(wid, whiteboard.getContentId().toString()); + // since each wid is different for a different session, copy access token is also different + group.setCopyAccessToken(whiteboardCopyAccessToken); if (itemRatingDtoMap != null) { group.setItemRatingDto(itemRatingDtoMap.get(session.getSessionId())); @@ -587,6 +585,33 @@ return null; } + private void copyWhiteboardContent(String sourceWid, String targetWid) throws WhiteboardApplicationException { + if (StringUtils.isBlank(sourceWid) || StringUtils.isBlank(targetWid)) { + return; + } + // using Whiteboard API from https://cloud13.de/testwhiteboard/apidoc/index.html + String whiteboardServerUrl = getWhiteboardServerUrl(); + StringBuilder url = new StringBuilder().append(whiteboardServerUrl).append("/api/copywhiteboard?sourceWid=") + .append(sourceWid).append("&targetWid=").append(targetWid); + String whiteboardAccessToken = getWhiteboardAccessTokenHash(sourceWid, null); + if (whiteboardAccessToken != null) { + url.append("&at=").append(whiteboardAccessToken); + } + + try { + HttpURLConnection connection = HttpUrlConnectionUtil.getConnection(url.toString()); + connection.connect(); + int code = connection.getResponseCode(); + if (code != 200) { + throw new IOException("When copying Whiteboard from ID " + sourceWid + " to ID " + targetWid + + " server responded with code " + code); + } + } catch (IOException e) { + throw new WhiteboardApplicationException( + "Could not copy Whiteboard from ID " + sourceWid + " to ID " + targetWid, e); + } + } + public static String getWhiteboardAuthorName(UserDTO user) throws UnsupportedEncodingException { if (user == null) { return null; @@ -733,8 +758,12 @@ } Whiteboard toContent = Whiteboard.newInstance(whiteboard, toContentId); - // copy whiteboard canvas on next open - toContent.setSourceWid(whiteboard.getContentId().toString()); + // copy whiteboard canvas + try { + copyWhiteboardContent(whiteboard.getContentId().toString(), toContentId.toString()); + } catch (WhiteboardApplicationException e) { + throw new ToolException("Error while copying tool content", e); + } whiteboardDao.insert(toContent); if (toContent.isGalleryWalkEnabled() && !toContent.isGalleryWalkReadOnly()) { Index: lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/AuthoringController.java =================================================================== diff -u -r6583579862c8623515c9861dd8edec09b6d1898f -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/AuthoringController.java (.../AuthoringController.java) (revision 6583579862c8623515c9861dd8edec09b6d1898f) +++ lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/AuthoringController.java (.../AuthoringController.java) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -31,7 +31,6 @@ import javax.servlet.http.HttpSession; import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.whiteboard.WhiteboardConstants; @@ -169,12 +168,6 @@ String whiteboardAccessTokenHash = whiteboardService.getWhiteboardAccessTokenHash(wid, null); request.setAttribute("whiteboardAccessToken", whiteboardAccessTokenHash); - if (StringUtils.isNotBlank(authoringForm.getWhiteboard().getSourceWid())) { - String whiteboardCopyAccessTokenHash = whiteboardService.getWhiteboardAccessTokenHash(wid, - authoringForm.getWhiteboard().getSourceWid()); - request.setAttribute("whiteboardCopyAccessToken", whiteboardCopyAccessTokenHash); - } - return "pages/authoring/authoring"; } @@ -215,11 +208,6 @@ } whiteboardPO.setUpdated(new Timestamp(new Date().getTime())); } - - // if whiteboard canvas was copied from another Learning Design, - // not it becomes the source, i.e. does not copy from anything anymore - whiteboardPO.setSourceWid(null); - // *******************************Handle user******************* // try to get form system session HttpSession ss = SessionManager.getSession(); Index: lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/LearningController.java =================================================================== diff -u -r4c4fe77d887f75b6dad30ab974aba88a1fa34e25 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/LearningController.java (.../LearningController.java) (revision 4c4fe77d887f75b6dad30ab974aba88a1fa34e25) +++ lams_tool_whiteboard/src/java/org/lamsfoundation/lams/tool/whiteboard/web/controller/LearningController.java (.../LearningController.java) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -35,7 +35,6 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; @@ -226,11 +225,9 @@ String whiteboardAccessTokenHash = whiteboardService.getWhiteboardAccessTokenHash(wid, null); request.setAttribute("whiteboardAccessToken", whiteboardAccessTokenHash); - if (StringUtils.isNotBlank(whiteboard.getSourceWid())) { - String whiteboardCopyAccessTokenHash = whiteboardService.getWhiteboardAccessTokenHash(wid, - whiteboard.getSourceWid()); - request.setAttribute("whiteboardCopyAccessToken", whiteboardCopyAccessTokenHash); - } + String whiteboardCopyAccessTokenHash = whiteboardService.getWhiteboardAccessTokenHash(wid, + whiteboard.getContentId().toString()); + request.setAttribute("whiteboardCopyAccessToken", whiteboardCopyAccessTokenHash); return "pages/learning/learning"; } Index: lams_tool_whiteboard/web/pages/authoring/basic.jsp =================================================================== diff -u -r6583579862c8623515c9861dd8edec09b6d1898f -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/web/pages/authoring/basic.jsp (.../basic.jsp) (revision 6583579862c8623515c9861dd8edec09b6d1898f) +++ lams_tool_whiteboard/web/pages/authoring/basic.jsp (.../basic.jsp) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -17,5 +17,5 @@ \ No newline at end of file Index: lams_tool_whiteboard/web/pages/learning/galleryWalk.jsp =================================================================== diff -u -r4c4fe77d887f75b6dad30ab974aba88a1fa34e25 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/web/pages/learning/galleryWalk.jsp (.../galleryWalk.jsp) (revision 4c4fe77d887f75b6dad30ab974aba88a1fa34e25) +++ lams_tool_whiteboard/web/pages/learning/galleryWalk.jsp (.../galleryWalk.jsp) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -169,7 +169,7 @@ Index: lams_tool_whiteboard/web/pages/learning/learning.jsp =================================================================== diff -u -re9d22ce99dd49f9fd9495c9e78a3306ee07a74b0 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/web/pages/learning/learning.jsp (.../learning.jsp) (revision e9d22ce99dd49f9fd9495c9e78a3306ee07a74b0) +++ lams_tool_whiteboard/web/pages/learning/learning.jsp (.../learning.jsp) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -216,7 +216,7 @@ Index: lams_tool_whiteboard/web/pages/monitoring/summary.jsp =================================================================== diff -u -r4c4fe77d887f75b6dad30ab974aba88a1fa34e25 -rd1b5adfc103345fa2525236c53313dcda1cfb7c0 --- lams_tool_whiteboard/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision 4c4fe77d887f75b6dad30ab974aba88a1fa34e25) +++ lams_tool_whiteboard/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision d1b5adfc103345fa2525236c53313dcda1cfb7c0) @@ -834,7 +834,7 @@ <%-- If there is no grouping, data is loaded immediately. If there is grouping, data is loaded on panel expand. --%>