mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +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:
		
							
								
								
									
										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", | ||||
|   "productName": "Trilium Notes", | ||||
|   "description": "Trilium Notes", | ||||
|   "version": "0.30.6", | ||||
|   "version": "0.30.7", | ||||
|   "license": "AGPL-3.0-only", | ||||
|   "main": "electron.js", | ||||
|   "bin": { | ||||
|   | ||||
| @@ -18,6 +18,10 @@ function setProtectedSessionTimeout(encSessTimeout) { | ||||
|     protectedSessionTimeout = encSessTimeout; | ||||
| } | ||||
|  | ||||
| function getProtectedSessionId() { | ||||
|     return utils.getCookie(PROTECTED_SESSION_ID_KEY); | ||||
| } | ||||
|  | ||||
| function setProtectedSessionId(id) { | ||||
|     // using session cookie so that it disappears after browser/tab is closed | ||||
|     utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, id); | ||||
| @@ -42,6 +46,7 @@ function touchProtectedSession() { | ||||
| } | ||||
|  | ||||
| export default { | ||||
|     getProtectedSessionId, | ||||
|     setProtectedSessionId, | ||||
|     resetProtectedSession, | ||||
|     isProtectedSessionAvailable, | ||||
|   | ||||
| @@ -1,11 +1,22 @@ | ||||
| import protectedSessionHolder from './protected_session_holder.js'; | ||||
| import utils from './utils.js'; | ||||
| import infoService from "./info.js"; | ||||
|  | ||||
| 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 | ||||
|     // so hypothetical protectedSessionId becomes protectedsessionid on the backend | ||||
|     // also avoiding using underscores instead of dashes since nginx filters them out by default | ||||
|     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, | ||||
|         '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, | ||||
|         type: extraOptions.type, | ||||
|         mime: extraOptions.mime, | ||||
|         utcDateCreated: extraOptions.utcDateCreated, | ||||
|         dateCreated: extraOptions.dateCreated, | ||||
|         isExpanded: extraOptions.isExpanded, | ||||
|         notePosition: extraOptions.notePosition | ||||
|     }; | ||||
| @@ -307,12 +307,12 @@ async function saveNoteRevision(note) { | ||||
|     const now = new Date(); | ||||
|     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( | ||||
|         "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) { | ||||
|         await new NoteRevision({ | ||||
| @@ -324,9 +324,7 @@ async function saveNoteRevision(note) { | ||||
|             mime: note.mime, | ||||
|             isProtected: false, // will be fixed in the protectNoteRevisions() call | ||||
|             dateModifiedFrom: note.dateModified, | ||||
|             dateModifiedTo: dateUtils.localNowDateTime(), | ||||
|             utcDateModifiedFrom: note.utcDateModified, | ||||
|             utcDateModifiedTo: dateUtils.utcNowDateTime() | ||||
|             dateModifiedTo: dateUtils.nowDate() | ||||
|         }).save(); | ||||
|     } | ||||
| } | ||||
| @@ -346,11 +344,16 @@ async function updateNote(noteId, noteUpdates) { | ||||
|     note.isProtected = noteUpdates.isProtected; | ||||
|     await note.save(); | ||||
|  | ||||
|     const noteContent = await note.getNoteContent(); | ||||
|  | ||||
|     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) { | ||||
|         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 | ||||
|     // 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(() => { | ||||
|   | ||||
| @@ -15,7 +15,8 @@ function setDataKey(decryptedDataKey) { | ||||
| } | ||||
|  | ||||
| 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() { | ||||
| @@ -81,6 +82,7 @@ function decryptNoteRevision(hist) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|         if (hist.title) { | ||||
|             hist.title = dataEncryptionService.decryptString(dataKey, hist.title); | ||||
|         } | ||||
| @@ -88,6 +90,10 @@ function decryptNoteRevision(hist) { | ||||
|         if (hist.content) { | ||||
|             hist.content = dataEncryptionService.decryptString(dataKey, hist.content); | ||||
|         } | ||||
|     } | ||||
|     catch (e) { | ||||
|         throw new Error(`Decryption failed for note ${hist.noteId}: ` + e.message + " " + e.stack); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function encryptNote(note) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user