Compare commits

...

5 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
17 changed files with 92 additions and 37 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 . .

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "trilium",
"version": "0.52.1-beta",
"version": "0.52.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "trilium",
"version": "0.52.1-beta",
"version": "0.52.3",
"hasInstallScript": true,
"license": "AGPL-3.0-only",
"dependencies": {

View File

@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "Trilium Notes",
"description": "Trilium Notes",
"version": "0.52.2",
"version": "0.52.4",
"license": "AGPL-3.0-only",
"main": "electron.js",
"bin": {

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

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

@@ -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-09T23:39:48+02:00", buildRevision: "96c4934c00703a93e4887af1bab20d953823c8ed" };
module.exports = { buildDate:"2022-07-01T00:11:53+02:00", buildRevision: "3faae63b849a1fabc31b823bb7af3a84d32256a7" };

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

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

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