mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	introduced new exception classes for structured error reporting
This commit is contained in:
		
							
								
								
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -5,7 +5,6 @@ | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "trilium", | ||||
|       "version": "0.57.3", | ||||
|       "hasInstallScript": true, | ||||
|       "license": "AGPL-3.0-only", | ||||
|   | ||||
| @@ -1329,7 +1329,7 @@ class Note extends AbstractEntity { | ||||
|     } | ||||
|  | ||||
|     isLaunchBarConfig() { | ||||
|         return this.type === 'launcher' || ['lbRoot', 'lbAvailableShortcuts', 'lbVisibleShortcuts']; | ||||
|         return this.type === 'launcher' || ['lbRoot', 'lbAvailableLaunchers', 'lbVisibleLaunchers'].includes(this.noteId); | ||||
|     } | ||||
|  | ||||
|     isOptions() { | ||||
|   | ||||
							
								
								
									
										7
									
								
								src/errors/not_found_error.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/errors/not_found_error.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| class NotFoundError { | ||||
|     constructor(message) { | ||||
|         this.message = message; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = NotFoundError; | ||||
							
								
								
									
										7
									
								
								src/errors/validation_error.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/errors/validation_error.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| class ValidationError { | ||||
|     constructor(message) { | ||||
|         this.message = message; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = ValidationError; | ||||
| @@ -828,7 +828,7 @@ class NoteShort { | ||||
|     } | ||||
|  | ||||
|     isLaunchBarConfig() { | ||||
|         return this.type === 'launcher' || ['lbRoot', 'lbAvailableShortcuts', 'lbVisibleShortcuts'].includes(this.noteId); | ||||
|         return this.type === 'launcher' || ['lbRoot', 'lbAvailableLaunchers', 'lbVisibleLaunchers'].includes(this.noteId); | ||||
|     } | ||||
|  | ||||
|     isOptions() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import utils from './utils.js'; | ||||
| import ValidationError from "./validation_error.js"; | ||||
|  | ||||
| const REQUEST_LOGGING_ENABLED = false; | ||||
|  | ||||
| @@ -102,10 +103,15 @@ async function call(method, url, data, headers = {}) { | ||||
|     return resp.body; | ||||
| } | ||||
|  | ||||
| async function reportError(method, url, status, error) { | ||||
|     const message = "Error when calling " + method + " " + url + ": " + status + " - " + error; | ||||
|  | ||||
| async function reportError(method, url, status, response) { | ||||
|     const toastService = (await import("./toast.js")).default; | ||||
|  | ||||
|     if ([400, 404].includes(status) && response && typeof response === 'object') { | ||||
|         toastService.showError(response.message); | ||||
|         throw new ValidationError(response); | ||||
|     } | ||||
|  | ||||
|     const message = "Error when calling " + method + " " + url + ": " + status + " - " + responseText; | ||||
|     toastService.showError(message); | ||||
|     toastService.throwError(message); | ||||
| } | ||||
|   | ||||
							
								
								
									
										7
									
								
								src/public/app/services/validation_error.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/public/app/services/validation_error.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| export default class ValidationError { | ||||
|     constructor(resp) { | ||||
|         for (const key in resp) { | ||||
|             this[key] = resp[key]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -568,7 +568,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | ||||
|                     $span.append($refreshSearchButton); | ||||
|                 } | ||||
|  | ||||
|                 if (!['search', 'launcher'].includes(note.type) && !note.isOptions()) { | ||||
|                 if (!['search', 'launcher'].includes(note.type) && !note.isOptions() && !note.isLaunchBarConfig()) { | ||||
|                     const $createChildNoteButton = $('<span class="tree-item-button add-note-button bx bx-plus" title="Create child note"></span>'); | ||||
|  | ||||
|                     $span.append($createChildNoteButton); | ||||
|   | ||||
| @@ -5,6 +5,8 @@ const log = require('../../services/log'); | ||||
| const attributeService = require('../../services/attributes'); | ||||
| const Attribute = require('../../becca/entities/attribute'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function getEffectiveNoteAttributes(req) { | ||||
|     const note = becca.getNote(req.params.noteId); | ||||
| @@ -21,11 +23,11 @@ function updateNoteAttribute(req) { | ||||
|         attribute = becca.getAttribute(body.attributeId); | ||||
|  | ||||
|         if (!attribute) { | ||||
|             return [404, `Attribute '${body.attributeId}' does not exist.`]; | ||||
|             throw new NotFoundError(`Attribute '${body.attributeId}' does not exist.`); | ||||
|         } | ||||
|  | ||||
|         if (attribute.noteId !== noteId) { | ||||
|             return [400, `Attribute '${body.attributeId}' is not owned by ${noteId}`]; | ||||
|             throw new ValidationError(`Attribute '${body.attributeId}' is not owned by ${noteId}`); | ||||
|         } | ||||
|  | ||||
|         if (body.type !== attribute.type | ||||
| @@ -106,7 +108,7 @@ function deleteNoteAttribute(req) { | ||||
|  | ||||
|     if (attribute) { | ||||
|         if (attribute.noteId !== noteId) { | ||||
|             return [400, `Attribute ${attributeId} is not owned by ${noteId}`]; | ||||
|             throw new ValidationError(`Attribute ${attributeId} is not owned by ${noteId}`); | ||||
|         } | ||||
|  | ||||
|         attribute.markAsDeleted(); | ||||
|   | ||||
| @@ -9,6 +9,8 @@ const becca = require('../../becca/becca'); | ||||
| const TaskContext = require('../../services/task_context'); | ||||
| const branchService = require("../../services/branches"); | ||||
| const log = require("../../services/log.js"); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| /** | ||||
|  * Code in this file deals with moving and cloning branches. Relationship between note and parent note is unique | ||||
| @@ -22,7 +24,7 @@ function moveBranchToParent(req) { | ||||
|     const branchToMove = becca.getBranch(branchId); | ||||
|  | ||||
|     if (!parentBranch || !branchToMove) { | ||||
|         return [400, `One or both branches ${branchId}, ${parentBranchId} have not been found`]; | ||||
|         throw new ValidationError(`One or both branches ${branchId}, ${parentBranchId} have not been found`); | ||||
|     } | ||||
|  | ||||
|     return branchService.moveBranchToBranch(branchToMove, parentBranch, branchId); | ||||
| @@ -35,11 +37,11 @@ function moveBranchBeforeNote(req) { | ||||
|     const beforeBranch = becca.getBranch(beforeBranchId); | ||||
|  | ||||
|     if (!branchToMove) { | ||||
|         return [404, `Can't find branch ${branchId}`]; | ||||
|         throw new NotFoundError(`Can't find branch '${branchId}'`); | ||||
|     } | ||||
|  | ||||
|     if (!beforeBranch) { | ||||
|         return [404, `Can't find branch ${beforeBranchId}`]; | ||||
|         throw new NotFoundError(`Can't find branch '${beforeBranchId}'`); | ||||
|     } | ||||
|  | ||||
|     const validationResult = treeService.validateParentChild(beforeBranch.parentNoteId, branchToMove.noteId, branchId); | ||||
| @@ -193,7 +195,7 @@ function deleteBranch(req) { | ||||
|     const branch = becca.getBranch(req.params.branchId); | ||||
|  | ||||
|     if (!branch) { | ||||
|         return [404, `Branch ${req.params.branchId} not found`]; | ||||
|         throw new NotFoundError(`Branch '${req.params.branchId}' not found`); | ||||
|     } | ||||
|  | ||||
|     const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes'); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ const opmlExportService = require('../../services/export/opml'); | ||||
| const becca = require('../../becca/becca'); | ||||
| const TaskContext = require("../../services/task_context"); | ||||
| const log = require("../../services/log"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function exportBranch(req, res) { | ||||
|     const {branchId, type, format, version, taskId} = req.params; | ||||
| @@ -34,11 +35,11 @@ function exportBranch(req, res) { | ||||
|             opmlExportService.exportToOpml(taskContext, branch, version, res); | ||||
|         } | ||||
|         else { | ||||
|             return [404, "Unrecognized export format " + format]; | ||||
|             throw new NotFoundError(`Unrecognized export format '${format}'`); | ||||
|         } | ||||
|     } | ||||
|     catch (e) { | ||||
|         const message = "Export failed with following error: '" + e.message + "'. More details might be in the logs."; | ||||
|         const message = `Export failed with following error: '${e.message}'. More details might be in the logs.`; | ||||
|         taskContext.reportError(message); | ||||
|  | ||||
|         log.error(message + e.stack); | ||||
|   | ||||
| @@ -10,6 +10,7 @@ const { Readable } = require('stream'); | ||||
| const chokidar = require('chokidar'); | ||||
| const ws = require('../../services/ws'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function updateFile(req) { | ||||
|     const {noteId} = req.params; | ||||
| @@ -18,7 +19,7 @@ function updateFile(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} doesn't exist.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     note.saveNoteRevision(); | ||||
| @@ -116,7 +117,7 @@ function saveToTmpDir(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404,`Note ${noteId} doesn't exist.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     const tmpObj = tmp.fileSync({postfix: getFilename(note)}); | ||||
|   | ||||
| @@ -4,6 +4,8 @@ const imageService = require('../../services/image'); | ||||
| const becca = require('../../becca/becca'); | ||||
| const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR; | ||||
| const fs = require('fs'); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function returnImage(req, res) { | ||||
|     const image = becca.getNote(req.params.noteId); | ||||
| @@ -51,11 +53,11 @@ function uploadImage(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} doesn't exist.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     if (!["image/png", "image/jpg", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"].includes(file.mimetype)) { | ||||
|         return [400, "Unknown image type: " + file.mimetype]; | ||||
|         throw new ValidationError(`Unknown image type: ${file.mimetype}`); | ||||
|     } | ||||
|  | ||||
|     const {url} = imageService.saveImage(noteId, file.buffer, file.originalname, true, true); | ||||
| @@ -73,7 +75,7 @@ function updateImage(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} doesn't exist.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     if (!["image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"].includes(file.mimetype)) { | ||||
|   | ||||
| @@ -10,6 +10,8 @@ const becca = require('../../becca/becca'); | ||||
| const beccaLoader = require('../../becca/becca_loader'); | ||||
| const log = require('../../services/log'); | ||||
| const TaskContext = require('../../services/task_context'); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| async function importToBranch(req) { | ||||
|     const {parentNoteId} = req.params; | ||||
| @@ -27,13 +29,13 @@ async function importToBranch(req) { | ||||
|     const file = req.file; | ||||
|  | ||||
|     if (!file) { | ||||
|         return [400, "No file has been uploaded"]; | ||||
|         throw new ValidationError("No file has been uploaded"); | ||||
|     } | ||||
|  | ||||
|     const parentNote = becca.getNote(parentNoteId); | ||||
|  | ||||
|     if (!parentNote) { | ||||
|         return [404, `Note ${parentNoteId} doesn't exist.`]; | ||||
|         throw new NotFoundError(`Note '${parentNoteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     const extension = path.extname(file.originalname).toLowerCase(); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const becca = require("../../becca/becca"); | ||||
| const { JSDOM } = require("jsdom"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function buildDescendantCountMap() { | ||||
|     const noteIdToCountMap = {}; | ||||
| @@ -326,7 +327,7 @@ function getBacklinkCount(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, "Not found"]; | ||||
|         throw new NotFoundError(`Note '${noteId}' not found`); | ||||
|     } | ||||
|     else { | ||||
|         return { | ||||
| @@ -340,7 +341,7 @@ function getBacklinks(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} was not found`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' was not found`); | ||||
|     } | ||||
|  | ||||
|     let backlinksWithExcerptCount = 0; | ||||
|   | ||||
| @@ -9,13 +9,15 @@ const TaskContext = require('../../services/task_context'); | ||||
| const protectedSessionService = require('../../services/protected_session'); | ||||
| const fs = require('fs'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function getNote(req) { | ||||
|     const noteId = req.params.noteId; | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, "Note " + noteId + " has not been found."]; | ||||
|         throw new NotFoundError(`Note '${noteId}' has not been found.`); | ||||
|     } | ||||
|  | ||||
|     const pojo = note.getPojo(); | ||||
| @@ -197,11 +199,11 @@ function changeTitle(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note '${noteId}' has not been found`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' has not been found`); | ||||
|     } | ||||
|  | ||||
|     if (!note.isContentAvailable()) { | ||||
|         return [400, `Note '${noteId}' is not available for change`]; | ||||
|         throw new ValidationError(`Note '${noteId}' is not available for change`); | ||||
|     } | ||||
|  | ||||
|     const noteTitleChanged = note.title !== title; | ||||
| @@ -290,7 +292,7 @@ function uploadModifiedFile(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note '${noteId}' has not been found`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' has not been found`); | ||||
|     } | ||||
|  | ||||
|     log.info(`Updating note '${noteId}' with content from ${filePath}`); | ||||
| @@ -300,7 +302,7 @@ function uploadModifiedFile(req) { | ||||
|     const fileContent = fs.readFileSync(filePath); | ||||
|  | ||||
|     if (!fileContent) { | ||||
|         return [400, `File ${fileContent} is empty`]; | ||||
|         throw new ValidationError(`File '${fileContent}' is empty`); | ||||
|     } | ||||
|  | ||||
|     note.setContent(fileContent); | ||||
| @@ -311,11 +313,11 @@ function forceSaveNoteRevision(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} not found.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' not found.`); | ||||
|     } | ||||
|  | ||||
|     if (!note.isContentAvailable()) { | ||||
|         return [400, `Note revision of a protected note cannot be created outside of a protected session.`]; | ||||
|         throw new ValidationError(`Note revision of a protected note cannot be created outside of a protected session.`); | ||||
|     } | ||||
|  | ||||
|     note.saveNoteRevision(); | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| const optionService = require('../../services/options'); | ||||
| const log = require('../../services/log'); | ||||
| const searchService = require('../../services/search/services/search'); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
|  | ||||
| // options allowed to be updated directly in options dialog | ||||
| const ALLOWED_OPTIONS = new Set([ | ||||
| @@ -82,7 +83,7 @@ function updateOption(req) { | ||||
|     const {name, value} = req.params; | ||||
|  | ||||
|     if (!update(name, value)) { | ||||
|         return [400, "not allowed option to change"]; | ||||
|         throw new ValidationError("not allowed option to change"); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const passwordService = require('../../services/password'); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
|  | ||||
| function changePassword(req) { | ||||
|     if (passwordService.isPasswordSet()) { | ||||
| @@ -14,7 +15,7 @@ function changePassword(req) { | ||||
| function resetPassword(req) { | ||||
|     // protection against accidental call (not a security measure) | ||||
|     if (req.query.really !== "yesIReallyWantToResetPasswordAndLoseAccessToMyProtectedNotes") { | ||||
|         return [400, "Incorrect password reset confirmation"]; | ||||
|         throw new ValidationError("Incorrect password reset confirmation"); | ||||
|     } | ||||
|  | ||||
|     return passwordService.resetPassword(); | ||||
|   | ||||
| @@ -6,12 +6,14 @@ const searchService = require('../../services/search/services/search'); | ||||
| const bulkActionService = require("../../services/bulk_actions"); | ||||
| const cls = require("../../services/cls"); | ||||
| const {formatAttrForSearch} = require("../../services/attribute_formatter"); | ||||
| const ValidationError = require("../../public/app/services/validation_error.js"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function searchFromNote(req) { | ||||
|     const note = becca.getNote(req.params.noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${req.params.noteId} has not been found.`]; | ||||
|         throw new NotFoundError(`Note '${req.params.noteId}' has not been found.`); | ||||
|     } | ||||
|  | ||||
|     if (note.isDeleted) { | ||||
| @@ -20,7 +22,7 @@ function searchFromNote(req) { | ||||
|     } | ||||
|  | ||||
|     if (note.type !== 'search') { | ||||
|         return [400, `Note ${req.params.noteId} is not a search note.`] | ||||
|         throw new ValidationError(`Note '${req.params.noteId}' is not a search note.`); | ||||
|     } | ||||
|  | ||||
|     return searchService.searchFromNote(note); | ||||
| @@ -30,16 +32,16 @@ function searchAndExecute(req) { | ||||
|     const note = becca.getNote(req.params.noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${req.params.noteId} has not been found.`]; | ||||
|         throw new NotFoundError(`Note '${req.params.noteId}' has not been found.`); | ||||
|     } | ||||
|  | ||||
|     if (note.isDeleted) { | ||||
|         // this can be triggered from recent changes and it's harmless to return empty list rather than fail | ||||
|         // this can be triggered from recent changes, and it's harmless to return empty list rather than fail | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     if (note.type !== 'search') { | ||||
|         return [400, `Note ${req.params.noteId} is not a search note.`] | ||||
|         throw new ValidationError(`Note '${req.params.noteId}' is not a search note.`); | ||||
|     } | ||||
|  | ||||
|     const {searchResultNoteIds} = searchService.searchFromNote(note); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const similarityService = require('../../becca/similarity'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| async function getSimilarNotes(req) { | ||||
|     const noteId = req.params.noteId; | ||||
| @@ -9,7 +10,7 @@ async function getSimilarNotes(req) { | ||||
|     const note = becca.getNote(noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} not found.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' not found.`); | ||||
|     } | ||||
|  | ||||
|     return await similarityService.findSimilarNotes(noteId); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const sql = require('../../services/sql'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function getSchema() { | ||||
|     const tableNames = sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`); | ||||
| @@ -21,7 +22,7 @@ function execute(req) { | ||||
|     const note = becca.getNote(req.params.noteId); | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${req.params.noteId} was not found.`]; | ||||
|         throw new NotFoundError(`Note '${req.params.noteId}' was not found.`); | ||||
|     } | ||||
|  | ||||
|     const queries = note.getContent().split("\n---"); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| const sql = require('../../services/sql'); | ||||
| const becca = require('../../becca/becca'); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function getNoteSize(req) { | ||||
|     const {noteId} = req.params; | ||||
| @@ -26,7 +27,7 @@ function getSubtreeSize(req) { | ||||
|     const note = becca.notes[noteId]; | ||||
|  | ||||
|     if (!note) { | ||||
|         return [404, `Note ${noteId} was not found.`]; | ||||
|         throw new NotFoundError(`Note '${noteId}' was not found.`); | ||||
|     } | ||||
|  | ||||
|     const subTreeNoteIds = note.getSubtreeNoteIds(); | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| const becca = require('../../becca/becca'); | ||||
| const log = require('../../services/log'); | ||||
| const NotFoundError = require("../../errors/not_found_error.js"); | ||||
|  | ||||
| function getNotesAndBranchesAndAttributes(noteIds) { | ||||
|     noteIds = new Set(noteIds); | ||||
| @@ -141,7 +142,7 @@ function getTree(req) { | ||||
|     } | ||||
|  | ||||
|     if (!(subTreeNoteId in becca.notes)) { | ||||
|         return [404, `Note ${subTreeNoteId} not found in the cache`]; | ||||
|         throw new NotFoundError(`Note '${subTreeNoteId}' not found in the cache`); | ||||
|     } | ||||
|  | ||||
|     collect(becca.notes[subTreeNoteId]); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ const myScryptService = require('../services/my_scrypt'); | ||||
| const log = require('../services/log'); | ||||
| const passwordService = require("../services/password"); | ||||
| const assetPath = require("../services/asset_path"); | ||||
| const ValidationError = require("../public/app/services/validation_error.js"); | ||||
|  | ||||
| function loginPage(req, res) { | ||||
|     res.render('login', { | ||||
| @@ -23,7 +24,7 @@ function setPasswordPage(req, res) { | ||||
|  | ||||
| function setPassword(req, res) { | ||||
|     if (passwordService.isPasswordSet()) { | ||||
|         return [400, "Password has been already set"]; | ||||
|         throw new ValidationError("Password has been already set"); | ||||
|     } | ||||
|  | ||||
|     let {password1, password2} = req.body; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ const loginRoute = require('./login'); | ||||
| const indexRoute = require('./index'); | ||||
| const utils = require('../services/utils'); | ||||
| const multer = require('multer'); | ||||
| const ValidationError = require("../errors/validation_error.js"); | ||||
|  | ||||
| // API routes | ||||
| const treeApiRoute = require('./api/tree'); | ||||
| @@ -61,6 +62,7 @@ const csurf = require('csurf'); | ||||
| const {createPartialContentHandler} = require("express-partial-content"); | ||||
| const rateLimit = require("express-rate-limit"); | ||||
| const AbstractEntity = require("../becca/entities/abstract_entity"); | ||||
| const NotFoundError = require("../errors/not_found_error.js"); | ||||
|  | ||||
| const csrfMiddleware = csurf({ | ||||
|     cookie: true, | ||||
| @@ -169,13 +171,7 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio | ||||
|  | ||||
|                             log.request(req, res, Date.now() - start, responseLength); | ||||
|                         }) | ||||
|                         .catch(e => { | ||||
|                             log.error(`${method} ${path} threw exception: ` + e.stack); | ||||
|  | ||||
|                             res.setHeader("Content-Type", "text/plain") | ||||
|                                 .status(500) | ||||
|                                 .send(e.message); | ||||
|                         }); | ||||
|                         .catch(e => handleException(method, path, e, res)); | ||||
|                 } | ||||
|                 else { | ||||
|                     const responseLength = resultHandler(req, res, result); | ||||
| @@ -185,13 +181,31 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio | ||||
|             } | ||||
|         } | ||||
|         catch (e) { | ||||
|             handleException(method, path, e, res); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function handleException(method, path, e, res) { | ||||
|     log.error(`${method} ${path} threw exception: ` + e.stack); | ||||
|  | ||||
|     if (e instanceof ValidationError) { | ||||
|         res.setHeader("Content-Type", "application/json") | ||||
|             .status(400) | ||||
|             .send({ | ||||
|                 message: e.message | ||||
|             }); | ||||
|     } if (e instanceof NotFoundError) { | ||||
|         res.setHeader("Content-Type", "application/json") | ||||
|             .status(404) | ||||
|             .send({ | ||||
|                 message: e.message | ||||
|             }); | ||||
|     } else { | ||||
|         res.setHeader("Content-Type", "text/plain") | ||||
|             .status(500) | ||||
|             .send(e.message); | ||||
|     } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| const MAX_ALLOWED_FILE_SIZE_MB = 250; | ||||
|   | ||||
| @@ -19,6 +19,7 @@ const Note = require('../becca/entities/note'); | ||||
| const Attribute = require('../becca/entities/attribute'); | ||||
| const dayjs = require("dayjs"); | ||||
| const htmlSanitizer = require("./html_sanitizer.js"); | ||||
| const ValidationError = require("../errors/validation_error.js"); | ||||
|  | ||||
| function getNewNotePosition(parentNoteId) { | ||||
|     const note = becca.notes[parentNoteId]; | ||||
| @@ -107,15 +108,11 @@ function getAndValidateParent(params) { | ||||
|     const parentNote = becca.notes[params.parentNoteId]; | ||||
|  | ||||
|     if (!parentNote) { | ||||
|         throw new Error(`Parent note "${params.parentNoteId}" not found.`); | ||||
|     } | ||||
|  | ||||
|     if (parentNote.type === 'launcher') { | ||||
|         throw new Error(`Launchers should not have child notes.`); | ||||
|         throw new ValidationError(`Parent note "${params.parentNoteId}" not found.`); | ||||
|     } | ||||
|  | ||||
|     if (!params.ignoreForbiddenParents && (parentNote.isLaunchBarConfig() || parentNote.isOptions())) { | ||||
|         throw new Error(`Creating child notes into '${parentNote.noteId}' is not allowed.`); | ||||
|         throw new ValidationError(`Creating child notes into '${parentNote.noteId}' is not allowed.`); | ||||
|     } | ||||
|  | ||||
|     return parentNote; | ||||
|   | ||||
| @@ -6,7 +6,7 @@ const ws = require('./ws'); | ||||
| const taskContexts = {}; | ||||
|  | ||||
| class TaskContext { | ||||
|     constructor(taskId, taskType, data) { | ||||
|     constructor(taskId, taskType, data = null) { | ||||
|         this.taskId = taskId; | ||||
|         this.taskType = taskType; | ||||
|         this.data = data; | ||||
| @@ -24,7 +24,7 @@ class TaskContext { | ||||
|     } | ||||
|  | ||||
|     /** @returns {TaskContext} */ | ||||
|     static getInstance(taskId, taskType, data) { | ||||
|     static getInstance(taskId, taskType, data = null) { | ||||
|         if (!taskContexts[taskId]) { | ||||
|             taskContexts[taskId] = new TaskContext(taskId, taskType, data); | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user