| 
									
										
										
										
											2022-04-11 21:38:05 +02:00
										 |  |  | const excalidrawToSvg = require("excalidraw-to-svg"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  | const shaca = require("./shaca/shaca"); | 
					
						
							|  |  |  | const shacaLoader = require("./shaca/shaca_loader"); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  | const shareRoot = require("./share_root"); | 
					
						
							| 
									
										
										
										
											2022-01-10 17:09:20 +01:00
										 |  |  | const contentRenderer = require("./content_renderer"); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 20:54:48 +01:00
										 |  |  | function getSharedSubTreeRoot(note) { | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  |     if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { | 
					
						
							| 
									
										
										
										
											2021-12-23 20:54:48 +01:00
										 |  |  |         // share root itself is not shared
 | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 20:54:48 +01:00
										 |  |  |     // every path leads to share root, but which one to choose?
 | 
					
						
							|  |  |  |     // for sake of simplicity URLs are not note paths
 | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  |     const parentNote = note.getParentNotes()[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (parentNote.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { | 
					
						
							|  |  |  |         return note; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-23 20:54:48 +01:00
										 |  |  |     return getSharedSubTreeRoot(parentNote); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  | function addNoIndexHeader(note, res) { | 
					
						
							|  |  |  |     if (note.hasLabel('shareDisallowRobotIndexing')) { | 
					
						
							|  |  |  |         res.setHeader('X-Robots-Tag', 'noindex'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  | function register(router) { | 
					
						
							| 
									
										
										
										
											2022-01-17 23:13:56 +01:00
										 |  |  |     function renderNote(note, res) { | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  |         if (!note) { | 
					
						
							| 
									
										
										
										
											2021-12-22 09:10:38 +01:00
										 |  |  |             res.status(404).render("share/404"); | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         addNoIndexHeader(note, res); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (note.hasLabel('shareRaw') || ['image', 'file'].includes(note.type)) { | 
					
						
							|  |  |  |             res.setHeader('Content-Type', note.mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             res.send(note.getContent()); | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const {header, content, isEmpty} = contentRenderer.getContent(note); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const subRoot = getSharedSubTreeRoot(note); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res.render("share/page", { | 
					
						
							|  |  |  |             note, | 
					
						
							|  |  |  |             header, | 
					
						
							|  |  |  |             content, | 
					
						
							|  |  |  |             isEmpty, | 
					
						
							|  |  |  |             subRoot | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2022-01-17 23:13:56 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     router.get(['/share', '/share/'], (req, res, next) => { | 
					
						
							|  |  |  |         shacaLoader.ensureLoad(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         renderNote(shaca.shareRootNote, res); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     router.get('/share/:shareId', (req, res, next) => { | 
					
						
							|  |  |  |         const {shareId} = req.params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         shacaLoader.ensureLoad(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         renderNote(note, res); | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |     router.get('/share/api/notes/:noteId', (req, res, next) => { | 
					
						
							|  |  |  |         const {noteId} = req.params; | 
					
						
							|  |  |  |         const note = shaca.getNote(noteId); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |         if (!note) { | 
					
						
							|  |  |  |             return res.status(404).send(`Note ${noteId} not found`); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  |         addNoIndexHeader(note, res); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |         res.json(note.getPojoWithAttributes()); | 
					
						
							| 
									
										
										
										
											2021-10-19 22:48:38 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-12-06 22:53:17 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-22 09:36:38 +01:00
										 |  |  |     router.get('/share/api/notes/:noteId/download', (req, res, next) => { | 
					
						
							| 
									
										
										
										
											2021-12-06 22:53:17 +01:00
										 |  |  |         const {noteId} = req.params; | 
					
						
							|  |  |  |         const note = shaca.getNote(noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!note) { | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |             return res.status(404).send(`Note ${noteId} not found`); | 
					
						
							| 
									
										
										
										
											2021-12-06 22:53:17 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  |         addNoIndexHeader(note, res); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-06 22:53:17 +01:00
										 |  |  |         const utils = require("../services/utils"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | 
					
						
							|  |  |  |         res.setHeader('Content-Type', note.mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res.send(note.getContent()); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-12-27 20:48:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-11 21:50:10 +02:00
										 |  |  |     router.get(['/share/api/images/:noteId/:filename', '/share/api/images/:noteId'], (req, res, next) => { | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |         const image = shaca.getNote(req.params.noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!image) { | 
					
						
							|  |  |  |             return res.status(404).send(`Note ${noteId} not found`); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-11 21:38:05 +02:00
										 |  |  |         else if (!["image", "canvas-note"].includes(image.type)) { | 
					
						
							|  |  |  |             return res.status(400).send("Requested note is not a shareable image"); | 
					
						
							|  |  |  |         } else if (image.type === "canvas-note") { | 
					
						
							|  |  |  |             /** | 
					
						
							|  |  |  |              * FIXME: deduplicate the code from api/image.js | 
					
						
							|  |  |  |              */ | 
					
						
							|  |  |  |             // render the svg in node.js using excalidraw and jsdom
 | 
					
						
							|  |  |  |             const content = image.getContent(); | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 const data = JSON.parse(content) | 
					
						
							|  |  |  |                 const excalidrawData = { | 
					
						
							|  |  |  |                     type: "excalidraw", | 
					
						
							|  |  |  |                     version: 2, | 
					
						
							|  |  |  |                     source: "trilium", | 
					
						
							|  |  |  |                     elements: data.elements, | 
					
						
							|  |  |  |                     appState: data.appState, | 
					
						
							|  |  |  |                     files: data.files, | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 excalidrawToSvg(excalidrawData) | 
					
						
							|  |  |  |                     .then(svg => { | 
					
						
							|  |  |  |                         const svgHtml = svg.outerHTML; | 
					
						
							|  |  |  |                         res.set('Content-Type', "image/svg+xml"); | 
					
						
							|  |  |  |                         res.set("Cache-Control", "no-cache, no-store, must-revalidate"); | 
					
						
							|  |  |  |                         res.send(svgHtml); | 
					
						
							|  |  |  |                     }); | 
					
						
							|  |  |  |             } catch(err) { | 
					
						
							|  |  |  |                 res.status(500).send("there was an error parsing excalidraw to svg"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             // normal image
 | 
					
						
							|  |  |  |             res.set('Content-Type', image.mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             res.send(image.getContent()); | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // used for PDF viewing
 | 
					
						
							| 
									
										
										
										
											2021-12-24 21:36:31 +00:00
										 |  |  |     router.get('/share/api/notes/:noteId/view', (req, res, next) => { | 
					
						
							|  |  |  |         const {noteId} = req.params; | 
					
						
							|  |  |  |         const note = shaca.getNote(noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!note) { | 
					
						
							| 
									
										
										
										
											2022-01-01 13:23:09 +01:00
										 |  |  |             return res.status(404).send(`Note ${noteId} not found`); | 
					
						
							| 
									
										
										
										
											2021-12-24 21:36:31 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 23:17:47 +01:00
										 |  |  |         addNoIndexHeader(note, res); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-24 21:36:31 +00:00
										 |  |  |         res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | 
					
						
							|  |  |  |         res.setHeader('Content-Type', note.mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         res.send(note.getContent()); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-10-17 14:44:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = { | 
					
						
							|  |  |  |     register | 
					
						
							|  |  |  | } |