Notes/src/routes/api/options.ts

177 lines
4.7 KiB
TypeScript
Raw Normal View History

2017-10-21 21:10:33 -04:00
"use strict";
import optionService from "../../services/options.js";
import log from "../../services/log.js";
import searchService from "../../services/search/services/search.js";
import ValidationError from "../../errors/validation_error.js";
import type { Request } from "express";
import { changeLanguage, getLocales } from "../../services/i18n.js";
import { listSyntaxHighlightingThemes } from "../../services/code_block_theme.js";
import type { OptionNames } from "../../services/options_interface.js";
2023-06-30 11:18:34 +02:00
// options allowed to be updated directly in the Options dialog
2019-11-19 20:53:04 +01:00
const ALLOWED_OPTIONS = new Set([
2025-01-09 18:07:02 +02:00
"eraseEntitiesAfterTimeInSeconds",
"eraseEntitiesAfterTimeScale",
2025-01-09 18:07:02 +02:00
"protectedSessionTimeout",
"protectedSessionTimeoutTimeScale",
2025-01-09 18:07:02 +02:00
"revisionSnapshotTimeInterval",
"revisionSnapshotTimeIntervalTimeScale",
2025-01-09 18:07:02 +02:00
"revisionSnapshotNumberLimit",
"zoomFactor",
"theme",
"codeBlockTheme",
"codeBlockWordWrap",
2025-01-09 18:07:02 +02:00
"syncServerHost",
"syncServerTimeout",
"syncProxy",
"hoistedNoteId",
"mainFontSize",
"mainFontFamily",
"treeFontSize",
"treeFontFamily",
"detailFontSize",
"detailFontFamily",
"monospaceFontSize",
"monospaceFontFamily",
"openNoteContexts",
"vimKeymapEnabled",
"codeLineWrapEnabled",
"codeNotesMimeTypes",
"spellCheckEnabled",
"spellCheckLanguageCode",
"imageMaxWidthHeight",
"imageJpegQuality",
"leftPaneWidth",
"rightPaneWidth",
"leftPaneVisible",
"rightPaneVisible",
"nativeTitleBarVisible",
"headingStyle",
"autoCollapseNoteTree",
"autoReadonlySizeText",
"autoReadonlySizeCode",
"overrideThemeFonts",
"dailyBackupEnabled",
"weeklyBackupEnabled",
"monthlyBackupEnabled",
"maxContentWidth",
"compressImages",
"downloadImagesAutomatically",
"minTocHeadings",
"highlightsList",
"checkForUpdates",
"disableTray",
"eraseUnusedAttachmentsAfterSeconds",
"eraseUnusedAttachmentsAfterTimeScale",
2025-01-09 18:07:02 +02:00
"disableTray",
"customSearchEngineName",
"customSearchEngineUrl",
"promotedAttributesOpenInRibbon",
"editedNotesOpenInRibbon",
"locale",
"firstDayOfWeek",
"languages",
2025-01-09 18:07:02 +02:00
"textNoteEditorType",
"textNoteEditorMultilineToolbar",
"layoutOrientation",
"backgroundEffects",
"allowedHtmlTags",
"redirectBareDomain",
"showLoginInShareTheme"
2019-11-19 20:53:04 +01:00
]);
2020-06-20 12:31:38 +02:00
function getOptions() {
2023-06-29 22:10:13 +02:00
const optionMap = optionService.getOptionMap();
2024-04-06 21:57:09 +03:00
const resultMap: Record<string, string> = {};
2019-11-19 20:53:04 +01:00
for (const optionName in optionMap) {
if (isAllowed(optionName)) {
2025-01-03 17:54:05 +02:00
resultMap[optionName] = optionMap[optionName as OptionNames];
2019-11-19 20:53:04 +01:00
}
}
2025-01-09 18:07:02 +02:00
resultMap["isPasswordSet"] = optionMap["passwordVerificationHash"] ? "true" : "false";
2019-11-19 20:53:04 +01:00
return resultMap;
}
2024-04-06 21:57:09 +03:00
function updateOption(req: Request) {
2025-01-09 18:07:02 +02:00
const { name, value } = req.params;
2020-06-20 12:31:38 +02:00
if (!update(name, value)) {
throw new ValidationError("not allowed option to change");
}
}
2024-04-06 21:57:09 +03:00
function updateOptions(req: Request) {
for (const optionName in req.body) {
2020-06-20 12:31:38 +02:00
if (!update(optionName, req.body[optionName])) {
// this should be improved
// it should return 400 instead of current 500, but at least it now rollbacks transaction
2023-05-04 22:16:18 +02:00
throw new Error(`Option '${optionName}' is not allowed to be changed`);
}
}
}
2024-04-06 21:57:09 +03:00
function update(name: string, value: string) {
2019-11-19 20:53:04 +01:00
if (!isAllowed(name)) {
return false;
}
2025-01-09 18:07:02 +02:00
if (name !== "openNoteContexts") {
2023-04-11 22:00:04 +02:00
log.info(`Updating option '${name}' to '${value}'`);
}
2025-01-03 17:54:05 +02:00
optionService.setOption(name as OptionNames, value);
if (name === "locale") {
// This runs asynchronously, so it's not perfect, but it does the trick for now.
changeLanguage(value);
}
return true;
}
2020-06-20 12:31:38 +02:00
function getUserThemes() {
2025-01-09 18:07:02 +02:00
const notes = searchService.searchNotes("#appTheme", { ignoreHoistedNote: true });
2019-02-03 00:12:57 +01:00
const ret = [];
for (const note of notes) {
2025-01-09 18:07:02 +02:00
let value = note.getOwnedLabelValue("appTheme");
2019-02-03 00:12:57 +01:00
2019-02-03 15:35:37 +01:00
if (!value) {
2025-01-09 18:07:02 +02:00
value = note.title.toLowerCase().replace(/[^a-z0-9]/gi, "-");
2019-02-03 00:12:57 +01:00
}
ret.push({
val: value,
title: note.title,
noteId: note.noteId
2019-01-27 21:18:11 +01:00
});
2019-02-03 00:12:57 +01:00
}
return ret;
2019-01-27 21:18:11 +01:00
}
function getSyntaxHighlightingThemes() {
return listSyntaxHighlightingThemes();
}
function getSupportedLocales() {
return getLocales();
}
2024-04-06 21:57:09 +03:00
function isAllowed(name: string) {
2025-01-09 18:07:02 +02:00
return ALLOWED_OPTIONS.has(name) || name.startsWith("keyboardShortcuts") || name.endsWith("Collapsed") || name.startsWith("hideArchivedNotes");
2019-11-19 20:53:04 +01:00
}
export default {
2018-04-01 20:33:10 -04:00
getOptions,
updateOption,
2019-01-27 21:18:11 +01:00
updateOptions,
getUserThemes,
getSyntaxHighlightingThemes,
getSupportedLocales
2020-06-20 12:31:38 +02:00
};