Compare commits

...

14 Commits

Author SHA1 Message Date
zadam
e7db262559 release 0.52.4 2022-07-01 00:11:53 +02:00
zadam
3faae63b84 set correct content type for error messages 2022-07-01 00:01:29 +02:00
zadam
fac9fef652 release 0.52.3 2022-06-13 23:41:52 +02:00
zadam
f0ab1fb5a1 Merge pull request #2917 from bill88t/master
Added the USER_UID & USER_GID env variables
2022-06-13 23:23:30 +02:00
zadam
df3fdb59c5 fix saving note revisions, closes #2915 2022-06-13 22:54:08 +02:00
zadam
23e9bcfdc5 release 0.52.2 2022-06-09 23:39:48 +02:00
zadam
96c4934c00 new default keyboard shortcuts alt+up/down/left/right for moving notes on Mac 2022-06-09 23:38:07 +02:00
zadam
31fb02f810 titleTemplate should be sanitized on import 2022-06-09 21:01:02 +02:00
zadam
e206d9cc68 fix selected note text color 2022-06-08 22:27:36 +02:00
zadam
2d33f570f4 fix bulk/search action delete 2022-06-08 22:25:00 +02:00
zadam
15f8173add fix ugly hover close button 2022-06-07 20:11:43 +02:00
zadam
7609bc78ec allow ignoring DB version for skipping uncritical migrations in case of a downgrade 2022-06-06 22:27:06 +02:00
zadam
b4ac41eff8 fix handlers import, closes #2900 2022-06-06 21:59:44 +02:00
zadam
de1c76ee3c typo 2022-06-05 21:24:52 +02:00
27 changed files with 150 additions and 79 deletions

View File

@@ -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
View File

@@ -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": {

View File

@@ -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": {

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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",

View File

@@ -968,3 +968,8 @@ input {
.note-split.full-content-width {
max-width: 999999px;
}
button.close:hover {
text-shadow: none;
color: currentColor;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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()) {

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);
}
});
}

View File

@@ -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();

View File

@@ -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" };

View File

@@ -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' },

View File

@@ -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);

View File

@@ -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"
},

View File

@@ -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();

View File

@@ -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();

View File

@@ -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));
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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