mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge branch 'stable'
# Conflicts: # package-lock.json # src/public/javascripts/services/server.js # src/services/app_info.js # src/services/notes.js
This commit is contained in:
commit
9a5a085103
6
db/migrations/0127__fix_inconsistent_isProtected.sql
Normal file
6
db/migrations/0127__fix_inconsistent_isProtected.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
UPDATE notes SET title = 'Recovered protected note', isProtected = 0 WHERE noteId IN (
|
||||||
|
SELECT noteId FROM notes JOIN note_contents USING(noteId)
|
||||||
|
WHERE notes.isProtected = 1
|
||||||
|
AND note_contents.isProtected = 0
|
||||||
|
AND notes.isDeleted = 0
|
||||||
|
)
|
@ -2,7 +2,7 @@
|
|||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"productName": "Trilium Notes",
|
"productName": "Trilium Notes",
|
||||||
"description": "Trilium Notes",
|
"description": "Trilium Notes",
|
||||||
"version": "0.30.6",
|
"version": "0.30.7",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -18,6 +18,10 @@ function setProtectedSessionTimeout(encSessTimeout) {
|
|||||||
protectedSessionTimeout = encSessTimeout;
|
protectedSessionTimeout = encSessTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getProtectedSessionId() {
|
||||||
|
return utils.getCookie(PROTECTED_SESSION_ID_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
function setProtectedSessionId(id) {
|
function setProtectedSessionId(id) {
|
||||||
// using session cookie so that it disappears after browser/tab is closed
|
// using session cookie so that it disappears after browser/tab is closed
|
||||||
utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, id);
|
utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, id);
|
||||||
@ -42,6 +46,7 @@ function touchProtectedSession() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
getProtectedSessionId,
|
||||||
setProtectedSessionId,
|
setProtectedSessionId,
|
||||||
resetProtectedSession,
|
resetProtectedSession,
|
||||||
isProtectedSessionAvailable,
|
isProtectedSessionAvailable,
|
||||||
|
@ -1,11 +1,22 @@
|
|||||||
|
import protectedSessionHolder from './protected_session_holder.js';
|
||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
import infoService from "./info.js";
|
import infoService from "./info.js";
|
||||||
|
|
||||||
function getHeaders() {
|
function getHeaders() {
|
||||||
|
let protectedSessionId = null;
|
||||||
|
|
||||||
|
try { // this is because protected session might not be declared in some cases
|
||||||
|
protectedSessionId = protectedSessionHolder.getProtectedSessionId();
|
||||||
|
}
|
||||||
|
catch(e) {}
|
||||||
|
|
||||||
// headers need to be lowercase because node.js automatically converts them to lower case
|
// headers need to be lowercase because node.js automatically converts them to lower case
|
||||||
// so hypothetical protectedSessionId becomes protectedsessionid on the backend
|
// so hypothetical protectedSessionId becomes protectedsessionid on the backend
|
||||||
// also avoiding using underscores instead of dashes since nginx filters them out by default
|
// also avoiding using underscores instead of dashes since nginx filters them out by default
|
||||||
return {
|
return {
|
||||||
|
// protectedSessionId is normally carried in cookie, but for electron AJAX requests we bypass
|
||||||
|
// HTTP so no cookies and we need to pass it here explicitly
|
||||||
|
'trilium-protected-session-id': protectedSessionId,
|
||||||
'trilium-source-id': glob.sourceId,
|
'trilium-source-id': glob.sourceId,
|
||||||
'x-csrf-token': glob.csrfToken
|
'x-csrf-token': glob.csrfToken
|
||||||
};
|
};
|
||||||
|
@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2019-03-28T23:17:24+01:00", buildRevision: "b2052a6ccda31712492cffc899ee132b0229613b" };
|
module.exports = { buildDate:"2019-03-30T20:13:53+01:00", buildRevision: "c240fb98967d11ea3925c2c39b44138bb8e46f58" };
|
||||||
|
@ -150,7 +150,7 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
|
|||||||
isProtected: !!extraOptions.isProtected,
|
isProtected: !!extraOptions.isProtected,
|
||||||
type: extraOptions.type,
|
type: extraOptions.type,
|
||||||
mime: extraOptions.mime,
|
mime: extraOptions.mime,
|
||||||
utcDateCreated: extraOptions.utcDateCreated,
|
dateCreated: extraOptions.dateCreated,
|
||||||
isExpanded: extraOptions.isExpanded,
|
isExpanded: extraOptions.isExpanded,
|
||||||
notePosition: extraOptions.notePosition
|
notePosition: extraOptions.notePosition
|
||||||
};
|
};
|
||||||
@ -307,12 +307,12 @@ async function saveNoteRevision(note) {
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
const noteRevisionSnapshotTimeInterval = parseInt(await optionService.getOption('noteRevisionSnapshotTimeInterval'));
|
const noteRevisionSnapshotTimeInterval = parseInt(await optionService.getOption('noteRevisionSnapshotTimeInterval'));
|
||||||
|
|
||||||
const revisionCutoff = dateUtils.utcDateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000));
|
const revisionCutoff = dateUtils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000));
|
||||||
|
|
||||||
const existingNoteRevisionId = await sql.getValue(
|
const existingNoteRevisionId = await sql.getValue(
|
||||||
"SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND utcDateModifiedTo >= ?", [note.noteId, revisionCutoff]);
|
"SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [note.noteId, revisionCutoff]);
|
||||||
|
|
||||||
const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.utcDateCreated).getTime();
|
const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.dateCreated).getTime();
|
||||||
|
|
||||||
if (!existingNoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
|
if (!existingNoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
|
||||||
await new NoteRevision({
|
await new NoteRevision({
|
||||||
@ -324,9 +324,7 @@ async function saveNoteRevision(note) {
|
|||||||
mime: note.mime,
|
mime: note.mime,
|
||||||
isProtected: false, // will be fixed in the protectNoteRevisions() call
|
isProtected: false, // will be fixed in the protectNoteRevisions() call
|
||||||
dateModifiedFrom: note.dateModified,
|
dateModifiedFrom: note.dateModified,
|
||||||
dateModifiedTo: dateUtils.localNowDateTime(),
|
dateModifiedTo: dateUtils.nowDate()
|
||||||
utcDateModifiedFrom: note.utcDateModified,
|
|
||||||
utcDateModifiedTo: dateUtils.utcNowDateTime()
|
|
||||||
}).save();
|
}).save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -346,11 +344,16 @@ async function updateNote(noteId, noteUpdates) {
|
|||||||
note.isProtected = noteUpdates.isProtected;
|
note.isProtected = noteUpdates.isProtected;
|
||||||
await note.save();
|
await note.save();
|
||||||
|
|
||||||
|
const noteContent = await note.getNoteContent();
|
||||||
|
|
||||||
if (!['file', 'image'].includes(note.type)) {
|
if (!['file', 'image'].includes(note.type)) {
|
||||||
noteUpdates.content = await saveLinks(note, noteUpdates.content);
|
noteUpdates.noteContent.content = await saveLinks(note, noteUpdates.noteContent.content);
|
||||||
|
|
||||||
|
noteContent.content = noteUpdates.noteContent.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
await note.setContent(noteUpdates.content);
|
noteContent.isProtected = noteUpdates.isProtected;
|
||||||
|
await noteContent.save();
|
||||||
|
|
||||||
if (noteTitleChanged) {
|
if (noteTitleChanged) {
|
||||||
await triggerNoteTitleChanged(note);
|
await triggerNoteTitleChanged(note);
|
||||||
@ -410,9 +413,9 @@ async function cleanupDeletedNotes() {
|
|||||||
// it's better to not use repository for this because it will complain about saving protected notes
|
// it's better to not use repository for this because it will complain about saving protected notes
|
||||||
// out of protected session
|
// out of protected session
|
||||||
|
|
||||||
await sql.execute("UPDATE note_contents SET content = NULL WHERE content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.utcDateModified <= ?)", [dateUtils.utcDateStr(cutoffDate)]);
|
await sql.execute("UPDATE note_contents SET content = NULL WHERE content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.dateModified <= ?)", [dateUtils.dateStr(cutoffDate)]);
|
||||||
|
|
||||||
await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.utcDateModified <= ?)", [dateUtils.utcDateStr(cutoffDate)]);
|
await sql.execute("UPDATE note_revisions SET content = NULL WHERE note_revisions.content IS NOT NULL AND noteId IN (SELECT noteId FROM notes WHERE isDeleted = 1 AND notes.dateModified <= ?)", [dateUtils.dateStr(cutoffDate)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlInit.dbReady.then(() => {
|
sqlInit.dbReady.then(() => {
|
||||||
|
@ -15,7 +15,8 @@ function setDataKey(decryptedDataKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setProtectedSessionId(req) {
|
function setProtectedSessionId(req) {
|
||||||
cls.namespace.set('protectedSessionId', req.cookies.protectedSessionId);
|
// cookies is the main storage but for electron header is used when bypassing HTTP
|
||||||
|
cls.namespace.set('protectedSessionId', req.headers['trilium-protected-session-id'] || req.cookies.protectedSessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProtectedSessionId() {
|
function getProtectedSessionId() {
|
||||||
@ -81,12 +82,17 @@ function decryptNoteRevision(hist) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hist.title) {
|
try {
|
||||||
hist.title = dataEncryptionService.decryptString(dataKey, hist.title);
|
if (hist.title) {
|
||||||
}
|
hist.title = dataEncryptionService.decryptString(dataKey, hist.title);
|
||||||
|
}
|
||||||
|
|
||||||
if (hist.content) {
|
if (hist.content) {
|
||||||
hist.content = dataEncryptionService.decryptString(dataKey, hist.content);
|
hist.content = dataEncryptionService.decryptString(dataKey, hist.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new Error(`Decryption failed for note ${hist.noteId}: ` + e.message + " " + e.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user