From db5e76fe8c5089a30b3d80fcd9e04a6e23b571f7 Mon Sep 17 00:00:00 2001 From: zadam Date: Mon, 19 Dec 2022 21:39:12 +0100 Subject: [PATCH] allow access to share api root note only if there's share index, #3434 --- src/services/cloning.js | 6 ------ src/share/routes.js | 24 ++++++++++++++---------- src/share/shaca/entities/attribute.js | 4 ++++ src/share/shaca/entities/note.js | 6 +++++- src/share/shaca/shaca.js | 3 +++ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/services/cloning.js b/src/services/cloning.js index 00cd0f721..4f89fb8fe 100644 --- a/src/services/cloning.js +++ b/src/services/cloning.js @@ -9,12 +9,6 @@ const beccaService = require("../becca/becca_service"); const log = require("./log"); function cloneNoteToNote(noteId, parentNoteId, prefix) { - if (parentNoteId === 'share') { - const specialNotesService = require('./special_notes'); - // share root note is created lazily - specialNotesService.getShareRoot(); - } - const parentNote = becca.getNote(parentNoteId); if (parentNote.type === 'search') { diff --git a/src/share/routes.js b/src/share/routes.js index 34f0a8f5c..e53f127a4 100644 --- a/src/share/routes.js +++ b/src/share/routes.js @@ -40,9 +40,15 @@ function checkNoteAccess(noteId, req, res) { const note = shaca.getNote(noteId); if (!note) { - res.setHeader("Content-Type", "text/plain") - .status(404) - .send(`Note '${noteId}' not found`); + res.status(404) + .json({ message: `Note '${noteId}' not found` }); + + return false; + } + + if (noteId === 'share' && !shaca.shareIndexEnabled) { + res.status(403) + .json({ message: `Accessing share index is forbidden.` }); return false; } @@ -179,9 +185,8 @@ function register(router) { } if (!["image", "canvas"].includes(image.type)) { - return res.setHeader('Content-Type', 'text/plain') - .status(400) - .send("Requested note is not a shareable image"); + return res.status(400) + .json({ message: "Requested note is not a shareable image" }); } else if (image.type === "canvas") { /** * special "image" type. the canvas is actually type application/json @@ -196,10 +201,9 @@ function register(router) { res.set('Content-Type', "image/svg+xml"); res.set("Cache-Control", "no-cache, no-store, must-revalidate"); res.send(svg); - } catch(err) { - res.setHeader('Content-Type', 'text/plain') - .status(500) - .send("there was an error parsing excalidraw to svg"); + } catch (err) { + res.status(500) + .json({ message: "There was an error parsing excalidraw to svg." }); } } else { // normal image diff --git a/src/share/shaca/entities/attribute.js b/src/share/shaca/entities/attribute.js index 365d1c434..9c898be96 100644 --- a/src/share/shaca/entities/attribute.js +++ b/src/share/shaca/entities/attribute.js @@ -47,6 +47,10 @@ class Attribute extends AbstractEntity { if (this.type === 'label' && this.name === 'shareRoot') { this.shaca.shareRootNote = this.note; } + + if (this.type === 'label' && this.name === 'shareIndex') { + this.shaca.shareIndexEnabled = true; + } } /** @returns {boolean} */ diff --git a/src/share/shaca/entities/note.js b/src/share/shaca/entities/note.js index ce5a5aa44..f7de68771 100644 --- a/src/share/shaca/entities/note.js +++ b/src/share/shaca/entities/note.js @@ -465,7 +465,11 @@ class Note extends AbstractEntity { type: this.type, mime: this.mime, utcDateModified: this.utcDateModified, - attributes: this.getAttributes().map(attr => attr.getPojo()), + attributes: this.getAttributes() + // relations could link across shared subtrees which might leak them + // individual relations might be whitelisted based on needs #3434 + .filter(attr => attr.type === 'label') + .map(attr => attr.getPojo()), parentNoteIds: this.parents.map(parentNote => parentNote.noteId), childNoteIds: this.children.map(child => child.noteId) }; diff --git a/src/share/shaca/shaca.js b/src/share/shaca/shaca.js index 360b1b169..547b91f84 100644 --- a/src/share/shaca/shaca.js +++ b/src/share/shaca/shaca.js @@ -20,6 +20,9 @@ class Shaca { /** @type {Note|null} */ this.shareRootNote = null; + /** @type {boolean} true if the index of all shared subtrees is enabled */ + this.shareIndexEnabled = false; + this.loaded = false; }