mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	add memberId to entity_changes to avoid having to resend all changes second time
This commit is contained in:
		| @@ -44,7 +44,7 @@ find $DIR/node_modules -name demo -exec rm -rf {} \; | |||||||
|  |  | ||||||
| find $DIR/libraries -name "*.map" -type f -delete | find $DIR/libraries -name "*.map" -type f -delete | ||||||
|  |  | ||||||
| rm -r $DIR/src/public/app | rm -rf $DIR/src/public/app | ||||||
|  |  | ||||||
| sed -i -e 's/app\/desktop.js/app-dist\/desktop.js/g' $DIR/src/views/desktop.ejs | sed -i -e 's/app\/desktop.js/app-dist\/desktop.js/g' $DIR/src/views/desktop.ejs | ||||||
| sed -i -e 's/app\/mobile.js/app-dist\/mobile.js/g' $DIR/src/views/mobile.ejs | sed -i -e 's/app\/mobile.js/app-dist\/mobile.js/g' $DIR/src/views/mobile.ejs | ||||||
|   | |||||||
| @@ -5,7 +5,8 @@ CREATE TABLE IF NOT EXISTS "entity_changes" ( | |||||||
|                                                 `hash`	TEXT NOT NULL, |                                                 `hash`	TEXT NOT NULL, | ||||||
|                                                 `isErased` INT NOT NULL, |                                                 `isErased` INT NOT NULL, | ||||||
|                                                 `changeId` TEXT NOT NULL, |                                                 `changeId` TEXT NOT NULL, | ||||||
|                                                 `sourceId` TEXT NOT NULL, |                                                 `componentId` TEXT NOT NULL, | ||||||
|  |                                                 `memberId` TEXT NOT NULL, | ||||||
|                                                 `isSynced` INTEGER NOT NULL, |                                                 `isSynced` INTEGER NOT NULL, | ||||||
|                                                 `utcDateChanged` TEXT NOT NULL |                                                 `utcDateChanged` TEXT NOT NULL | ||||||
|                                                 ); |                                                 ); | ||||||
|   | |||||||
							
								
								
									
										11484
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11484
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -43,10 +43,10 @@ | |||||||
|     "@electron/remote": "2.0.1", |     "@electron/remote": "2.0.1", | ||||||
|     "express": "4.17.2", |     "express": "4.17.2", | ||||||
|     "express-partial-content": "^1.0.2", |     "express-partial-content": "^1.0.2", | ||||||
|     "express-rate-limit": "5.5.1", |     "express-rate-limit": "6.0.5", | ||||||
|     "express-session": "1.17.2", |     "express-session": "1.17.2", | ||||||
|     "fs-extra": "10.0.0", |     "fs-extra": "10.0.0", | ||||||
|     "helmet": "4.6.0", |     "helmet": "5.0.1", | ||||||
|     "html": "1.0.0", |     "html": "1.0.0", | ||||||
|     "html2plaintext": "2.1.4", |     "html2plaintext": "2.1.4", | ||||||
|     "http-proxy-agent": "5.0.0", |     "http-proxy-agent": "5.0.0", | ||||||
| @@ -88,7 +88,7 @@ | |||||||
|     "electron-packager": "15.4.0", |     "electron-packager": "15.4.0", | ||||||
|     "electron-rebuild": "3.2.5", |     "electron-rebuild": "3.2.5", | ||||||
|     "esm": "3.2.25", |     "esm": "3.2.25", | ||||||
|     "jasmine": "3.10.0", |     "jasmine": "4.0.1", | ||||||
|     "jsdoc": "3.6.7", |     "jsdoc": "3.6.7", | ||||||
|     "lorem-ipsum": "2.0.4", |     "lorem-ipsum": "2.0.4", | ||||||
|     "rcedit": "3.0.1", |     "rcedit": "3.0.1", | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ function route(router, method, path, routeHandler) { | |||||||
|             cls.namespace.bindEmitter(res); |             cls.namespace.bindEmitter(res); | ||||||
|  |  | ||||||
|             cls.init(() => { |             cls.init(() => { | ||||||
|                 cls.set('sourceId', "etapi"); |                 cls.set('componentId', "etapi"); | ||||||
|                 cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']); |                 cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']); | ||||||
|  |  | ||||||
|                 const cb = () => routeHandler(req, res, next); |                 const cb = () => routeHandler(req, res, next); | ||||||
|   | |||||||
| @@ -22,9 +22,9 @@ async function processEntityChanges(entityChanges) { | |||||||
|             } else if (ec.entityName === 'note_contents') { |             } else if (ec.entityName === 'note_contents') { | ||||||
|                 delete froca.noteComplementPromises[ec.entityId]; |                 delete froca.noteComplementPromises[ec.entityId]; | ||||||
|  |  | ||||||
|                 loadResults.addNoteContent(ec.entityId, ec.sourceId); |                 loadResults.addNoteContent(ec.entityId, ec.componentId); | ||||||
|             } else if (ec.entityName === 'note_revisions') { |             } else if (ec.entityName === 'note_revisions') { | ||||||
|                 loadResults.addNoteRevision(ec.entityId, ec.noteId, ec.sourceId); |                 loadResults.addNoteRevision(ec.entityId, ec.noteId, ec.componentId); | ||||||
|             } else if (ec.entityName === 'note_revision_contents') { |             } else if (ec.entityName === 'note_revision_contents') { | ||||||
|                 // this should change only when toggling isProtected, ignore |                 // this should change only when toggling isProtected, ignore | ||||||
|             } else if (ec.entityName === 'options') { |             } else if (ec.entityName === 'options') { | ||||||
| @@ -87,7 +87,7 @@ function processNoteChange(loadResults, ec) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     loadResults.addNote(ec.entityId, ec.sourceId); |     loadResults.addNote(ec.entityId, ec.componentId); | ||||||
|  |  | ||||||
|     if (ec.isErased && ec.entityId in froca.notes) { |     if (ec.isErased && ec.entityId in froca.notes) { | ||||||
|         utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`); |         utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`); | ||||||
| @@ -125,7 +125,7 @@ function processBranchChange(loadResults, ec) { | |||||||
|                 delete parentNote.childToBranch[branch.noteId]; |                 delete parentNote.childToBranch[branch.noteId]; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             loadResults.addBranch(ec.entityId, ec.sourceId); |             loadResults.addBranch(ec.entityId, ec.componentId); | ||||||
|  |  | ||||||
|             delete froca.branches[ec.entityId]; |             delete froca.branches[ec.entityId]; | ||||||
|         } |         } | ||||||
| @@ -133,7 +133,7 @@ function processBranchChange(loadResults, ec) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     loadResults.addBranch(ec.entityId, ec.sourceId); |     loadResults.addBranch(ec.entityId, ec.componentId); | ||||||
|  |  | ||||||
|     const childNote = froca.notes[ec.entity.noteId]; |     const childNote = froca.notes[ec.entity.noteId]; | ||||||
|     const parentNote = froca.notes[ec.entity.parentNoteId]; |     const parentNote = froca.notes[ec.entity.parentNoteId]; | ||||||
| @@ -175,7 +175,7 @@ function processNoteReordering(loadResults, ec) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     loadResults.addNoteReordering(ec.entityId, ec.sourceId); |     loadResults.addNoteReordering(ec.entityId, ec.componentId); | ||||||
| } | } | ||||||
|  |  | ||||||
| function processAttributeChange(loadResults, ec) { | function processAttributeChange(loadResults, ec) { | ||||||
| @@ -199,7 +199,7 @@ function processAttributeChange(loadResults, ec) { | |||||||
|                 targetNote.targetRelations = targetNote.targetRelations.filter(attributeId => attributeId !== attribute.attributeId); |                 targetNote.targetRelations = targetNote.targetRelations.filter(attributeId => attributeId !== attribute.attributeId); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             loadResults.addAttribute(ec.entityId, ec.sourceId); |             loadResults.addAttribute(ec.entityId, ec.componentId); | ||||||
|  |  | ||||||
|             delete froca.attributes[ec.entityId]; |             delete froca.attributes[ec.entityId]; | ||||||
|         } |         } | ||||||
| @@ -207,7 +207,7 @@ function processAttributeChange(loadResults, ec) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     loadResults.addAttribute(ec.entityId, ec.sourceId); |     loadResults.addAttribute(ec.entityId, ec.componentId); | ||||||
|  |  | ||||||
|     const sourceNote = froca.notes[ec.entity.noteId]; |     const sourceNote = froca.notes[ec.entity.noteId]; | ||||||
|     const targetNote = ec.entity.type === 'relation' && froca.notes[ec.entity.value]; |     const targetNote = ec.entity.type === 'relation' && froca.notes[ec.entity.value]; | ||||||
|   | |||||||
| @@ -9,8 +9,8 @@ export default class LoadResults { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         this.noteIdToSourceId = {}; |         this.noteIdToComponentId = {}; | ||||||
|         this.sourceIdToNoteIds = {}; |         this.componentIdToNoteIds = {}; | ||||||
|  |  | ||||||
|         this.branches = []; |         this.branches = []; | ||||||
|  |  | ||||||
| @@ -20,7 +20,7 @@ export default class LoadResults { | |||||||
|  |  | ||||||
|         this.noteRevisions = []; |         this.noteRevisions = []; | ||||||
|  |  | ||||||
|         this.contentNoteIdToSourceId = []; |         this.contentNoteIdToComponentId = []; | ||||||
|  |  | ||||||
|         this.options = []; |         this.options = []; | ||||||
|     } |     } | ||||||
| @@ -29,22 +29,22 @@ export default class LoadResults { | |||||||
|         return this.entities[entityName]?.[entityId]; |         return this.entities[entityName]?.[entityId]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addNote(noteId, sourceId) { |     addNote(noteId, componentId) { | ||||||
|         this.noteIdToSourceId[noteId] = this.noteIdToSourceId[noteId] || []; |         this.noteIdToComponentId[noteId] = this.noteIdToComponentId[noteId] || []; | ||||||
|  |  | ||||||
|         if (!this.noteIdToSourceId[noteId].includes(sourceId)) { |         if (!this.noteIdToComponentId[noteId].includes(componentId)) { | ||||||
|             this.noteIdToSourceId[noteId].push(sourceId); |             this.noteIdToComponentId[noteId].push(componentId); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         this.sourceIdToNoteIds[sourceId] = this.sourceIdToNoteIds[sourceId] || []; |         this.componentIdToNoteIds[componentId] = this.componentIdToNoteIds[componentId] || []; | ||||||
|  |  | ||||||
|         if (!this.sourceIdToNoteIds[sourceId]) { |         if (!this.componentIdToNoteIds[componentId]) { | ||||||
|             this.sourceIdToNoteIds[sourceId].push(noteId); |             this.componentIdToNoteIds[componentId].push(noteId); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addBranch(branchId, sourceId) { |     addBranch(branchId, componentId) { | ||||||
|         this.branches.push({branchId, sourceId}); |         this.branches.push({branchId, componentId}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     getBranches() { |     getBranches() { | ||||||
| @@ -53,7 +53,7 @@ export default class LoadResults { | |||||||
|             .filter(branch => !!branch); |             .filter(branch => !!branch); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addNoteReordering(parentNoteId, sourceId) { |     addNoteReordering(parentNoteId, componentId) { | ||||||
|         this.noteReorderings.push(parentNoteId); |         this.noteReorderings.push(parentNoteId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -61,20 +61,20 @@ export default class LoadResults { | |||||||
|         return this.noteReorderings; |         return this.noteReorderings; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addAttribute(attributeId, sourceId) { |     addAttribute(attributeId, componentId) { | ||||||
|         this.attributes.push({attributeId, sourceId}); |         this.attributes.push({attributeId, componentId}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** @returns {Attribute[]} */ |     /** @returns {Attribute[]} */ | ||||||
|     getAttributes(sourceId = 'none') { |     getAttributes(componentId = 'none') { | ||||||
|         return this.attributes |         return this.attributes | ||||||
|             .filter(row => row.sourceId !== sourceId) |             .filter(row => row.componentId !== componentId) | ||||||
|             .map(row => this.getEntity("attributes", row.attributeId)) |             .map(row => this.getEntity("attributes", row.attributeId)) | ||||||
|             .filter(attr => !!attr); |             .filter(attr => !!attr); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addNoteRevision(noteRevisionId, noteId, sourceId) { |     addNoteRevision(noteRevisionId, noteId, componentId) { | ||||||
|         this.noteRevisions.push({noteRevisionId, noteId, sourceId}); |         this.noteRevisions.push({noteRevisionId, noteId, componentId}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     hasNoteRevisionForNote(noteId) { |     hasNoteRevisionForNote(noteId) { | ||||||
| @@ -82,28 +82,28 @@ export default class LoadResults { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     getNoteIds() { |     getNoteIds() { | ||||||
|         return Object.keys(this.noteIdToSourceId); |         return Object.keys(this.noteIdToComponentId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isNoteReloaded(noteId, sourceId = null) { |     isNoteReloaded(noteId, componentId = null) { | ||||||
|         if (!noteId) { |         if (!noteId) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         const sourceIds = this.noteIdToSourceId[noteId]; |         const componentIds = this.noteIdToComponentId[noteId]; | ||||||
|         return sourceIds && !!sourceIds.find(sId => sId !== sourceId); |         return componentIds && !!componentIds.find(sId => sId !== componentId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addNoteContent(noteId, sourceId) { |     addNoteContent(noteId, componentId) { | ||||||
|         this.contentNoteIdToSourceId.push({noteId, sourceId}); |         this.contentNoteIdToComponentId.push({noteId, componentId}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isNoteContentReloaded(noteId, sourceId) { |     isNoteContentReloaded(noteId, componentId) { | ||||||
|         if (!noteId) { |         if (!noteId) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return this.contentNoteIdToSourceId.find(l => l.noteId === noteId && l.sourceId !== sourceId); |         return this.contentNoteIdToComponentId.find(l => l.noteId === noteId && l.componentId !== componentId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     addOption(name) { |     addOption(name) { | ||||||
| @@ -124,17 +124,17 @@ export default class LoadResults { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     isEmpty() { |     isEmpty() { | ||||||
|         return Object.keys(this.noteIdToSourceId).length === 0 |         return Object.keys(this.noteIdToComponentId).length === 0 | ||||||
|             && this.branches.length === 0 |             && this.branches.length === 0 | ||||||
|             && this.attributes.length === 0 |             && this.attributes.length === 0 | ||||||
|             && this.noteReorderings.length === 0 |             && this.noteReorderings.length === 0 | ||||||
|             && this.noteRevisions.length === 0 |             && this.noteRevisions.length === 0 | ||||||
|             && this.contentNoteIdToSourceId.length === 0 |             && this.contentNoteIdToComponentId.length === 0 | ||||||
|             && this.options.length === 0; |             && this.options.length === 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isEmptyForTree() { |     isEmptyForTree() { | ||||||
|         return Object.keys(this.noteIdToSourceId).length === 0 |         return Object.keys(this.noteIdToComponentId).length === 0 | ||||||
|             && this.branches.length === 0 |             && this.branches.length === 0 | ||||||
|             && this.attributes.length === 0 |             && this.attributes.length === 0 | ||||||
|             && this.noteReorderings.length === 0; |             && this.noteReorderings.length === 0; | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ async function getHeaders(headers) { | |||||||
|     // 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 | ||||||
|     // 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 | ||||||
|     const allHeaders = { |     const allHeaders = { | ||||||
|         'trilium-source-id': glob.sourceId, |         'trilium-component-id': glob.componentId, | ||||||
|         'trilium-local-now-datetime': utils.localNowDateTime(), |         'trilium-local-now-datetime': utils.localNowDateTime(), | ||||||
|         'trilium-hoisted-note-id': activeNoteContext ? activeNoteContext.hoistedNoteId : null, |         'trilium-hoisted-note-id': activeNoteContext ? activeNoteContext.hoistedNoteId : null, | ||||||
|         'x-csrf-token': glob.csrfToken |         'x-csrf-token': glob.csrfToken | ||||||
| @@ -29,20 +29,20 @@ async function getHeaders(headers) { | |||||||
|     return allHeaders; |     return allHeaders; | ||||||
| } | } | ||||||
|  |  | ||||||
| async function get(url, sourceId) { | async function get(url, componentId) { | ||||||
|     return await call('GET', url, null, {'trilium-source-id': sourceId}); |     return await call('GET', url, null, {'trilium-component-id': componentId}); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function post(url, data, sourceId) { | async function post(url, data, componentId) { | ||||||
|     return await call('POST', url, data, {'trilium-source-id': sourceId}); |     return await call('POST', url, data, {'trilium-component-id': componentId}); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function put(url, data, sourceId) { | async function put(url, data, componentId) { | ||||||
|     return await call('PUT', url, data, {'trilium-source-id': sourceId}); |     return await call('PUT', url, data, {'trilium-component-id': componentId}); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function remove(url, sourceId) { | async function remove(url, componentId) { | ||||||
|     return await call('DELETE', url, null, {'trilium-source-id': sourceId}); |     return await call('DELETE', url, null, {'trilium-component-id': componentId}); | ||||||
| } | } | ||||||
|  |  | ||||||
| let i = 1; | let i = 1; | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ function SetupModel() { | |||||||
|  |  | ||||||
|     this.syncServerHost = ko.observable(); |     this.syncServerHost = ko.observable(); | ||||||
|     this.syncProxy = ko.observable(); |     this.syncProxy = ko.observable(); | ||||||
|  |     this.password = ko.observable(); | ||||||
|  |  | ||||||
|     this.instanceType = utils.isElectron() ? "desktop" : "server"; |     this.instanceType = utils.isElectron() ? "desktop" : "server"; | ||||||
|  |  | ||||||
| @@ -48,19 +49,13 @@ function SetupModel() { | |||||||
|     this.finish = async () => { |     this.finish = async () => { | ||||||
|         const syncServerHost = this.syncServerHost(); |         const syncServerHost = this.syncServerHost(); | ||||||
|         const syncProxy = this.syncProxy(); |         const syncProxy = this.syncProxy(); | ||||||
|         const username = this.username(); |         const password = this.password(); | ||||||
|         const password = this.password1(); |  | ||||||
|  |  | ||||||
|         if (!syncServerHost) { |         if (!syncServerHost) { | ||||||
|             showAlert("Trilium server address can't be empty"); |             showAlert("Trilium server address can't be empty"); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!username) { |  | ||||||
|             showAlert("Username can't be empty"); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (!password) { |         if (!password) { | ||||||
|             showAlert("Password can't be empty"); |             showAlert("Password can't be empty"); | ||||||
|             return; |             return; | ||||||
| @@ -70,7 +65,6 @@ function SetupModel() { | |||||||
|         const resp = await $.post('api/setup/sync-from-server', { |         const resp = await $.post('api/setup/sync-from-server', { | ||||||
|             syncServerHost: syncServerHost, |             syncServerHost: syncServerHost, | ||||||
|             syncProxy: syncProxy, |             syncProxy: syncProxy, | ||||||
|             username: username, |  | ||||||
|             password: password |             password: password | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| const options = require('../../services/options'); | const options = require('../../services/options'); | ||||||
| const utils = require('../../services/utils'); | const utils = require('../../services/utils'); | ||||||
| const dateUtils = require('../../services/date_utils'); | const dateUtils = require('../../services/date_utils'); | ||||||
| const sourceIdService = require('../../services/source_id'); | const memberId = require('../../services/member_id'); | ||||||
| const passwordEncryptionService = require('../../services/password_encryption'); | const passwordEncryptionService = require('../../services/password_encryption'); | ||||||
| const protectedSessionService = require('../../services/protected_session'); | const protectedSessionService = require('../../services/protected_session'); | ||||||
| const appInfo = require('../../services/app_info'); | const appInfo = require('../../services/app_info'); | ||||||
| @@ -47,7 +47,7 @@ function loginSync(req) { | |||||||
|     req.session.loggedIn = true; |     req.session.loggedIn = true; | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|         sourceId: sourceIdService.getCurrentSourceId(), |         memberId: memberId, | ||||||
|         maxEntityChangeId: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1") |         maxEntityChangeId: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1") | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -123,13 +123,36 @@ function forceNoteSync(req) { | |||||||
| function getChanged(req) { | function getChanged(req) { | ||||||
|     const startTime = Date.now(); |     const startTime = Date.now(); | ||||||
|  |  | ||||||
|     const lastEntityChangeId = parseInt(req.query.lastEntityChangeId); |     let lastEntityChangeId = parseInt(req.query.lastEntityChangeId); | ||||||
|  |     const clientMemberId = req.query.memberId; | ||||||
|  |     let filteredEntityChanges = []; | ||||||
|  |  | ||||||
|     const entityChanges = sql.getRows("SELECT * FROM entity_changes WHERE isSynced = 1 AND id > ? LIMIT 1000", [lastEntityChangeId]); |     while (filteredEntityChanges.length === 0) { | ||||||
|  |         const entityChanges = sql.getRows(` | ||||||
|  |             SELECT * | ||||||
|  |             FROM entity_changes | ||||||
|  |             WHERE isSynced = 1 | ||||||
|  |               AND id > ? | ||||||
|  |             ORDER BY id | ||||||
|  |             LIMIT 1000`, [lastEntityChangeId]); | ||||||
|  |  | ||||||
|  |         if (entityChanges.length === 0) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         filteredEntityChanges = entityChanges.filter(ec => ec.memberId !== clientMemberId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const entityChangesRecords = syncService.getEntityChangesRecords(filteredEntityChanges); | ||||||
|  |  | ||||||
|  |     if (entityChangesRecords.length > 0) { | ||||||
|  |         lastEntityChangeId = entityChangesRecords[entityChangesRecords.length - 1].entityChange.id; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const ret = { |     const ret = { | ||||||
|         entityChanges: syncService.getEntityChangesRecords(entityChanges), |         entityChanges: entityChangesRecords, | ||||||
|         maxEntityChangeId: sql.getValue('SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1') |         maxEntityChangeId: sql.getValue('SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1'), | ||||||
|  |         lastEntityChangeId | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     if (ret.entityChanges.length > 0) { |     if (ret.entityChanges.length > 0) { | ||||||
| @@ -174,10 +197,10 @@ function update(req) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const {entities} = body; |     const {entities, memberId} = body; | ||||||
|  |  | ||||||
|     for (const {entityChange, entity} of entities) { |     for (const {entityChange, entity} of entities) { | ||||||
|         syncUpdateService.updateEntity(entityChange, entity); |         syncUpdateService.updateEntity(entityChange, entity, memberId); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| const sourceIdService = require('../services/source_id'); |  | ||||||
| const sql = require('../services/sql'); | const sql = require('../services/sql'); | ||||||
| const attributeService = require('../services/attributes'); | const attributeService = require('../services/attributes'); | ||||||
| const config = require('../services/config'); | const config = require('../services/config'); | ||||||
| @@ -28,7 +27,6 @@ function index(req, res) { | |||||||
|         mainFontSize: parseInt(options.mainFontSize), |         mainFontSize: parseInt(options.mainFontSize), | ||||||
|         treeFontSize: parseInt(options.treeFontSize), |         treeFontSize: parseInt(options.treeFontSize), | ||||||
|         detailFontSize: parseInt(options.detailFontSize), |         detailFontSize: parseInt(options.detailFontSize), | ||||||
|         sourceId: sourceIdService.generateSourceId(), |  | ||||||
|         maxEntityChangeIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes"), |         maxEntityChangeIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes"), | ||||||
|         maxEntityChangeSyncIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1"), |         maxEntityChangeSyncIdAtLoad: sql.getValue("SELECT COALESCE(MAX(id), 0) FROM entity_changes WHERE isSynced = 1"), | ||||||
|         instanceName: config.General ? config.General.instanceName : null, |         instanceName: config.General ? config.General.instanceName : null, | ||||||
|   | |||||||
| @@ -144,7 +144,7 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio | |||||||
|             cls.namespace.bindEmitter(res); |             cls.namespace.bindEmitter(res); | ||||||
|  |  | ||||||
|             const result = cls.init(() => { |             const result = cls.init(() => { | ||||||
|                 cls.set('sourceId', req.headers['trilium-source-id']); |                 cls.set('componentId', req.headers['trilium-component-id']); | ||||||
|                 cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']); |                 cls.set('localNowDateTime', req.headers['trilium-local-now-datetime']); | ||||||
|                 cls.set('hoistedNoteId', req.headers['trilium-hoisted-note-id'] || 'root'); |                 cls.set('hoistedNoteId', req.headers['trilium-hoisted-note-id'] || 'root'); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 = 190; | const APP_DB_VERSION = 191; | ||||||
| const SYNC_VERSION = 25; | const SYNC_VERSION = 25; | ||||||
| const CLIPPER_PROTOCOL_VERSION = "1.0"; | const CLIPPER_PROTOCOL_VERSION = "1.0"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,8 +28,8 @@ function getHoistedNoteId() { | |||||||
|     return namespace.get('hoistedNoteId') || 'root'; |     return namespace.get('hoistedNoteId') || 'root'; | ||||||
| } | } | ||||||
|  |  | ||||||
| function getSourceId() { | function getComponentId() { | ||||||
|     return namespace.get('sourceId'); |     return namespace.get('componentId'); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getLocalNowDateTime() { | function getLocalNowDateTime() { | ||||||
| @@ -80,7 +80,7 @@ module.exports = { | |||||||
|     set, |     set, | ||||||
|     namespace, |     namespace, | ||||||
|     getHoistedNoteId, |     getHoistedNoteId, | ||||||
|     getSourceId, |     getComponentId, | ||||||
|     getLocalNowDateTime, |     getLocalNowDateTime, | ||||||
|     disableEntityEvents, |     disableEntityEvents, | ||||||
|     isEntityEventsDisabled, |     isEntityEventsDisabled, | ||||||
|   | |||||||
| @@ -1,13 +1,19 @@ | |||||||
| const sql = require('./sql'); | const sql = require('./sql'); | ||||||
| const sourceIdService = require('./source_id'); |  | ||||||
| const dateUtils = require('./date_utils'); | const dateUtils = require('./date_utils'); | ||||||
| const log = require('./log'); | const log = require('./log'); | ||||||
| const cls = require('./cls'); | const cls = require('./cls'); | ||||||
| const utils = require('./utils'); | const utils = require('./utils'); | ||||||
|  | const memberId = require('./member_id'); | ||||||
| const becca = require("../becca/becca"); | const becca = require("../becca/becca"); | ||||||
|  |  | ||||||
| let maxEntityChangeId = 0; | let maxEntityChangeId = 0; | ||||||
|  |  | ||||||
|  | function addEntityChangeWithMemberId(origEntityChange, memberId) { | ||||||
|  |     const ec = {...origEntityChange, memberId}; | ||||||
|  |  | ||||||
|  |     return addEntityChange(ec); | ||||||
|  | } | ||||||
|  |  | ||||||
| function addEntityChange(origEntityChange) { | function addEntityChange(origEntityChange) { | ||||||
|     const ec = {...origEntityChange}; |     const ec = {...origEntityChange}; | ||||||
|  |  | ||||||
| @@ -17,7 +23,8 @@ function addEntityChange(origEntityChange) { | |||||||
|         ec.changeId = utils.randomString(12); |         ec.changeId = utils.randomString(12); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ec.sourceId = ec.sourceId || cls.getSourceId() || sourceIdService.getCurrentSourceId(); |     ec.componentId = ec.componentId || cls.getComponentId() || ""; | ||||||
|  |     ec.memberId = ec.memberId || memberId; | ||||||
|     ec.isSynced = ec.isSynced ? 1 : 0; |     ec.isSynced = ec.isSynced ? 1 : 0; | ||||||
|     ec.isErased = ec.isErased ? 1 : 0; |     ec.isErased = ec.isErased ? 1 : 0; | ||||||
|     ec.id = sql.replace("entity_changes", ec); |     ec.id = sql.replace("entity_changes", ec); | ||||||
| @@ -27,7 +34,7 @@ function addEntityChange(origEntityChange) { | |||||||
|     cls.addEntityChange(ec); |     cls.addEntityChange(ec); | ||||||
| } | } | ||||||
|  |  | ||||||
| function addNoteReorderingEntityChange(parentNoteId, sourceId) { | function addNoteReorderingEntityChange(parentNoteId, componentId) { | ||||||
|     addEntityChange({ |     addEntityChange({ | ||||||
|         entityName: "note_reordering", |         entityName: "note_reordering", | ||||||
|         entityId: parentNoteId, |         entityId: parentNoteId, | ||||||
| @@ -35,7 +42,8 @@ function addNoteReorderingEntityChange(parentNoteId, sourceId) { | |||||||
|         isErased: false, |         isErased: false, | ||||||
|         utcDateChanged: dateUtils.utcNowDateTime(), |         utcDateChanged: dateUtils.utcNowDateTime(), | ||||||
|         isSynced: true, |         isSynced: true, | ||||||
|         sourceId |         componentId, | ||||||
|  |         memberId: memberId | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     const eventService = require('./events'); |     const eventService = require('./events'); | ||||||
| @@ -138,6 +146,7 @@ module.exports = { | |||||||
|     addNoteReorderingEntityChange, |     addNoteReorderingEntityChange, | ||||||
|     moveEntityChangeToTop, |     moveEntityChangeToTop, | ||||||
|     addEntityChange, |     addEntityChange, | ||||||
|  |     addEntityChangeWithMemberId, | ||||||
|     fillAllEntityChanges, |     fillAllEntityChanges, | ||||||
|     addEntityChangesForSector, |     addEntityChangesForSector, | ||||||
|     getMaxEntityChangeId: () => maxEntityChangeId |     getMaxEntityChangeId: () => maxEntityChangeId | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								src/services/member_id.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/services/member_id.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | const utils = require('./utils'); | ||||||
|  |  | ||||||
|  | const memberId = utils.randomString(12); | ||||||
|  |  | ||||||
|  | module.exports = memberId; | ||||||
| @@ -30,9 +30,9 @@ function executeBundle(bundle, apiParams = {}) { | |||||||
|         apiParams.startNote = bundle.note; |         apiParams.startNote = bundle.note; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const originalSourceId = cls.get('sourceId'); |     const originalComponentId = cls.get('componentId'); | ||||||
|  |  | ||||||
|     cls.set('sourceId', 'script'); |     cls.set('componentId', 'script'); | ||||||
|  |  | ||||||
|     // last \r\n is necessary if script contains line comment on its last line |     // last \r\n is necessary if script contains line comment on its last line | ||||||
|     const script = "function() {\r\n" + bundle.script + "\r\n}"; |     const script = "function() {\r\n" + bundle.script + "\r\n}"; | ||||||
| @@ -47,7 +47,7 @@ function executeBundle(bundle, apiParams = {}) { | |||||||
|         throw e; |         throw e; | ||||||
|     } |     } | ||||||
|     finally { |     finally { | ||||||
|         cls.set('sourceId', originalSourceId); |         cls.set('componentId', originalComponentId); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,27 +0,0 @@ | |||||||
| const utils = require('./utils'); |  | ||||||
|  |  | ||||||
| const localSourceIds = {}; |  | ||||||
|  |  | ||||||
| function generateSourceId() { |  | ||||||
|     const sourceId = utils.randomString(12); |  | ||||||
|  |  | ||||||
|     localSourceIds[sourceId] = true; |  | ||||||
|  |  | ||||||
|     return sourceId; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function isLocalSourceId(srcId) { |  | ||||||
|     return !!localSourceIds[srcId]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const currentSourceId = generateSourceId(); |  | ||||||
|  |  | ||||||
| function getCurrentSourceId() { |  | ||||||
|     return currentSourceId; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| module.exports = { |  | ||||||
|     generateSourceId, |  | ||||||
|     getCurrentSourceId, |  | ||||||
|     isLocalSourceId |  | ||||||
| }; |  | ||||||
| @@ -4,7 +4,7 @@ const log = require('./log'); | |||||||
| const sql = require('./sql'); | const sql = require('./sql'); | ||||||
| const optionService = require('./options'); | const optionService = require('./options'); | ||||||
| const utils = require('./utils'); | const utils = require('./utils'); | ||||||
| const sourceIdService = require('./source_id'); | const memberId = require('./member_id'); | ||||||
| const dateUtils = require('./date_utils'); | const dateUtils = require('./date_utils'); | ||||||
| const syncUpdateService = require('./sync_update'); | const syncUpdateService = require('./sync_update'); | ||||||
| const contentHashService = require('./content_hash'); | const contentHashService = require('./content_hash'); | ||||||
| @@ -107,11 +107,11 @@ async function doLogin() { | |||||||
|         hash: hash |         hash: hash | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     if (sourceIdService.isLocalSourceId(resp.sourceId)) { |     if (resp.memberId === memberId) { | ||||||
|         throw new Error(`Sync server has source ID ${resp.sourceId} which is also local. This usually happens when the sync client is (mis)configured to sync with itself (URL points back to client) instead of the correct sync server.`); |         throw new Error(`Sync server has member ID ${resp.memberId} which is also local. This usually happens when the sync client is (mis)configured to sync with itself (URL points back to client) instead of the correct sync server.`); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     syncContext.sourceId = resp.sourceId; |     syncContext.memberId = resp.memberId; | ||||||
|  |  | ||||||
|     const lastSyncedPull = getLastSyncedPull(); |     const lastSyncedPull = getLastSyncedPull(); | ||||||
|  |  | ||||||
| @@ -131,7 +131,7 @@ async function pullChanges(syncContext) { | |||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
|         const lastSyncedPull = getLastSyncedPull(); |         const lastSyncedPull = getLastSyncedPull(); | ||||||
|         const changesUri = '/api/sync/changed?lastEntityChangeId=' + lastSyncedPull; |         const changesUri = `/api/sync/changed?memberId=${memberId}&lastEntityChangeId=${lastSyncedPull}`; | ||||||
|  |  | ||||||
|         const startDate = Date.now(); |         const startDate = Date.now(); | ||||||
|  |  | ||||||
| @@ -141,37 +141,39 @@ async function pullChanges(syncContext) { | |||||||
|  |  | ||||||
|         outstandingPullCount = Math.max(0, resp.maxEntityChangeId - lastSyncedPull); |         outstandingPullCount = Math.max(0, resp.maxEntityChangeId - lastSyncedPull); | ||||||
|  |  | ||||||
|         const {entityChanges} = resp; |         const {entityChanges, lastEntityChangeId} = resp; | ||||||
|  |  | ||||||
|         if (entityChanges.length === 0) { |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         sql.transactional(() => { |         sql.transactional(() => { | ||||||
|             for (const {entityChange, entity} of entityChanges) { |             for (const {entityChange, entity} of entityChanges) { | ||||||
|                 const changeAppliedAlready = !entityChange.changeId |                 const changeAppliedAlready = !entityChange.changeId | ||||||
|                     || !!sql.getValue("SELECT id FROM entity_changes WHERE changeId = ?", [entityChange.changeId]); |                     || !!sql.getValue("SELECT id FROM entity_changes WHERE changeId = ?", [entityChange.changeId]); | ||||||
|  |  | ||||||
|                 if (!changeAppliedAlready && !sourceIdService.isLocalSourceId(entityChange.sourceId)) { |                 if (!changeAppliedAlready) { | ||||||
|                     if (!atLeastOnePullApplied) { // send only for first |                     if (!atLeastOnePullApplied) { // send only for first | ||||||
|                         ws.syncPullInProgress(); |                         ws.syncPullInProgress(); | ||||||
|  |  | ||||||
|                         atLeastOnePullApplied = true; |                         atLeastOnePullApplied = true; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     syncUpdateService.updateEntity(entityChange, entity); |                     syncUpdateService.updateEntity(entityChange, entity, syncContext.memberId); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 outstandingPullCount = Math.max(0, resp.maxEntityChangeId - entityChange.id); |                 outstandingPullCount = Math.max(0, resp.maxEntityChangeId - entityChange.id); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             setLastSyncedPull(entityChanges[entityChanges.length - 1].entityChange.id); |             if (lastSyncedPull !== lastEntityChangeId) { | ||||||
|  |                 setLastSyncedPull(lastEntityChangeId); | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  |         if (entityChanges.length === 0) { | ||||||
|  |             break; | ||||||
|  |         } else { | ||||||
|             const sizeInKb = Math.round(JSON.stringify(resp).length / 1024); |             const sizeInKb = Math.round(JSON.stringify(resp).length / 1024); | ||||||
|  |  | ||||||
|             log.info(`Pulled ${entityChanges.length} changes in ${sizeInKb} KB, starting at entityChangeId=${lastSyncedPull} in ${pulledDate - startDate}ms and applied them in ${Date.now() - pulledDate}ms, ${outstandingPullCount} outstanding pulls`); |             log.info(`Pulled ${entityChanges.length} changes in ${sizeInKb} KB, starting at entityChangeId=${lastSyncedPull} in ${pulledDate - startDate}ms and applied them in ${Date.now() - pulledDate}ms, ${outstandingPullCount} outstanding pulls`); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     log.info("Finished pull"); |     log.info("Finished pull"); | ||||||
| } | } | ||||||
| @@ -189,10 +191,9 @@ async function pushChanges(syncContext) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         const filteredEntityChanges = entityChanges.filter(entityChange => { |         const filteredEntityChanges = entityChanges.filter(entityChange => { | ||||||
|             if (entityChange.sourceId === syncContext.sourceId) { |             if (entityChange.memberId === syncContext.memberId) { | ||||||
|                 // this may set lastSyncedPush beyond what's actually sent (because of size limit) |                 // this may set lastSyncedPush beyond what's actually sent (because of size limit) | ||||||
|                 // so this is applied to the database only if there's no actual update |                 // so this is applied to the database only if there's no actual update | ||||||
|                 // TODO: it would be better to simplify this somehow |  | ||||||
|                 lastSyncedPush = entityChange.id; |                 lastSyncedPush = entityChange.id; | ||||||
|  |  | ||||||
|                 return false; |                 return false; | ||||||
| @@ -214,8 +215,8 @@ async function pushChanges(syncContext) { | |||||||
|         const startDate = new Date(); |         const startDate = new Date(); | ||||||
|  |  | ||||||
|         await syncRequest(syncContext, 'PUT', '/api/sync/update', { |         await syncRequest(syncContext, 'PUT', '/api/sync/update', { | ||||||
|             sourceId: sourceIdService.getCurrentSourceId(), |             entities: entityChangesRecords, | ||||||
|             entities: entityChangesRecords |             memberId | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         ws.syncPushInProgress(); |         ws.syncPushInProgress(); | ||||||
|   | |||||||
| @@ -4,12 +4,12 @@ const entityChangesService = require('./entity_changes'); | |||||||
| const eventService = require('./events'); | const eventService = require('./events'); | ||||||
| const entityConstructor = require("../becca/entity_constructor"); | const entityConstructor = require("../becca/entity_constructor"); | ||||||
|  |  | ||||||
| function updateEntity(entityChange, entityRow) { | function updateEntity(entityChange, entityRow, memberId) { | ||||||
|     // can be undefined for options with isSynced=false |     // can be undefined for options with isSynced=false | ||||||
|     if (!entityRow) { |     if (!entityRow) { | ||||||
|         if (entityChange.isSynced) { |         if (entityChange.isSynced) { | ||||||
|             if (entityChange.isErased) { |             if (entityChange.isErased) { | ||||||
|                 eraseEntity(entityChange); |                 eraseEntity(entityChange, memberId); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 log.info(`Encountered synced non-erased entity change without entity: ${JSON.stringify(entityChange)}`); |                 log.info(`Encountered synced non-erased entity change without entity: ${JSON.stringify(entityChange)}`); | ||||||
| @@ -23,8 +23,8 @@ function updateEntity(entityChange, entityRow) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const updated = entityChange.entityName === 'note_reordering' |     const updated = entityChange.entityName === 'note_reordering' | ||||||
|         ? updateNoteReordering(entityChange, entityRow) |         ? updateNoteReordering(entityChange, entityRow, memberId) | ||||||
|         : updateNormalEntity(entityChange, entityRow); |         : updateNormalEntity(entityChange, entityRow, memberId); | ||||||
|  |  | ||||||
|     if (updated) { |     if (updated) { | ||||||
|         if (entityRow.isDeleted) { |         if (entityRow.isDeleted) { | ||||||
| @@ -42,7 +42,7 @@ function updateEntity(entityChange, entityRow) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function updateNormalEntity(remoteEntityChange, entity) { | function updateNormalEntity(remoteEntityChange, entity, memberId) { | ||||||
|     const localEntityChange = sql.getRow(` |     const localEntityChange = sql.getRow(` | ||||||
|         SELECT utcDateChanged, hash, isErased |         SELECT utcDateChanged, hash, isErased | ||||||
|         FROM entity_changes  |         FROM entity_changes  | ||||||
| @@ -54,7 +54,7 @@ function updateNormalEntity(remoteEntityChange, entity) { | |||||||
|  |  | ||||||
|             sql.execute(`DELETE FROM ${remoteEntityChange.entityName} WHERE ${primaryKey} = ?`, remoteEntityChange.entityId); |             sql.execute(`DELETE FROM ${remoteEntityChange.entityName} WHERE ${primaryKey} = ?`, remoteEntityChange.entityId); | ||||||
|  |  | ||||||
|             entityChangesService.addEntityChange(remoteEntityChange); |             entityChangesService.addEntityChangeWithMemberId(remoteEntityChange, memberId); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
| @@ -71,7 +71,7 @@ function updateNormalEntity(remoteEntityChange, entity) { | |||||||
|         sql.transactional(() => { |         sql.transactional(() => { | ||||||
|             sql.replace(remoteEntityChange.entityName, entity); |             sql.replace(remoteEntityChange.entityName, entity); | ||||||
|  |  | ||||||
|             entityChangesService.addEntityChange(remoteEntityChange); |             entityChangesService.addEntityChangeWithMemberId(remoteEntityChange, memberId); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
| @@ -80,13 +80,13 @@ function updateNormalEntity(remoteEntityChange, entity) { | |||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| function updateNoteReordering(entityChange, entity) { | function updateNoteReordering(entityChange, entity, memberId) { | ||||||
|     sql.transactional(() => { |     sql.transactional(() => { | ||||||
|         for (const key in entity) { |         for (const key in entity) { | ||||||
|             sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity[key], key]); |             sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [entity[key], key]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         entityChangesService.addEntityChange(entityChange); |         entityChangesService.addEntityChangeWithMemberId(entityChange, memberId); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     return true; |     return true; | ||||||
| @@ -105,7 +105,7 @@ function handleContent(content) { | |||||||
|     return content; |     return content; | ||||||
| } | } | ||||||
|  |  | ||||||
| function eraseEntity(entityChange) { | function eraseEntity(entityChange, memberId) { | ||||||
|     const {entityName, entityId} = entityChange; |     const {entityName, entityId} = entityChange; | ||||||
|  |  | ||||||
|     if (!["notes", "note_contents", "branches", "attributes", "note_revisions", "note_revision_contents"].includes(entityName)) { |     if (!["notes", "note_contents", "branches", "attributes", "note_revisions", "note_revision_contents"].includes(entityName)) { | ||||||
| @@ -119,7 +119,7 @@ function eraseEntity(entityChange) { | |||||||
|  |  | ||||||
|     eventService.emit(eventService.ENTITY_DELETE_SYNCED, { entityName, entityId }); |     eventService.emit(eventService.ENTITY_DELETE_SYNCED, { entityName, entityId }); | ||||||
|  |  | ||||||
|     entityChangesService.addEntityChange(entityChange, true); |     entityChangesService.addEntityChangeWithMemberId(entityChange, memberId); | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|   | |||||||
| @@ -48,7 +48,6 @@ | |||||||
|     window.device = "desktop"; |     window.device = "desktop"; | ||||||
|     window.glob = { |     window.glob = { | ||||||
|         activeDialog: null, |         activeDialog: null, | ||||||
|         sourceId: '<%= sourceId %>', |  | ||||||
|         maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>, |         maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>, | ||||||
|         maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>, |         maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>, | ||||||
|         instanceName: '<%= instanceName %>', |         instanceName: '<%= instanceName %>', | ||||||
|   | |||||||
| @@ -111,7 +111,6 @@ | |||||||
|     window.device = "mobile"; |     window.device = "mobile"; | ||||||
|     window.glob = { |     window.glob = { | ||||||
|         activeDialog: null, |         activeDialog: null, | ||||||
|         sourceId: '<%= sourceId %>', |  | ||||||
|         maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>, |         maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>, | ||||||
|         maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>, |         maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>, | ||||||
|         instanceName: '<%= instanceName %>', |         instanceName: '<%= instanceName %>', | ||||||
|   | |||||||
| @@ -119,8 +119,8 @@ | |||||||
|                 <p><strong>Note:</strong> If you leave proxy setting blank, system proxy will be used (applies to desktop/electron build only)</p> |                 <p><strong>Note:</strong> If you leave proxy setting blank, system proxy will be used (applies to desktop/electron build only)</p> | ||||||
|             </div> |             </div> | ||||||
|             <div class="form-group"> |             <div class="form-group"> | ||||||
|                 <label for="password1">Password</label> |                 <label for="password">Password</label> | ||||||
|                 <input type="password" id="password1" class="form-control" data-bind="value: password1" placeholder="Password"> |                 <input type="password" id="password" class="form-control" data-bind="value: password" placeholder="Password"> | ||||||
|             </div> |             </div> | ||||||
|  |  | ||||||
|             <button type="button" data-bind="click: back" class="btn btn-secondary">Back</button> |             <button type="button" data-bind="click: back" class="btn btn-secondary">Back</button> | ||||||
| @@ -146,7 +146,7 @@ | |||||||
|     global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */ |     global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */ | ||||||
|  |  | ||||||
|     window.glob = { |     window.glob = { | ||||||
|         sourceId: '' |         componentId: '' | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     window.syncInProgress = <%= syncInProgress ? 'true' : 'false' %>; |     window.syncInProgress = <%= syncInProgress ? 'true' : 'false' %>; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user