diff --git a/src/becca/entities/attribute.js b/src/becca/entities/attribute.js index bb209d3ec..a5c9e664b 100644 --- a/src/becca/entities/attribute.js +++ b/src/becca/entities/attribute.js @@ -5,6 +5,7 @@ const AbstractEntity = require("./abstract_entity"); const sql = require("../../services/sql"); const dateUtils = require("../../services/date_utils"); const promotedAttributeDefinitionParser = require("../../services/promoted_attribute_definition_parser"); +const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name"); /** * Attribute is an abstract concept which has two real uses - label (key - value pair) @@ -178,6 +179,8 @@ class Attribute extends AbstractEntity { beforeSaving() { this.validate(); + this.name = sanitizeAttributeName(this.name); + if (!this.value) { // null value isn't allowed this.value = ""; diff --git a/src/routes/api/sender.js b/src/routes/api/sender.js index fc0368758..b93104281 100644 --- a/src/routes/api/sender.js +++ b/src/routes/api/sender.js @@ -5,6 +5,7 @@ const imageService = require('../../services/image'); const dateNoteService = require('../../services/date_notes'); const noteService = require('../../services/notes'); const attributeService = require('../../services/attributes'); +const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name.js"); function uploadImage(req) { const file = req.file; @@ -25,7 +26,7 @@ function uploadImage(req) { const labels = JSON.parse(labelsStr); for (const {name, value} of labels) { - note.setLabel(attributeService.sanitizeAttributeName(name), value); + note.setLabel(sanitizeAttributeName(name), value); } } @@ -50,7 +51,7 @@ function saveNote(req) { if (req.body.labels) { for (const {name, value} of req.body.labels) { - note.setLabel(attributeService.sanitizeAttributeName(name), value); + note.setLabel(sanitizeAttributeName(name), value); } } diff --git a/src/services/attributes.js b/src/services/attributes.js index 406bfbcca..289bd6355 100644 --- a/src/services/attributes.js +++ b/src/services/attributes.js @@ -128,20 +128,6 @@ function isAttributeDangerous(type, name) { ); } -function sanitizeAttributeName(origName) { - let fixedName; - - if (origName === '') { - fixedName = "unnamed"; - } - else { - // any not allowed character should be replaced with underscore - fixedName = origName.replace(/[^\p{L}\p{N}_:]/ug, "_"); - } - - return fixedName; -} - module.exports = { getNotesWithLabel, getNotesWithLabelFast, @@ -151,6 +137,5 @@ module.exports = { createAttribute, getAttributeNames, isAttributeType, - isAttributeDangerous, - sanitizeAttributeName + isAttributeDangerous }; diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 8a2a75f36..dc529b926 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -9,10 +9,10 @@ const cls = require('./cls'); const entityChangesService = require('./entity_changes'); const optionsService = require('./options'); const Branch = require('../becca/entities/branch'); -const attributeService = require('./attributes'); const noteRevisionService = require('./note_revisions'); const becca = require("../becca/becca"); const utils = require("../services/utils"); +const {sanitizeAttributeName} = require("./sanitize_attribute_name.js"); const noteTypes = require("../services/note_types").getNoteTypeNames(); class ConsistencyChecks { @@ -607,7 +607,7 @@ class ConsistencyChecks { const attrNames = sql.getColumn(`SELECT DISTINCT name FROM attributes`); for (const origName of attrNames) { - const fixedName = attributeService.sanitizeAttributeName(origName); + const fixedName = sanitizeAttributeName(origName); if (fixedName !== origName) { if (this.autoFix) { diff --git a/src/services/import/enex.js b/src/services/import/enex.js index 059702314..dde601a72 100644 --- a/src/services/import/enex.js +++ b/src/services/import/enex.js @@ -9,6 +9,7 @@ const imageService = require("../image"); const protectedSessionService = require('../protected_session'); const htmlSanitizer = require("../html_sanitizer"); const attributeService = require("../attributes"); +const {sanitizeAttributeName} = require("../sanitize_attribute_name.js"); // date format is e.g. 20181121T193703Z function parseDate(text) { @@ -117,7 +118,7 @@ function importEnex(taskContext, file, parentNote) { labelName = 'sourceUrl'; } - labelName = attributeService.sanitizeAttributeName(labelName); + labelName = sanitizeAttributeName(labelName); note.attributes.push({ type: 'label', @@ -166,7 +167,7 @@ function importEnex(taskContext, file, parentNote) { } else if (currentTag === 'tag') { note.attributes.push({ type: 'label', - name: attributeService.sanitizeAttributeName(text), + name: sanitizeAttributeName(text), value: '' }) } diff --git a/src/services/sanitize_attribute_name.js b/src/services/sanitize_attribute_name.js new file mode 100644 index 000000000..3a7c9ff67 --- /dev/null +++ b/src/services/sanitize_attribute_name.js @@ -0,0 +1,18 @@ +function sanitizeAttributeName(origName) { + let fixedName; + + if (origName === '') { + fixedName = "unnamed"; + } + else { + // any not allowed character should be replaced with underscore + fixedName = origName.replace(/[^\p{L}\p{N}_:]/ug, "_"); + } + + return fixedName; +} + + +module.exports = { + sanitizeAttributeName +}; diff --git a/src/services/special_notes.js b/src/services/special_notes.js index dbf8937aa..523c7b7fc 100644 --- a/src/services/special_notes.js +++ b/src/services/special_notes.js @@ -36,14 +36,13 @@ function getInboxNote(date) { function createSqlConsole() { const {note} = noteService.createNewNote({ - parentNoteId: getMonthlyParentNoteId('_sqlConsole'), - title: 'SQL Console', + parentNoteId: getMonthlyParentNoteId('_sqlConsole', 'sqlConsole'), + title: 'SQL Console - ' + dateUtils.localNowDate(), content: "SELECT title, isDeleted, isProtected FROM notes WHERE noteId = ''\n\n\n\n", type: 'code', mime: 'text/x-sqlite;schema=trilium' }); - note.setLabel('_sqlConsole', dateUtils.localNowDate()); note.setLabel('iconClass', 'bx bx-data'); note.setLabel('keepCurrentHoisting'); @@ -71,7 +70,7 @@ function saveSqlConsole(sqlConsoleNoteId) { function createSearchNote(searchString, ancestorNoteId) { const {note} = noteService.createNewNote({ - parentNoteId: getMonthlyParentNoteId('_search'), + parentNoteId: getMonthlyParentNoteId('_search', 'search'), title: `Search: ${searchString}`, content: "", type: 'search', @@ -118,9 +117,9 @@ function saveSearchNote(searchNoteId) { return result; } -function getMonthlyParentNoteId(rootNoteId) { +function getMonthlyParentNoteId(rootNoteId, prefix) { const month = dateUtils.localNowDate().substring(0, 7); - const labelName = `${rootNoteId}MonthNote`; + const labelName = `${prefix}MonthNote`; let monthNote = searchService.findFirstNoteWithQuery(`#${labelName}="${month}"`, new SearchContext({ancestorNoteId: rootNoteId}));