feat(backend): main handling of readonly sharing
* Saving works as before * Don't broadcast drawevents from readonly whiteboard (prevents malicious use)
This commit is contained in:
parent
d268eb6d93
commit
14e1ee5391
@ -2,6 +2,7 @@ const path = require("path");
|
||||
|
||||
const config = require("./config/config");
|
||||
const WhiteboardServerSideInfo = require("./WhiteboardServerSideInfo");
|
||||
const ReadOnlyBackendService = require("./services/ReadOnlyBackendService");
|
||||
|
||||
function startBackendServer(port) {
|
||||
var fs = require("fs-extra");
|
||||
@ -28,10 +29,13 @@ function startBackendServer(port) {
|
||||
const { accessToken, enableWebdav } = config.backend;
|
||||
|
||||
app.get("/api/loadwhiteboard", function (req, res) {
|
||||
var wid = req["query"]["wid"];
|
||||
var at = req["query"]["at"]; //accesstoken
|
||||
const wid = req["query"]["wid"];
|
||||
const at = req["query"]["at"]; //accesstoken
|
||||
if (accessToken === "" || accessToken == at) {
|
||||
var ret = s_whiteboard.loadStoredData(wid);
|
||||
const widForData = ReadOnlyBackendService.isReadOnly(wid)
|
||||
? ReadOnlyBackendService.getIdFromReadOnlyId(wid)
|
||||
: wid;
|
||||
const ret = s_whiteboard.loadStoredData(widForData);
|
||||
res.send(ret);
|
||||
res.end();
|
||||
} else {
|
||||
@ -192,7 +196,7 @@ function startBackendServer(port) {
|
||||
}, (1 / config.backend.performance.whiteboardInfoBroadcastFreq) * 1000);
|
||||
|
||||
io.on("connection", function (socket) {
|
||||
var whiteboardId = null;
|
||||
let whiteboardId = null;
|
||||
socket.on("disconnect", function () {
|
||||
if (infoByWhiteboard.has(whiteboardId)) {
|
||||
const whiteboardServerSideInfo = infoByWhiteboard.get(whiteboardId);
|
||||
@ -212,9 +216,20 @@ function startBackendServer(port) {
|
||||
});
|
||||
|
||||
socket.on("drawToWhiteboard", function (content) {
|
||||
if (!whiteboardId || ReadOnlyBackendService.isReadOnly(whiteboardId)) return;
|
||||
|
||||
content = escapeAllContentStrings(content);
|
||||
if (accessToken === "" || accessToken == content["at"]) {
|
||||
socket.compress(false).broadcast.to(whiteboardId).emit("drawToWhiteboard", content); //Send to all users in the room (not own socket)
|
||||
const broadcastTo = (wid) =>
|
||||
socket.compress(false).broadcast.to(wid).emit("drawToWhiteboard", content);
|
||||
// broadcast to current whiteboard
|
||||
broadcastTo(whiteboardId);
|
||||
const readOnlyId = ReadOnlyBackendService.getReadOnlyId(whiteboardId);
|
||||
const readOnlyWhiteboardInfo = infoByWhiteboard.get(readOnlyId);
|
||||
if (readOnlyWhiteboardInfo && readOnlyWhiteboardInfo.hasConnectedUser()) {
|
||||
// broadcast the same content to the associated read-only whiteboard
|
||||
broadcastTo(readOnlyId);
|
||||
}
|
||||
s_whiteboard.handleEventsAndData(content); //save whiteboardchanges on the server
|
||||
} else {
|
||||
socket.emit("wrongAccessToken", true);
|
||||
@ -224,9 +239,16 @@ function startBackendServer(port) {
|
||||
socket.on("joinWhiteboard", function (content) {
|
||||
content = escapeAllContentStrings(content);
|
||||
if (accessToken === "" || accessToken == content["at"]) {
|
||||
socket.emit("whiteboardConfig", { common: config.frontend });
|
||||
|
||||
whiteboardId = content["wid"];
|
||||
|
||||
socket.emit("whiteboardConfig", {
|
||||
common: config.frontend,
|
||||
whiteboardSpecific: {
|
||||
correspondingReadOnlyId: ReadOnlyBackendService.getReadOnlyId(whiteboardId),
|
||||
isReadOnly: ReadOnlyBackendService.isReadOnly(whiteboardId),
|
||||
},
|
||||
});
|
||||
|
||||
socket.join(whiteboardId); //Joins room name=wid
|
||||
if (!infoByWhiteboard.has(whiteboardId)) {
|
||||
infoByWhiteboard.set(whiteboardId, new WhiteboardServerSideInfo());
|
||||
|
71
scripts/services/ReadOnlyBackendService.js
Normal file
71
scripts/services/ReadOnlyBackendService.js
Normal file
@ -0,0 +1,71 @@
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
|
||||
class ReadOnlyBackendService {
|
||||
/**
|
||||
* Mapping from an editable whiteboard id to the matching read-only whiteboard id
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
*/
|
||||
#idToReadOnlyId = new Map();
|
||||
|
||||
/**
|
||||
* Mapping from a read-only whiteboard id to the matching editable whiteboard id
|
||||
*
|
||||
* @type {Map<string, string>}
|
||||
* @private
|
||||
*/
|
||||
#readOnlyIdToId = new Map();
|
||||
|
||||
/**
|
||||
* Make sure a whiteboardId is ignited in the service
|
||||
*
|
||||
* If it's not found in the service, we assume that it's an editable whiteboard
|
||||
*
|
||||
* @param {string} whiteboardId
|
||||
*/
|
||||
init(whiteboardId) {
|
||||
const idToReadOnlyId = this.#idToReadOnlyId;
|
||||
const readOnlyIdToId = this.#readOnlyIdToId;
|
||||
|
||||
if (!idToReadOnlyId.has(whiteboardId) && !readOnlyIdToId.has(whiteboardId)) {
|
||||
const readOnlyId = uuidv4();
|
||||
idToReadOnlyId.set(whiteboardId, readOnlyId);
|
||||
readOnlyIdToId.set(readOnlyId, whiteboardId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read-only id corresponding to a whiteboard id
|
||||
*
|
||||
* @param {string} whiteboardId
|
||||
* @return {string}
|
||||
*/
|
||||
getReadOnlyId(whiteboardId) {
|
||||
// make sure it's inited
|
||||
this.init(whiteboardId);
|
||||
return this.#idToReadOnlyId.get(whiteboardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id corresponding to readonly id
|
||||
*
|
||||
* @param {string} readOnlyId
|
||||
* @return {string}
|
||||
*/
|
||||
getIdFromReadOnlyId(readOnlyId) {
|
||||
return this.#readOnlyIdToId.get(readOnlyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell is whiteboard id corresponds to a read-only whiteboard
|
||||
*
|
||||
* @param whiteboardId
|
||||
* @return {boolean}
|
||||
*/
|
||||
isReadOnly(whiteboardId) {
|
||||
this.init(whiteboardId);
|
||||
return this.#readOnlyIdToId.has(whiteboardId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ReadOnlyBackendService();
|
Loading…
Reference in New Issue
Block a user