mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	added flag for the erased notes
This commit is contained in:
		
							
								
								
									
										31
									
								
								db/migrations/0151__add_isCleaned_to_note.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								db/migrations/0151__add_isCleaned_to_note.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | CREATE TABLE IF NOT EXISTS "notes_mig" ( | ||||||
|  |                                        `noteId`	TEXT NOT NULL, | ||||||
|  |                                        `title`	TEXT NOT NULL DEFAULT "note", | ||||||
|  |                                        `isProtected`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `type` TEXT NOT NULL DEFAULT 'text', | ||||||
|  |                                        `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||||
|  |                                        `hash` TEXT DEFAULT "" NOT NULL, | ||||||
|  |                                        `isDeleted`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `isErased`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `dateCreated`	TEXT NOT NULL, | ||||||
|  |                                        `dateModified`	TEXT NOT NULL, | ||||||
|  |                                        `utcDateCreated`	TEXT NOT NULL, | ||||||
|  |                                        `utcDateModified`	TEXT NOT NULL, | ||||||
|  |                                        PRIMARY KEY(`noteId`)); | ||||||
|  |  | ||||||
|  | INSERT INTO notes_mig (noteId, title, isProtected, type, mime, hash, isDeleted, isErased, dateCreated, dateModified, utcDateCreated, utcDateModified) | ||||||
|  | SELECT noteId, title, isProtected, type, mime, hash, isDeleted, 0, dateCreated, dateModified, utcDateCreated, utcDateModified FROM notes; | ||||||
|  |  | ||||||
|  | DROP TABLE notes; | ||||||
|  | ALTER TABLE notes_mig RENAME TO notes; | ||||||
|  |  | ||||||
|  | UPDATE notes SET isErased = 1 WHERE isDeleted = 1 | ||||||
|  | AND (SELECT CASE content WHEN NULL THEN 1 ELSE 0 END FROM note_contents WHERE note_contents.noteId = notes.noteId); | ||||||
|  |  | ||||||
|  | CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||||
|  | CREATE INDEX `IDX_notes_title` ON `notes` (`title`); | ||||||
|  | CREATE INDEX `IDX_notes_type` ON `notes` (`type`); | ||||||
|  | CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`); | ||||||
|  | CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`); | ||||||
|  | CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`); | ||||||
|  | CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`); | ||||||
| @@ -38,20 +38,6 @@ CREATE TABLE IF NOT EXISTS "attributes" | |||||||
|   isDeleted    INT  not null, |   isDeleted    INT  not null, | ||||||
|   hash         TEXT default "" not null, |   hash         TEXT default "" not null, | ||||||
|   isInheritable int DEFAULT 0 NULL); |   isInheritable int DEFAULT 0 NULL); | ||||||
| CREATE TABLE IF NOT EXISTS "notes" ( |  | ||||||
|                                      `noteId`	TEXT NOT NULL, |  | ||||||
|                                      `title`	TEXT NOT NULL DEFAULT "note", |  | ||||||
|                                      `isProtected`	INT NOT NULL DEFAULT 0, |  | ||||||
|                                      `type` TEXT NOT NULL DEFAULT 'text', |  | ||||||
|                                      `mime` TEXT NOT NULL DEFAULT 'text/html', |  | ||||||
|                                      `hash` TEXT DEFAULT "" NOT NULL, |  | ||||||
|                                      `isDeleted`	INT NOT NULL DEFAULT 0, |  | ||||||
|                                      `dateCreated`	TEXT NOT NULL, |  | ||||||
|                                      `dateModified`	TEXT NOT NULL, |  | ||||||
|                                      `utcDateCreated`	TEXT NOT NULL, |  | ||||||
|                                      `utcDateModified`	TEXT NOT NULL, |  | ||||||
|                                      PRIMARY KEY(`noteId`) |  | ||||||
| ); |  | ||||||
| CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | CREATE UNIQUE INDEX `IDX_sync_entityName_entityId` ON `sync` ( | ||||||
|                                                               `entityName`, |                                                               `entityName`, | ||||||
|                                                               `entityId` |                                                               `entityId` | ||||||
| @@ -119,3 +105,24 @@ CREATE INDEX `IDX_note_revisions_utcDateCreated` ON `note_revisions` (`utcDateCr | |||||||
| CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`); | CREATE INDEX `IDX_note_revisions_utcDateLastEdited` ON `note_revisions` (`utcDateLastEdited`); | ||||||
| CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); | CREATE INDEX `IDX_note_revisions_dateCreated` ON `note_revisions` (`dateCreated`); | ||||||
| CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`); | CREATE INDEX `IDX_note_revisions_dateLastEdited` ON `note_revisions` (`dateLastEdited`); | ||||||
|  | CREATE TABLE IF NOT EXISTS "notes" ( | ||||||
|  |                                        `noteId`	TEXT NOT NULL, | ||||||
|  |                                        `title`	TEXT NOT NULL DEFAULT "note", | ||||||
|  |                                        `isProtected`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `type` TEXT NOT NULL DEFAULT 'text', | ||||||
|  |                                        `mime` TEXT NOT NULL DEFAULT 'text/html', | ||||||
|  |                                        `hash` TEXT DEFAULT "" NOT NULL, | ||||||
|  |                                        `isDeleted`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `isErased`	INT NOT NULL DEFAULT 0, | ||||||
|  |                                        `dateCreated`	TEXT NOT NULL, | ||||||
|  |                                        `dateModified`	TEXT NOT NULL, | ||||||
|  |                                        `utcDateCreated`	TEXT NOT NULL, | ||||||
|  |                                        `utcDateModified`	TEXT NOT NULL, | ||||||
|  |                                        PRIMARY KEY(`noteId`)); | ||||||
|  | CREATE INDEX `IDX_notes_isDeleted` ON `notes` (`isDeleted`); | ||||||
|  | CREATE INDEX `IDX_notes_title` ON `notes` (`title`); | ||||||
|  | CREATE INDEX `IDX_notes_type` ON `notes` (`type`); | ||||||
|  | CREATE INDEX `IDX_notes_dateCreated` ON `notes` (`dateCreated`); | ||||||
|  | CREATE INDEX `IDX_notes_dateModified` ON `notes` (`dateModified`); | ||||||
|  | CREATE INDEX `IDX_notes_utcDateModified` ON `notes` (`utcDateModified`); | ||||||
|  | CREATE INDEX `IDX_notes_utcDateCreated` ON `notes` (`utcDateCreated`); | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "trilium", |   "name": "trilium", | ||||||
|   "version": "0.36.1-beta", |   "version": "0.36.2", | ||||||
|   "lockfileVersion": 1, |   "lockfileVersion": 1, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
| @@ -5219,9 +5219,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "file-type": { |     "file-type": { | ||||||
|       "version": "12.3.1", |       "version": "12.4.0", | ||||||
|       "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.3.1.tgz", |       "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.0.tgz", | ||||||
|       "integrity": "sha512-FXxY5h6vSYMjrRal4YqbtfuoKD/oE0AMjJ7E5Hm+BdaQECcFVD03B41RAWYJ7wyuLr/wRnCtFo7y37l+nh+TAA==" |       "integrity": "sha512-WTvyKq8yjtNmUtVAD8LGcTkvtCdJglM6ks2HTqEClm6+65XTqM6MoZYA1Vtra50DLRWLiM38fEs1y56f5VhnUA==" | ||||||
|     }, |     }, | ||||||
|     "filename-regex": { |     "filename-regex": { | ||||||
|       "version": "2.0.1", |       "version": "2.0.1", | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ | |||||||
|     "electron-window-state": "5.0.3", |     "electron-window-state": "5.0.3", | ||||||
|     "express": "4.17.1", |     "express": "4.17.1", | ||||||
|     "express-session": "1.17.0", |     "express-session": "1.17.0", | ||||||
|     "file-type": "12.3.1", |     "file-type": "12.4.0", | ||||||
|     "fs-extra": "8.1.0", |     "fs-extra": "8.1.0", | ||||||
|     "helmet": "3.21.2", |     "helmet": "3.21.2", | ||||||
|     "html": "1.0.0", |     "html": "1.0.0", | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ const RELATION_DEFINITION = 'relation-definition'; | |||||||
|  * @property {string} title - note title |  * @property {string} title - note title | ||||||
|  * @property {boolean} isProtected - true if note is protected |  * @property {boolean} isProtected - true if note is protected | ||||||
|  * @property {boolean} isDeleted - true if note is deleted |  * @property {boolean} isDeleted - true if note is deleted | ||||||
|  |  * @property {boolean} isErased - true if note's content is erased after it has been deleted | ||||||
|  * @property {string} dateCreated - local date time (with offset) |  * @property {string} dateCreated - local date time (with offset) | ||||||
|  * @property {string} dateModified - local date time (with offset) |  * @property {string} dateModified - local date time (with offset) | ||||||
|  * @property {string} utcDateCreated |  * @property {string} utcDateCreated | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ const build = require('./build'); | |||||||
| const packageJson = require('../../package'); | const packageJson = require('../../package'); | ||||||
| const {TRILIUM_DATA_DIR} = require('./data_dir'); | const {TRILIUM_DATA_DIR} = require('./data_dir'); | ||||||
|  |  | ||||||
| const APP_DB_VERSION = 150; | const APP_DB_VERSION = 151; | ||||||
| const SYNC_VERSION = 11; | const SYNC_VERSION = 11; | ||||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -228,6 +228,23 @@ async function findLogicIssues() { | |||||||
|             AND content IS NULL`, |             AND content IS NULL`, | ||||||
|         ({noteId}) => `Note ${noteId} content is null even though it is not deleted`); |         ({noteId}) => `Note ${noteId} content is null even though it is not deleted`); | ||||||
|  |  | ||||||
|  |     await findIssues(` | ||||||
|  |           SELECT noteId | ||||||
|  |           FROM notes | ||||||
|  |           JOIN note_contents USING(noteId) | ||||||
|  |           WHERE | ||||||
|  |             isErased = 1 | ||||||
|  |             AND content IS NOT NULL`, | ||||||
|  |         ({noteId}) => `Note ${noteId} content is not null even though the note is erased`); | ||||||
|  |  | ||||||
|  |     await findIssues(` | ||||||
|  |         SELECT noteId | ||||||
|  |         FROM notes | ||||||
|  |         WHERE | ||||||
|  |             isErased = 1 | ||||||
|  |             AND isDeleted = 0`, | ||||||
|  |         ({noteId}) => `Note ${noteId} is not deleted even though it is erased`); | ||||||
|  |  | ||||||
|     await findIssues(` |     await findIssues(` | ||||||
|           SELECT parentNoteId |           SELECT parentNoteId | ||||||
|           FROM  |           FROM  | ||||||
|   | |||||||
| @@ -457,15 +457,35 @@ async function scanForLinks(noteId) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function cleanupDeletedNotes() { | async function eraseDeletedNotes() { | ||||||
|     const cutoffDate = new Date(Date.now() - 48 * 3600 * 1000); |     const cutoffDate = new Date(Date.now() - 48 * 3600 * 1000); | ||||||
|  |  | ||||||
|  |     const noteIdsToErase = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 1 AND isErased = 0 AND notes.utcDateModified <= ?", [dateUtils.utcDateStr(cutoffDate)]); | ||||||
|  |  | ||||||
|  |     const utcNowDateTime = dateUtils.utcNowDateTime(); | ||||||
|  |     const localNowDateTime = dateUtils.localNowDateTime(); | ||||||
|  |  | ||||||
|     // 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.executeMany(` | ||||||
|  |         UPDATE notes  | ||||||
|  |         SET isErased = 1,  | ||||||
|  |             utcDateModified = '${utcNowDateTime}', | ||||||
|  |             dateModified = '${localNowDateTime}' | ||||||
|  |         WHERE noteId IN (???)`, noteIdsToErase); | ||||||
|  |  | ||||||
|     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.executeMany(` | ||||||
|  |         UPDATE note_contents  | ||||||
|  |         SET content = NULL, | ||||||
|  |             utcDateModified = '${utcNowDateTime}'  | ||||||
|  |         WHERE noteId IN (???)`, noteIdsToErase); | ||||||
|  |  | ||||||
|  |     await sql.executeMany(` | ||||||
|  |         UPDATE note_revisions  | ||||||
|  |         SET content = NULL, | ||||||
|  |             utcDateModified = '${utcNowDateTime}' | ||||||
|  |         WHERE noteId IN (???)`, noteIdsToErase); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function duplicateNote(noteId, parentNoteId) { | async function duplicateNote(noteId, parentNoteId) { | ||||||
| @@ -508,9 +528,9 @@ async function duplicateNote(noteId, parentNoteId) { | |||||||
|  |  | ||||||
| sqlInit.dbReady.then(() => { | sqlInit.dbReady.then(() => { | ||||||
|     // first cleanup kickoff 5 minutes after startup |     // first cleanup kickoff 5 minutes after startup | ||||||
|     setTimeout(cls.wrap(cleanupDeletedNotes), 5 * 60 * 1000); |     setTimeout(cls.wrap(eraseDeletedNotes), 5 * 60 * 1000); | ||||||
|  |  | ||||||
|     setInterval(cls.wrap(cleanupDeletedNotes), 4 * 3600 * 1000); |     setInterval(cls.wrap(eraseDeletedNotes), 4 * 3600 * 1000); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
| @@ -152,6 +152,11 @@ async function execute(query, params = []) { | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function executeMany(query, params) { | ||||||
|  |     // essentially just alias | ||||||
|  |     await getManyRows(query, params); | ||||||
|  | } | ||||||
|  |  | ||||||
| async function executeScript(query) { | async function executeScript(query) { | ||||||
|     return await wrap(async db => db.exec(query)); |     return await wrap(async db => db.exec(query)); | ||||||
| } | } | ||||||
| @@ -235,6 +240,7 @@ module.exports = { | |||||||
|     getMap, |     getMap, | ||||||
|     getColumn, |     getColumn, | ||||||
|     execute, |     execute, | ||||||
|  |     executeMany, | ||||||
|     executeScript, |     executeScript, | ||||||
|     transactional, |     transactional, | ||||||
|     upsert |     upsert | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user