allow only valid attr name characters for relation map relations, closes #1649

This commit is contained in:
zadam 2021-02-17 23:22:14 +01:00
parent faeb55bc90
commit ec2e973165
4 changed files with 32 additions and 12 deletions

View File

@ -1,3 +1,5 @@
import utils from "./utils.js";
function lex(str) { function lex(str) {
str = str.trim(); str = str.trim();
@ -105,14 +107,12 @@ function lex(str) {
return tokens; return tokens;
} }
const attrNameMatcher = new RegExp("^[\\p{L}\\p{N}_:]+$", "u");
function checkAttributeName(attrName) { function checkAttributeName(attrName) {
if (attrName.length === 0) { if (attrName.length === 0) {
throw new Error("Attribute name is empty, please fill the name."); throw new Error("Attribute name is empty, please fill the name.");
} }
if (!attrNameMatcher.test(attrName)) { if (!utils.isValidAttributeName(attrName)) {
throw new Error(`Attribute name "${attrName}" contains disallowed characters, only alphanumeric characters, colon and underscore are allowed.`); throw new Error(`Attribute name "${attrName}" contains disallowed characters, only alphanumeric characters, colon and underscore are allowed.`);
} }
} }

View File

@ -334,6 +334,16 @@ function initHelpButtons($el) {
}); });
} }
function filterAttributeName(name) {
return name.replace(/[^\p{L}\p{N}_:]/ug, "");
}
const ATTR_NAME_MATCHER = new RegExp("^[\\p{L}\\p{N}_:]+$", "u");
function isValidAttributeName(name) {
return ATTR_NAME_MATCHER.test(name);
}
export default { export default {
reloadApp, reloadApp,
parseDate, parseDate,
@ -374,5 +384,7 @@ export default {
dynamicRequire, dynamicRequire,
timeLimit, timeLimit,
initHelpDropdown, initHelpDropdown,
initHelpButtons initHelpButtons,
filterAttributeName,
isValidAttributeName
}; };

View File

@ -172,8 +172,6 @@ const ATTR_TITLES = {
"relation-definition": "Relation definition detail" "relation-definition": "Relation definition detail"
}; };
const ATTR_NAME_MATCHER = new RegExp("^[\\p{L}\\p{N}_:]+$", "u");
const ATTR_HELP = { const ATTR_HELP = {
"label": { "label": {
"disableVersioning": "disables auto-versioning. Useful for e.g. large, but unimportant notes - e.g. large JS libraries used for scripting", "disableVersioning": "disables auto-versioning. Useful for e.g. large, but unimportant notes - e.g. large JS libraries used for scripting",
@ -573,9 +571,9 @@ export default class AttributeDetailWidget extends TabAwareWidget {
updateAttributeInEditor() { updateAttributeInEditor() {
let attrName = this.$inputName.val(); let attrName = this.$inputName.val();
if (!ATTR_NAME_MATCHER.test(attrName)) { if (!utils.isValidAttributeName(attrName)) {
// invalid characters are simply ignored (from user perspective they are not even entered) // invalid characters are simply ignored (from user perspective they are not even entered)
attrName = attrName.replace(/[^\p{L}\p{N}_:]/ug, ""); attrName = utils.filterAttributeName(attrName);
this.$inputName.val(attrName); this.$inputName.val(attrName);
} }

View File

@ -471,14 +471,22 @@ export default class RelationMapTypeWidget extends TypeWidget {
} }
const promptDialog = await import("../../dialogs/prompt.js"); const promptDialog = await import("../../dialogs/prompt.js");
const name = await promptDialog.ask({ let name = await promptDialog.ask({
message: "Specify new relation name:", message: "Specify new relation name (allowed characters: alphanumeric, colon and underscore):",
shown: ({ $answer }) => shown: ({ $answer }) => {
$answer.on('keyup', () => {
// invalid characters are simply ignored (from user perspective they are not even entered)
const attrName = utils.filterAttributeName($answer.val());
$answer.val(attrName);
});
attributeAutocompleteService.initAttributeNameAutocomplete({ attributeAutocompleteService.initAttributeNameAutocomplete({
$el: $answer, $el: $answer,
attributeType: "relation", attributeType: "relation",
open: true open: true
}) });
}
}); });
if (!name || !name.trim()) { if (!name || !name.trim()) {
@ -487,6 +495,8 @@ export default class RelationMapTypeWidget extends TypeWidget {
return; return;
} }
name = utils.filterAttributeName(name);
const targetNoteId = this.idToNoteId(connection.target.id); const targetNoteId = this.idToNoteId(connection.target.id);
const sourceNoteId = this.idToNoteId(connection.source.id); const sourceNoteId = this.idToNoteId(connection.source.id);