diff --git a/config-sample.ini b/config-sample.ini index a18d940a4..bc88f6e1a 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -7,6 +7,6 @@ instanceName= port=8080 # true for TLS/SSL/HTTPS (secure), false for HTTP (unsecure). https=false -# path to certificate (run "bash generate-cert.sh" to generate self-signed certificate). Relevant only if https=true +# path to certificate (run "bash bin/generate-cert.sh" to generate self-signed certificate). Relevant only if https=true certPath= keyPath= diff --git a/src/public/javascripts/services/tree_utils.js b/src/public/javascripts/services/tree_utils.js index 548c9fcc5..e708ff845 100644 --- a/src/public/javascripts/services/tree_utils.js +++ b/src/public/javascripts/services/tree_utils.js @@ -34,7 +34,12 @@ function getNotePath(node) { async function getNoteTitle(noteId, parentNoteId = null) { utils.assertArguments(noteId); - let {title} = await treeCache.getNote(noteId); + const note = await treeCache.getNote(noteId); + if (!note) { + return "[not found]"; + } + + let {title} = note; if (parentNoteId !== null) { const branch = await treeCache.getBranchByChildParent(noteId, parentNoteId); diff --git a/src/routes/api/import.js b/src/routes/api/import.js index 2e47b1956..5911ab45e 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -79,6 +79,9 @@ async function importTar(file, parentNoteId) { const noteIdMap = {}; await importNotes(files, parentNoteId, noteIdMap); + + // import might contain relations targeting notes which are not in the import + await attributeService.removeInvalidRelations(); } function getFileName(name) { diff --git a/src/services/attributes.js b/src/services/attributes.js index 176678f11..949d1884f 100644 --- a/src/services/attributes.js +++ b/src/services/attributes.js @@ -77,11 +77,31 @@ async function getAttributeNames(type, nameLike) { return names; } +async function removeInvalidRelations() { + const relations = await repository.getEntities(` + SELECT attributes.* + FROM attributes + LEFT JOIN notes AS sourceNote ON attributes.noteId = sourceNote.noteId + LEFT JOIN notes AS targetNote ON attributes.value = targetNote.noteId + WHERE + attributes.isDeleted = 0 + AND attributes.type = 'relation' + AND (sourceNote.noteId IS NULL OR sourceNote.isDeleted + OR targetNote.noteId IS NULL OR targetNote.isDeleted)`); + + for (const relation of relations) { + relation.isDeleted = true; + + await relation.save(); + } +} + module.exports = { getNotesWithLabel, getNoteWithLabel, createLabel, createAttribute, getAttributeNames, + removeInvalidRelations, BUILTIN_ATTRIBUTES }; \ No newline at end of file diff --git a/src/services/notes.js b/src/services/notes.js index abb1baf62..de27966f9 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -250,6 +250,11 @@ async function deleteNote(branch) { for (const childBranch of await note.getChildBranches()) { await deleteNote(childBranch); } + + for (const attribute of await note.getOwnedAttributes()) { + attribute.isDeleted = true; + await attribute.save(); + } } }