mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	Compare commits
	
		
			14 Commits
		
	
	
		
			v0.52.1-be
			...
			v0.52.4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e7db262559 | ||
|  | 3faae63b84 | ||
|  | fac9fef652 | ||
|  | f0ab1fb5a1 | ||
|  | df3fdb59c5 | ||
|  | 23e9bcfdc5 | ||
|  | 96c4934c00 | ||
|  | 31fb02f810 | ||
|  | e206d9cc68 | ||
|  | 2d33f570f4 | ||
|  | 15f8173add | ||
|  | 7609bc78ec | ||
|  | b4ac41eff8 | ||
|  | de1c76ee3c | 
| @@ -22,7 +22,7 @@ RUN set -x \ | ||||
|     && apk del .build-dependencies | ||||
|  | ||||
| # Some setup tools need to be kept | ||||
| RUN apk add --no-cache su-exec | ||||
| RUN apk add --no-cache su-exec shadow | ||||
|  | ||||
| # Bundle app source | ||||
| COPY . . | ||||
|   | ||||
							
								
								
									
										46
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										46
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| { | ||||
|   "name": "trilium", | ||||
|   "version": "0.51.2", | ||||
|   "version": "0.52.3", | ||||
|   "lockfileVersion": 2, | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "trilium", | ||||
|       "version": "0.51.2", | ||||
|       "version": "0.52.3", | ||||
|       "hasInstallScript": true, | ||||
|       "license": "AGPL-3.0-only", | ||||
|       "dependencies": { | ||||
| @@ -21,7 +21,7 @@ | ||||
|         "commonmark": "0.30.0", | ||||
|         "cookie-parser": "1.4.6", | ||||
|         "csurf": "1.11.0", | ||||
|         "dayjs": "1.11.2", | ||||
|         "dayjs": "1.11.3", | ||||
|         "ejs": "3.1.8", | ||||
|         "electron-debug": "3.2.0", | ||||
|         "electron-dl": "3.3.1", | ||||
| @@ -65,7 +65,7 @@ | ||||
|         "tmp": "0.2.1", | ||||
|         "turndown": "7.1.1", | ||||
|         "unescape": "1.0.1", | ||||
|         "ws": "8.6.0", | ||||
|         "ws": "8.7.0", | ||||
|         "yauzl": "2.10.0" | ||||
|       }, | ||||
|       "bin": { | ||||
| @@ -82,7 +82,7 @@ | ||||
|         "jsdoc": "3.6.10", | ||||
|         "lorem-ipsum": "2.0.4", | ||||
|         "rcedit": "3.0.1", | ||||
|         "webpack": "5.72.1", | ||||
|         "webpack": "5.73.0", | ||||
|         "webpack-cli": "4.9.2" | ||||
|       }, | ||||
|       "optionalDependencies": { | ||||
| @@ -3115,9 +3115,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/dayjs": { | ||||
|       "version": "1.11.2", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", | ||||
|       "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" | ||||
|       "version": "1.11.3", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", | ||||
|       "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" | ||||
|     }, | ||||
|     "node_modules/debug": { | ||||
|       "version": "4.3.4", | ||||
| @@ -10252,9 +10252,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/webpack": { | ||||
|       "version": "5.72.1", | ||||
|       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", | ||||
|       "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", | ||||
|       "version": "5.73.0", | ||||
|       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", | ||||
|       "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@types/eslint-scope": "^3.7.3", | ||||
| @@ -10594,9 +10594,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/ws": { | ||||
|       "version": "8.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", | ||||
|       "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", | ||||
|       "version": "8.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", | ||||
|       "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", | ||||
|       "engines": { | ||||
|         "node": ">=10.0.0" | ||||
|       }, | ||||
| @@ -13271,9 +13271,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "dayjs": { | ||||
|       "version": "1.11.2", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz", | ||||
|       "integrity": "sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==" | ||||
|       "version": "1.11.3", | ||||
|       "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz", | ||||
|       "integrity": "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" | ||||
|     }, | ||||
|     "debug": { | ||||
|       "version": "4.3.4", | ||||
| @@ -18776,9 +18776,9 @@ | ||||
|       "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" | ||||
|     }, | ||||
|     "webpack": { | ||||
|       "version": "5.72.1", | ||||
|       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz", | ||||
|       "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==", | ||||
|       "version": "5.73.0", | ||||
|       "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", | ||||
|       "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@types/eslint-scope": "^3.7.3", | ||||
| @@ -19028,9 +19028,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "ws": { | ||||
|       "version": "8.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", | ||||
|       "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", | ||||
|       "version": "8.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", | ||||
|       "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", | ||||
|       "requires": {} | ||||
|     }, | ||||
|     "xdg-basedir": { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|   "name": "trilium", | ||||
|   "productName": "Trilium Notes", | ||||
|   "description": "Trilium Notes", | ||||
|   "version": "0.52.1-beta", | ||||
|   "version": "0.52.4", | ||||
|   "license": "AGPL-3.0-only", | ||||
|   "main": "electron.js", | ||||
|   "bin": { | ||||
| @@ -36,7 +36,7 @@ | ||||
|     "commonmark": "0.30.0", | ||||
|     "cookie-parser": "1.4.6", | ||||
|     "csurf": "1.11.0", | ||||
|     "dayjs": "1.11.2", | ||||
|     "dayjs": "1.11.3", | ||||
|     "ejs": "3.1.8", | ||||
|     "electron-debug": "3.2.0", | ||||
|     "electron-dl": "3.3.1", | ||||
| @@ -80,7 +80,7 @@ | ||||
|     "tmp": "0.2.1", | ||||
|     "turndown": "7.1.1", | ||||
|     "unescape": "1.0.1", | ||||
|     "ws": "8.6.0", | ||||
|     "ws": "8.7.0", | ||||
|     "yauzl": "2.10.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
| @@ -94,7 +94,7 @@ | ||||
|     "jsdoc": "3.6.10", | ||||
|     "lorem-ipsum": "2.0.4", | ||||
|     "rcedit": "3.0.1", | ||||
|     "webpack": "5.72.1", | ||||
|     "webpack": "5.73.0", | ||||
|     "webpack-cli": "4.9.2" | ||||
|   }, | ||||
|   "optionalDependencies": { | ||||
|   | ||||
| @@ -9,7 +9,6 @@ const entityChangesService = require('../../services/entity_changes'); | ||||
| const AbstractEntity = require("./abstract_entity"); | ||||
| const NoteRevision = require("./note_revision"); | ||||
| const TaskContext = require("../../services/task_context"); | ||||
| const handlers = require("../../services/handlers"); | ||||
|  | ||||
| const LABEL = 'label'; | ||||
| const RELATION = 'relation'; | ||||
| @@ -1134,6 +1133,10 @@ class Note extends AbstractEntity { | ||||
|      * @param {TaskContext} [taskContext] | ||||
|      */ | ||||
|     deleteNote(deleteId, taskContext) { | ||||
|         if (this.isDeleted) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!deleteId) { | ||||
|             deleteId = utils.randomString(10); | ||||
|         } | ||||
| @@ -1143,6 +1146,7 @@ class Note extends AbstractEntity { | ||||
|         } | ||||
|  | ||||
|         // needs to be run before branches and attributes are deleted and thus attached relations disappear | ||||
|         const handlers = require("../../services/handlers"); | ||||
|         handlers.runAttachedRelations(this, 'runOnNoteDeletion', this); | ||||
|         taskContext.noteDeletionHandlerTriggered = true; | ||||
|  | ||||
|   | ||||
| @@ -280,7 +280,7 @@ function isHtmlEmpty(html) { | ||||
|  | ||||
| async function clearBrowserCache() { | ||||
|     if (isElectron()) { | ||||
|         const win = utils.dynamicRequire('@electron/remote').getCurrentWindow(); | ||||
|         const win = dynamicRequire('@electron/remote').getCurrentWindow(); | ||||
|         await win.webContents.session.clearCache(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -235,7 +235,7 @@ const ATTR_HELP = { | ||||
|         "runOnNoteChange": "executes when note is changed (includes note creation as well)", | ||||
|         "runOnNoteDeletion": "executes when note is being deleted", | ||||
|         "runOnBranchCreation": "executes when a branch is created. Branch is a link between parent note and child note and is created e.g. when cloning or moving note.", | ||||
|         "runOnBranchDeletion": "executes when a branch is delete. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).", | ||||
|         "runOnBranchDeletion": "executes when a branch is deleted. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).", | ||||
|         "runOnChildNoteCreation": "executes when new note is created under this note", | ||||
|         "runOnAttributeCreation": "executes when new attribute is created under this note", | ||||
|         "runOnAttributeChange": "executes when attribute is changed under this note", | ||||
|   | ||||
| @@ -968,3 +968,8 @@ input { | ||||
| .note-split.full-content-width { | ||||
|     max-width: 999999px; | ||||
| } | ||||
|  | ||||
| button.close:hover { | ||||
|     text-shadow: none; | ||||
|     color: currentColor; | ||||
| } | ||||
|   | ||||
| @@ -170,7 +170,6 @@ span.fancytree-active .fancytree-title { | ||||
| } | ||||
|  | ||||
| span.fancytree-selected { | ||||
|     color: var(--hover-item-text-color) !important; | ||||
|     border-color: var(--main-border-color) !important; | ||||
|     border-radius: 5px; | ||||
| } | ||||
|   | ||||
| @@ -15,7 +15,9 @@ function exportBranch(req, res) { | ||||
|         const message = `Cannot export branch ${branchId} since it does not exist.`; | ||||
|         log.error(message); | ||||
|  | ||||
|         res.status(500).send(message); | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(500) | ||||
|             .send(message); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| @@ -41,7 +43,9 @@ function exportBranch(req, res) { | ||||
|  | ||||
|         log.error(message + e.stack); | ||||
|  | ||||
|         res.status(500).send(message); | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(500) | ||||
|             .send(message); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,8 @@ function updateFile(req) { | ||||
|         return [404, `Note ${noteId} doesn't exist.`]; | ||||
|     } | ||||
|  | ||||
|     noteRevisionService.createNoteRevision(note); | ||||
|     note.saveNoteRevision(); | ||||
|     noteRevisionService.protectNoteRevisions(note); | ||||
|  | ||||
|     note.mime = file.mimetype.toLowerCase(); | ||||
|     note.save(); | ||||
| @@ -47,7 +48,9 @@ function downloadNoteFile(noteId, res, contentDisposition = true) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return res.status(404).send(`Note ${noteId} doesn't exist.`); | ||||
|         return res.setHeader("Content-Type", "text/plain") | ||||
|             .status(404) | ||||
|             .send(`Note ${noteId} doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     if (note.isProtected && !protectedSessionService.isProtectedSessionAvailable()) { | ||||
|   | ||||
| @@ -20,20 +20,22 @@ function returnImage(req, res) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * special "image" type. the canvas is actually type application/json  | ||||
|      * special "image" type. the canvas is actually type application/json | ||||
|      * to avoid bitrot and enable usage as referenced image the svg is included. | ||||
|      */ | ||||
|     if (image.type === 'canvas') { | ||||
|         const content = image.getContent(); | ||||
|         try { | ||||
|             const data = JSON.parse(content); | ||||
|              | ||||
|  | ||||
|             const svg = data.svg || '<svg />' | ||||
|             res.set('Content-Type', "image/svg+xml"); | ||||
|             res.set("Cache-Control", "no-cache, no-store, must-revalidate"); | ||||
|             res.send(svg); | ||||
|         } catch(err) { | ||||
|             res.status(500).send("there was an error parsing excalidraw to svg"); | ||||
|             res.setHeader("Content-Type", "text/plain") | ||||
|                 .status(500) | ||||
|                 .send("there was an error parsing excalidraw to svg"); | ||||
|         } | ||||
|     } else { | ||||
|         res.set('Content-Type', image.mime); | ||||
|   | ||||
| @@ -65,11 +65,15 @@ function downloadNoteRevision(req, res) { | ||||
|     const noteRevision = becca.getNoteRevision(req.params.noteRevisionId); | ||||
|  | ||||
|     if (noteRevision.noteId !== req.params.noteId) { | ||||
|         return res.status(400).send(`Note revision ${req.params.noteRevisionId} does not belong to note ${req.params.noteId}`); | ||||
|         return res.setHeader("Content-Type", "text/plain") | ||||
|             .status(400) | ||||
|             .send(`Note revision ${req.params.noteRevisionId} does not belong to note ${req.params.noteId}`); | ||||
|     } | ||||
|  | ||||
|     if (noteRevision.isProtected && !protectedSessionService.isProtectedSessionAvailable()) { | ||||
|         return res.status(401).send("Protected session not available"); | ||||
|         return res.setHeader("Content-Type", "text/plain") | ||||
|             .status(401) | ||||
|             .send("Protected session not available"); | ||||
|     } | ||||
|  | ||||
|     const filename = getRevisionFilename(noteRevision); | ||||
| @@ -97,7 +101,8 @@ function restoreNoteRevision(req) { | ||||
|     if (noteRevision) { | ||||
|         const note = noteRevision.getNote(); | ||||
|  | ||||
|         noteRevisionService.createNoteRevision(note); | ||||
|         note.saveNoteRevision(); | ||||
|         noteRevisionService.protectNoteRevisions(note); | ||||
|  | ||||
|         note.title = noteRevision.title; | ||||
|         note.setContent(noteRevision.getContent()); | ||||
|   | ||||
| @@ -294,7 +294,8 @@ function uploadModifiedFile(req) { | ||||
|  | ||||
|     log.info(`Updating note '${noteId}' with content from ${filePath}`); | ||||
|  | ||||
|     noteRevisionService.createNoteRevision(note); | ||||
|     note.saveNoteRevision(); | ||||
|     noteRevisionService.protectNoteRevisions(note); | ||||
|  | ||||
|     const fileContent = fs.readFileSync(filePath); | ||||
|  | ||||
|   | ||||
| @@ -9,15 +9,16 @@ const noteRevisionService = require("../../services/note_revisions"); | ||||
| const branchService = require("../../services/branches"); | ||||
| const cloningService = require("../../services/cloning"); | ||||
| const {formatAttrForSearch} = require("../../services/attribute_formatter"); | ||||
| const utils = require("../../services/utils.js"); | ||||
|  | ||||
| async function searchFromNoteInt(note) { | ||||
| function searchFromNoteInt(note) { | ||||
|     let searchResultNoteIds; | ||||
|  | ||||
|     const searchScript = note.getRelationValue('searchScript'); | ||||
|     const searchString = note.getLabelValue('searchString'); | ||||
|  | ||||
|     if (searchScript) { | ||||
|         searchResultNoteIds = await searchFromRelation(note, 'searchScript'); | ||||
|         searchResultNoteIds = searchFromRelation(note, 'searchScript'); | ||||
|     } else { | ||||
|         const searchContext = new SearchContext({ | ||||
|             fastSearch: note.hasLabel('fastSearch'), | ||||
| @@ -61,7 +62,9 @@ async function searchFromNote(req) { | ||||
|  | ||||
| const ACTION_HANDLERS = { | ||||
|     deleteNote: (action, note) => { | ||||
|         note.markAsDeleted(); | ||||
|         const deleteId = 'searchbulkaction-' + utils.randomString(10); | ||||
|  | ||||
|         note.deleteNote(deleteId); | ||||
|     }, | ||||
|     deleteNoteRevisions: (action, note) => { | ||||
|         noteRevisionService.eraseNoteRevisions(note.getNoteRevisions().map(rev => rev.noteRevisionId)); | ||||
| @@ -149,7 +152,7 @@ function getActions(note) { | ||||
|         .filter(a => !!a); | ||||
| } | ||||
|  | ||||
| async function searchAndExecute(req) { | ||||
| function searchAndExecute(req) { | ||||
|     const note = becca.getNote(req.params.noteId); | ||||
|  | ||||
|     if (!note) { | ||||
| @@ -165,7 +168,7 @@ async function searchAndExecute(req) { | ||||
|         return [400, `Note ${req.params.noteId} is not a search note.`] | ||||
|     } | ||||
|  | ||||
|     const searchResultNoteIds = await searchFromNoteInt(note); | ||||
|     const searchResultNoteIds = searchFromNoteInt(note); | ||||
|  | ||||
|     const actions = getActions(note); | ||||
|  | ||||
|   | ||||
| @@ -49,7 +49,9 @@ function handleRequest(req, res) { | ||||
|             catch (e) { | ||||
|                 log.error(`Custom handler ${note.noteId} failed with ${e.message}`); | ||||
|  | ||||
|                 res.status(500).send(e.message); | ||||
|                 res.setHeader("Content-Type", "text/plain") | ||||
|                     .status(500) | ||||
|                     .send(e.message); | ||||
|             } | ||||
|         } | ||||
|         else if (attr.name === 'customResourceProvider') { | ||||
| @@ -65,7 +67,9 @@ function handleRequest(req, res) { | ||||
|     const message = `No handler matched for custom ${path} request.`; | ||||
|  | ||||
|     log.info(message); | ||||
|     res.status(404).send(message); | ||||
|     res.setHeader("Content-Type", "text/plain") | ||||
|         .status(404) | ||||
|         .send(message); | ||||
| } | ||||
|  | ||||
| function register(router) { | ||||
|   | ||||
| @@ -120,6 +120,10 @@ function apiResultHandler(req, res, result) { | ||||
|  | ||||
| function send(res, statusCode, response) { | ||||
|     if (typeof response === 'string') { | ||||
|         if (statusCode >= 400) { | ||||
|             res.setHeader("Content-Type", "text/plain"); | ||||
|         } | ||||
|  | ||||
|         res.status(statusCode).send(response); | ||||
|  | ||||
|         return response.length; | ||||
| @@ -167,7 +171,9 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio | ||||
|                         .catch(e => { | ||||
|                             log.error(`${method} ${path} threw exception: ` + e.stack); | ||||
|  | ||||
|                             res.status(500).send(e.message); | ||||
|                             res.setHeader("Content-Type", "text/plain") | ||||
|                                 .status(500) | ||||
|                                 .send(e.message); | ||||
|                         }); | ||||
|                 } | ||||
|                 else { | ||||
| @@ -180,7 +186,9 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio | ||||
|         catch (e) { | ||||
|             log.error(`${method} ${path} threw exception: ` + e.stack); | ||||
|  | ||||
|             res.status(500).send(e.message); | ||||
|             res.setHeader("Content-Type", "text/plain") | ||||
|                 .status(500) | ||||
|                 .send(e.message); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|   | ||||
| @@ -88,17 +88,23 @@ function checkEtapiToken(req, res, next) { | ||||
| function reject(req, res, message) { | ||||
|     log.info(`${req.method} ${req.path} rejected with 401 ${message}`); | ||||
|  | ||||
|     res.status(401).send(message); | ||||
|     res.setHeader("Content-Type", "text/plain") | ||||
|         .status(401) | ||||
|         .send(message); | ||||
| } | ||||
|  | ||||
| function checkCredentials(req, res, next) { | ||||
|     if (!sqlInit.isDbInitialized()) { | ||||
|         res.status(400).send('Database is not initialized yet.'); | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(400) | ||||
|             .send('Database is not initialized yet.'); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (!passwordService.isPasswordSet()) { | ||||
|         res.status(400).send('Password has not been set yet. Please set a password and repeat the action'); | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(400) | ||||
|             .send('Password has not been set yet. Please set a password and repeat the action'); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
| @@ -109,7 +115,9 @@ function checkCredentials(req, res, next) { | ||||
|     // username is ignored | ||||
|  | ||||
|     if (!passwordEncryptionService.verifyPassword(password)) { | ||||
|         res.status(401).send('Incorrect password'); | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(401) | ||||
|             .send('Incorrect password'); | ||||
|     } | ||||
|     else { | ||||
|         next(); | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| module.exports = { buildDate:"2022-06-05T15:00:25+02:00", buildRevision: "f587e0dfd9177462faef8ad7c39a855c25d03c91" }; | ||||
| module.exports = { buildDate:"2022-07-01T00:11:53+02:00", buildRevision: "3faae63b849a1fabc31b823bb7af3a84d32256a7" }; | ||||
|   | ||||
| @@ -50,7 +50,7 @@ module.exports = [ | ||||
|     { type: 'label', name: 'shareDisallowRobotIndexing' }, | ||||
|     { type: 'label', name: 'displayRelations' }, | ||||
|     { type: 'label', name: 'hideRelations' }, | ||||
|     { type: 'label', name: 'titleTemplate' }, | ||||
|     { type: 'label', name: 'titleTemplate', isDangerous: true }, | ||||
|  | ||||
|     // relation names | ||||
|     { type: 'relation', name: 'internalLink' }, | ||||
|   | ||||
| @@ -68,7 +68,7 @@ function updateImage(noteId, uploadBuffer, originalName) { | ||||
|  | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     noteRevisionService.createNoteRevision(note); | ||||
|     note.saveNoteRevision(); | ||||
|     noteRevisionService.protectNoteRevisions(note); | ||||
|  | ||||
|     note.setLabel('originalFileName', originalName); | ||||
|   | ||||
| @@ -98,25 +98,25 @@ const DEFAULT_KEYBOARD_ACTIONS = [ | ||||
|     }, | ||||
|     { | ||||
|         actionName: "moveNoteUp", | ||||
|         defaultShortcuts: ["CommandOrControl+Up"], | ||||
|         defaultShortcuts: isMac ? ["Alt+Up"] : ["CommandOrControl+Up"], | ||||
|         description: "Move note up", | ||||
|         scope: "note-tree" | ||||
|     }, | ||||
|     { | ||||
|         actionName: "moveNoteDown", | ||||
|         defaultShortcuts: ["CommandOrControl+Down"], | ||||
|         defaultShortcuts: isMac ? ["Alt+Down"] : ["CommandOrControl+Down"], | ||||
|         description: "Move note down", | ||||
|         scope: "note-tree" | ||||
|     }, | ||||
|     { | ||||
|         actionName: "moveNoteUpInHierarchy", | ||||
|         defaultShortcuts: ["CommandOrControl+Left"], | ||||
|         defaultShortcuts: isMac ? ["Alt+Left"] : ["CommandOrControl+Left"], | ||||
|         description: "Move note up in hierarchy", | ||||
|         scope: "note-tree" | ||||
|     }, | ||||
|     { | ||||
|         actionName: "moveNoteDownInHierarchy", | ||||
|         defaultShortcuts: ["CommandOrControl+Right"], | ||||
|         defaultShortcuts: isMac ? ["Alt+Right"] : ["CommandOrControl+Right"], | ||||
|         description: "Move note down in hierarchy", | ||||
|         scope: "note-tree" | ||||
|     }, | ||||
|   | ||||
| @@ -102,7 +102,7 @@ function isDbUpToDate() { | ||||
| async function migrateIfNecessary() { | ||||
|     const currentDbVersion = getDbVersion(); | ||||
|  | ||||
|     if (currentDbVersion > appInfo.dbVersion) { | ||||
|     if (currentDbVersion > appInfo.dbVersion && process.env.TRILIUM_IGNORE_DB_VERSION !== 'true') { | ||||
|         log.error(`Current DB version ${currentDbVersion} is newer than app db version ${appInfo.dbVersion} which means that it was created by newer and incompatible version of Trilium. Upgrade to latest version of Trilium to resolve this issue.`); | ||||
|  | ||||
|         utils.crash(); | ||||
|   | ||||
| @@ -1,9 +1,8 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const NoteRevision = require('../becca/entities/note_revision'); | ||||
| const dateUtils = require('./date_utils'); | ||||
| const log = require('./log'); | ||||
| const sql = require('./sql'); | ||||
| const protectedSession = require("./protected_session"); | ||||
|  | ||||
| /** | ||||
|  * @param {Note} note | ||||
| @@ -11,6 +10,12 @@ const sql = require('./sql'); | ||||
| function protectNoteRevisions(note) { | ||||
|     for (const revision of note.getNoteRevisions()) { | ||||
|         if (note.isProtected !== revision.isProtected) { | ||||
|             if (!protectedSession.isProtectedSessionAvailable()) { | ||||
|                 log.error("Protected session is not available to fix note revisions."); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 const content = revision.getContent(); | ||||
|  | ||||
|   | ||||
| @@ -78,6 +78,10 @@ function findResultsWithExpression(expression, searchContext) { | ||||
|  | ||||
|     const searchResults = noteSet.notes | ||||
|         .map(note => { | ||||
|             if (note.isDeleted) { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             const notePathArray = executionContext.noteIdToNotePath[note.noteId] || beccaService.getSomePath(note); | ||||
|  | ||||
|             if (!notePathArray) { | ||||
| @@ -85,7 +89,8 @@ function findResultsWithExpression(expression, searchContext) { | ||||
|             } | ||||
|  | ||||
|             return new SearchResult(notePathArray); | ||||
|         }); | ||||
|         }) | ||||
|         .filter(note => !!note); | ||||
|  | ||||
|     for (const res of searchResults) { | ||||
|         res.computeScore(searchContext.highlightedTokens); | ||||
| @@ -129,7 +134,7 @@ function parseQueryToExpression(query, searchContext) { | ||||
|             structuredExpressionTokens, | ||||
|             expression | ||||
|         }; | ||||
|          | ||||
|  | ||||
|         log.info("Search debug: " + JSON.stringify(searchContext.debugInfo, null, 4)); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -242,9 +242,9 @@ function transactional(func) { | ||||
|         return ret; | ||||
|     } | ||||
|     catch (e) { | ||||
|         const entityChanges = cls.getAndClearEntityChangeIds(); | ||||
|         const entityChangeIds = cls.getAndClearEntityChangeIds(); | ||||
|  | ||||
|         if (entityChanges.length > 0) { | ||||
|         if (entityChangeIds.length > 0) { | ||||
|             log.info("Transaction rollback dirtied the becca, forcing reload."); | ||||
|  | ||||
|             require('../becca/becca_loader').load(); | ||||
|   | ||||
| @@ -39,9 +39,9 @@ function register(router) { | ||||
|         addNoIndexHeader(note, res); | ||||
|  | ||||
|         if (note.hasLabel('shareRaw') || ['image', 'file'].includes(note.type)) { | ||||
|             res.setHeader('Content-Type', note.mime); | ||||
|             res.setHeader('Content-Type', note.mime) | ||||
|                 .send(note.getContent()); | ||||
|  | ||||
|             res.send(note.getContent()); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -83,7 +83,9 @@ function register(router) { | ||||
|         const note = shaca.getNote(noteId); | ||||
|  | ||||
|         if (!note) { | ||||
|             return res.status(404).send(`Note '${noteId}' not found`); | ||||
|             return res.setHeader("Content-Type", "text/plain") | ||||
|                 .status(404) | ||||
|                 .send(`Note '${noteId}' not found`); | ||||
|         } | ||||
|  | ||||
|         addNoIndexHeader(note, res); | ||||
| @@ -98,7 +100,9 @@ function register(router) { | ||||
|         const note = shaca.getNote(noteId); | ||||
|  | ||||
|         if (!note) { | ||||
|             return res.status(404).send(`Note '${noteId}' not found`); | ||||
|             return res.setHeader("Content-Type", "text/plain") | ||||
|                 .status(404) | ||||
|                 .send(`Note '${noteId}' not found`); | ||||
|         } | ||||
|  | ||||
|         addNoIndexHeader(note, res); | ||||
| @@ -122,13 +126,17 @@ function register(router) { | ||||
|         const image = shaca.getNote(req.params.noteId); | ||||
|  | ||||
|         if (!image) { | ||||
|             return res.status(404).send(`Note '${req.params.noteId}' not found`); | ||||
|             return res.setHeader('Content-Type', 'text/plain') | ||||
|                 .status(404) | ||||
|                 .send(`Note '${req.params.noteId}' not found`); | ||||
|         } | ||||
|         else if (!["image", "canvas"].includes(image.type)) { | ||||
|             return res.status(400).send("Requested note is not a shareable image"); | ||||
|             return res.setHeader('Content-Type', 'text/plain') | ||||
|                 .status(400) | ||||
|                 .send("Requested note is not a shareable image"); | ||||
|         } else if (image.type === "canvas") { | ||||
|             /** | ||||
|              * special "image" type. the canvas is actually type application/json  | ||||
|              * special "image" type. the canvas is actually type application/json | ||||
|              * to avoid bitrot and enable usage as referenced image the svg is included. | ||||
|              */ | ||||
|             const content = image.getContent(); | ||||
| @@ -141,7 +149,9 @@ function register(router) { | ||||
|                 res.set("Cache-Control", "no-cache, no-store, must-revalidate"); | ||||
|                 res.send(svg); | ||||
|             } catch(err) { | ||||
|                 res.status(500).send("there was an error parsing excalidraw to svg"); | ||||
|                 res.setHeader('Content-Type', 'text/plain') | ||||
|                     .status(500) | ||||
|                     .send("there was an error parsing excalidraw to svg"); | ||||
|             } | ||||
|         } else { | ||||
|             // normal image | ||||
| @@ -159,7 +169,9 @@ function register(router) { | ||||
|         const note = shaca.getNote(noteId); | ||||
|  | ||||
|         if (!note) { | ||||
|             return res.status(404).send(`Note '${noteId}' not found`); | ||||
|             return res.setHeader('Content-Type', 'text/plain') | ||||
|                 .status(404) | ||||
|                 .send(`Note '${noteId}' not found`); | ||||
|         } | ||||
|  | ||||
|         addNoIndexHeader(note, res); | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| [[ ! -z "${USER_UID}" ]] && usermod -u ${USER_UID} node || echo "No USER_UID specified, leaving 1000" | ||||
| [[ ! -z "${USER_GID}" ]] && groupmod -g ${USER_GID} node || echo "No USER_GID specified, leaving 1000" | ||||
|  | ||||
| chown -R node:node /home/node | ||||
| su-exec node node ./src/www | ||||
|   | ||||
		Reference in New Issue
	
	Block a user