2018-03-23 23:08:29 -04:00
|
|
|
"use strict";
|
|
|
|
|
2019-03-20 22:28:54 +01:00
|
|
|
const repository = require('../../services/repository');
|
2020-05-16 23:12:29 +02:00
|
|
|
const noteCacheService = require('../../services/note_cache/note_cache.js');
|
2019-03-20 22:28:54 +01:00
|
|
|
const log = require('../../services/log');
|
|
|
|
const scriptService = require('../../services/script');
|
2020-07-21 00:01:07 +02:00
|
|
|
const searchService = require('../../services/search/services/search.js');
|
2018-03-23 23:08:29 -04:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function searchNotes(req) {
|
2020-06-20 13:18:03 +02:00
|
|
|
const {count, results} = searchService.searchTrimmedNotes(req.params.searchString);
|
2018-03-23 23:08:29 -04:00
|
|
|
|
2019-04-02 22:52:42 +02:00
|
|
|
try {
|
|
|
|
return {
|
|
|
|
success: true,
|
2020-06-18 22:28:18 +02:00
|
|
|
count,
|
|
|
|
results
|
2019-04-02 22:52:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch {
|
|
|
|
return {
|
|
|
|
success: false
|
|
|
|
}
|
|
|
|
}
|
2018-03-30 17:29:13 -04:00
|
|
|
}
|
2018-03-23 23:08:29 -04:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function searchFromNote(req) {
|
|
|
|
const note = repository.getNote(req.params.noteId);
|
2019-03-20 22:28:54 +01:00
|
|
|
|
|
|
|
if (!note) {
|
|
|
|
return [404, `Note ${req.params.noteId} has not been found.`];
|
|
|
|
}
|
|
|
|
|
2020-01-13 19:35:06 +01:00
|
|
|
if (note.isDeleted) {
|
|
|
|
return [400, `Note ${req.params.noteId} is deleted.`];
|
|
|
|
}
|
|
|
|
|
2019-03-20 22:28:54 +01:00
|
|
|
if (note.type !== 'search') {
|
2020-01-13 19:35:06 +01:00
|
|
|
return [400, `Note ${req.params.noteId} is not search note.`]
|
2019-03-20 22:28:54 +01:00
|
|
|
}
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
const json = note.getJsonContent();
|
2019-03-20 22:28:54 +01:00
|
|
|
|
|
|
|
if (!json || !json.searchString) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
let noteIds;
|
|
|
|
|
2020-01-13 19:35:06 +01:00
|
|
|
try {
|
|
|
|
if (json.searchString.startsWith('=')) {
|
|
|
|
const relationName = json.searchString.substr(1).trim();
|
2019-03-20 22:28:54 +01:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
noteIds = searchFromRelation(note, relationName);
|
2020-01-13 19:35:06 +01:00
|
|
|
} else {
|
2020-06-20 12:31:38 +02:00
|
|
|
noteIds = searchService.searchForNoteIds(json.searchString);
|
2020-01-13 19:35:06 +01:00
|
|
|
}
|
2019-03-20 22:28:54 +01:00
|
|
|
}
|
2020-01-13 19:35:06 +01:00
|
|
|
catch (e) {
|
|
|
|
log.error(`Search failed for note ${note.noteId}: ` + e.message + ": " + e.stack);
|
|
|
|
|
|
|
|
throw new Error("Search failed, see logs for details.");
|
2019-03-20 22:28:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// we won't return search note's own noteId
|
|
|
|
noteIds = noteIds.filter(noteId => noteId !== note.noteId);
|
|
|
|
|
2020-01-13 19:35:06 +01:00
|
|
|
if (noteIds.length > 200) {
|
|
|
|
noteIds = noteIds.slice(0, 200);
|
|
|
|
}
|
|
|
|
|
2019-03-20 22:28:54 +01:00
|
|
|
return noteIds.map(noteCacheService.getNotePath).filter(res => !!res);
|
|
|
|
}
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function searchFromRelation(note, relationName) {
|
|
|
|
const scriptNote = note.getRelationTarget(relationName);
|
2019-03-20 22:28:54 +01:00
|
|
|
|
|
|
|
if (!scriptNote) {
|
|
|
|
log.info(`Search note's relation ${relationName} has not been found.`);
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!scriptNote.isJavaScript() || scriptNote.getScriptEnv() !== 'backend') {
|
|
|
|
log.info(`Note ${scriptNote.noteId} is not executable.`);
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!note.isContentAvailable) {
|
|
|
|
log.info(`Note ${scriptNote.noteId} is not available outside of protected session.`);
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
const result = scriptService.executeNote(scriptNote, { originEntity: note });
|
2019-03-20 22:28:54 +01:00
|
|
|
|
|
|
|
if (!Array.isArray(result)) {
|
|
|
|
log.info(`Result from ${scriptNote.noteId} is not an array.`);
|
|
|
|
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.length === 0) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
// we expect either array of noteIds (strings) or notes, in that case we extract noteIds ourselves
|
|
|
|
return typeof result[0] === 'string' ? result : result.map(item => item.noteId);
|
|
|
|
}
|
|
|
|
|
2020-06-25 23:56:06 +02:00
|
|
|
function getRelatedNotes(req) {
|
|
|
|
const attr = req.body;
|
|
|
|
|
|
|
|
const matchingNameAndValue = searchService.searchNotes(formatAttrForSearch(attr, true));
|
|
|
|
const matchingName = searchService.searchNotes(formatAttrForSearch(attr, false));
|
|
|
|
|
|
|
|
const results = [];
|
|
|
|
|
|
|
|
for (const record of matchingNameAndValue.concat(matchingName)) {
|
|
|
|
if (results.length >= 20) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (results.find(res => res.noteId === record.noteId)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
results.push(record);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
count: matchingName.length,
|
|
|
|
results
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatAttrForSearch(attr, searchWithValue) {
|
|
|
|
let searchStr = '';
|
|
|
|
|
|
|
|
if (attr.type === 'label') {
|
|
|
|
searchStr += '#';
|
|
|
|
}
|
|
|
|
else if (attr.type === 'relation') {
|
|
|
|
searchStr += '~';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
throw new Error(`Unrecognized attribute type ${JSON.stringify(attr)}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
searchStr += attr.name;
|
|
|
|
|
|
|
|
if (searchWithValue && attr.value) {
|
|
|
|
searchStr += '=';
|
|
|
|
searchStr += formatValue(attr.value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return searchStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatValue(val) {
|
|
|
|
if (!/[^\w_-]/.test(val)) {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
else if (!val.includes('"')) {
|
|
|
|
return '"' + val + '"';
|
|
|
|
}
|
|
|
|
else if (!val.includes("'")) {
|
|
|
|
return "'" + val + "'";
|
|
|
|
}
|
|
|
|
else if (!val.includes("`")) {
|
|
|
|
return "`" + val + "`";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return '"' + val.replace(/"/g, '\\"') + '"';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-30 17:29:13 -04:00
|
|
|
module.exports = {
|
|
|
|
searchNotes,
|
2020-06-25 23:56:06 +02:00
|
|
|
searchFromNote,
|
|
|
|
getRelatedNotes
|
2020-05-16 23:12:29 +02:00
|
|
|
};
|