diff --git a/package-lock.json b/package-lock.json
index 037578fba..05afb6ee6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7855,7 +7855,7 @@
},
"node_modules/isexe": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/ie/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"node_modules/isobject": {
diff --git a/src/public/app/widgets/type_widgets/options/multi_factor_authentication.js b/src/public/app/widgets/type_widgets/options/multi_factor_authentication.js
index 3aee5b6d1..e755c62bb 100644
--- a/src/public/app/widgets/type_widgets/options/multi_factor_authentication.js
+++ b/src/public/app/widgets/type_widgets/options/multi_factor_authentication.js
@@ -39,7 +39,7 @@ const TPL = `
Generate TOTP Secret
-
+
`;
export default class MultiFactorAuthenticationOptions extends OptionsWidget {
@@ -56,9 +56,6 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
this.$mfaHeadding.text("Multi-Factor Authentication");
this.generateKey();
- // var gen = require("speakeasy");
- // toastService.showMessage("***REMOVED***");
-
this.$totpEnabled.on("change", async () => {
this.updateCheckboxOption("totpEnabled", this.$totpEnabled);
});
@@ -67,6 +64,10 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
this.generateKey();
});
+ this.$saveTotpButton.on("click", async () => {
+ this.save();
+ });
+
this.$protectedSessionTimeout = this.$widget.find(
".protected-session-timeout-in-seconds"
);
@@ -100,49 +101,30 @@ export default class MultiFactorAuthenticationOptions extends OptionsWidget {
// }
optionsLoaded(options) {
- // I need to make sure that this is actually pinging the server and that this information is being pulled
- // because it is telling me "totpEnabled is not allowed to be changed" in a toast every time I check the box
server.get("totp/enabled").then((result) => {
if (result.success) {
- console.log("Result message: " + typeof result.message);
- console.log("Result message: " + result.message);
- this.setCheckboxState(this.$totpEnabled, result.message);
-
- console.log("TOTP Status: " + typeof result.message);
-
- if (result.message) {
- this.$totpSecretInput.prop("disabled", false);
- this.$saveTotpButton.prop("disabled", false);
- } else {
- this.$totpSecretInput.prop("disabled", true);
- this.$saveTotpButton.prop("disabled", true);
- }
+ this.$totpEnabled.prop("checked", result.message);
+ this.$totpSecretInput.prop("disabled", !result.message);
+ this.$saveTotpButton.prop("disabled", !result.message);
+ this.$totpSecret.prop("disapbled", !result.message);
} else {
toastService.showError(result.message);
}
});
+ server.get("totp/get").then((result) => {
+ this.$totpSecretInput.text(result.secret);
+ });
+
this.$protectedSessionTimeout.val(options.protectedSessionTimeout);
}
save() {
- const oldPassword = this.$oldPassword.val();
- const newPassword1 = this.$newPassword1.val();
- const newPassword2 = this.$newPassword2.val();
-
- this.$oldPassword.val("");
- this.$newPassword1.val("");
- this.$newPassword2.val("");
-
- if (newPassword1 !== newPassword2) {
- toastService.showError("New passwords are not the same.");
- return false;
- }
+ // TODO: CHECK VALIDITY OF SECRET
server
- .post("password/change", {
- current_password: oldPassword,
- new_password: newPassword1,
+ .post("totp/set", {
+ secret: this.$totpSecretInput.val(),
})
.then((result) => {
if (result.success) {
diff --git a/src/routes/api/options.ts b/src/routes/api/options.ts
index 24d7b35ad..97eab092c 100644
--- a/src/routes/api/options.ts
+++ b/src/routes/api/options.ts
@@ -1,145 +1,152 @@
"use strict";
-import optionService = require('../../services/options');
-import log = require('../../services/log');
-import searchService = require('../../services/search/services/search');
-import ValidationError = require('../../errors/validation_error');
-import { Request } from 'express';
+import optionService = require("../../services/options");
+import log = require("../../services/log");
+import searchService = require("../../services/search/services/search");
+import ValidationError = require("../../errors/validation_error");
+import { Request } from "express";
// options allowed to be updated directly in the Options dialog
const ALLOWED_OPTIONS = new Set([
- 'eraseEntitiesAfterTimeInSeconds',
- 'protectedSessionTimeout',
- 'revisionSnapshotTimeInterval',
- 'zoomFactor',
- 'theme',
- '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',
- 'disableTray',
- 'customSearchEngineName',
- 'customSearchEngineUrl',
- 'promotedAttributesOpenInRibbon',
- 'editedNotesOpenInRibbon'
+ "eraseEntitiesAfterTimeInSeconds",
+ "protectedSessionTimeout",
+ "revisionSnapshotTimeInterval",
+ "zoomFactor",
+ "theme",
+ "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",
+ "disableTray",
+ "customSearchEngineName",
+ "customSearchEngineUrl",
+ "promotedAttributesOpenInRibbon",
+ "editedNotesOpenInRibbon",
+ "totpEnabled",
]);
function getOptions() {
- const optionMap = optionService.getOptionMap();
- const resultMap: Record = {};
+ const optionMap = optionService.getOptionMap();
+ const resultMap: Record = {};
- for (const optionName in optionMap) {
- if (isAllowed(optionName)) {
- resultMap[optionName] = optionMap[optionName];
- }
+ for (const optionName in optionMap) {
+ if (isAllowed(optionName)) {
+ resultMap[optionName] = optionMap[optionName];
}
+ }
- resultMap['isPasswordSet'] = optionMap['passwordVerificationHash'] ? 'true' : 'false';
+ resultMap["isPasswordSet"] = optionMap["passwordVerificationHash"]
+ ? "true"
+ : "false";
- return resultMap;
+ return resultMap;
}
function updateOption(req: Request) {
- const {name, value} = req.params;
+ const { name, value } = req.params;
- if (!update(name, value)) {
- throw new ValidationError("not allowed option to change");
- }
+ if (!update(name, value)) {
+ throw new ValidationError("not allowed option to change");
+ }
}
function updateOptions(req: Request) {
- for (const optionName in req.body) {
- console.log( optionName )
- 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
- throw new Error(`Option '${optionName}' is not allowed to be changed`);
- }
+ for (const optionName in req.body) {
+ console.log(optionName);
+ 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
+ throw new Error(`Option '${optionName}' is not allowed to be changed`);
}
+ }
}
function update(name: string, value: string) {
- if (!isAllowed(name)) {
- return false;
- }
+ if (!isAllowed(name)) {
+ return false;
+ }
- if (name !== 'openNoteContexts') {
- log.info(`Updating option '${name}' to '${value}'`);
- }
+ if (name !== "openNoteContexts") {
+ log.info(`Updating option '${name}' to '${value}'`);
+ }
- optionService.setOption(name, value);
+ optionService.setOption(name, value);
- return true;
+ return true;
}
function getUserThemes() {
- const notes = searchService.searchNotes("#appTheme", {ignoreHoistedNote: true});
- const ret = [];
+ const notes = searchService.searchNotes("#appTheme", {
+ ignoreHoistedNote: true,
+ });
+ const ret = [];
- for (const note of notes) {
- let value = note.getOwnedLabelValue('appTheme');
+ for (const note of notes) {
+ let value = note.getOwnedLabelValue("appTheme");
- if (!value) {
- value = note.title.toLowerCase().replace(/[^a-z0-9]/gi, '-');
- }
-
- ret.push({
- val: value,
- title: note.title,
- noteId: note.noteId
- });
+ if (!value) {
+ value = note.title.toLowerCase().replace(/[^a-z0-9]/gi, "-");
}
- return ret;
+ ret.push({
+ val: value,
+ title: note.title,
+ noteId: note.noteId,
+ });
+ }
+
+ return ret;
}
function isAllowed(name: string) {
- return ALLOWED_OPTIONS.has(name)
- || name.startsWith("keyboardShortcuts")
- || name.endsWith("Collapsed")
- || name.startsWith("hideArchivedNotes");
+ return (
+ ALLOWED_OPTIONS.has(name) ||
+ name.startsWith("keyboardShortcuts") ||
+ name.endsWith("Collapsed") ||
+ name.startsWith("hideArchivedNotes")
+ );
}
export = {
- getOptions,
- updateOption,
- updateOptions,
- getUserThemes
+ getOptions,
+ updateOption,
+ updateOptions,
+ getUserThemes,
};
diff --git a/src/routes/api/totp.ts b/src/routes/api/totp.ts
index a4297c130..020e7e55c 100644
--- a/src/routes/api/totp.ts
+++ b/src/routes/api/totp.ts
@@ -1,4 +1,6 @@
import options = require("../../services/options");
+import totp_secret = require("../../services/encryption/totp_secret");
+import { Request } from "express";
const speakeasy = require("speakeasy");
function verifyOTPToken(guessedToken: any) {
@@ -20,24 +22,35 @@ function generateSecret() {
}
function checkForTOTP() {
- const totpEnabled = options.getOptionBool("totpEnabled")
+ const totpEnabled = options.getOptionBool("totpEnabled");
return { success: "true", message: totpEnabled };
}
function enableTOTP() {
- options.setOption("totpEnabled", true)
+ options.setOption("totpEnab| voidled", true);
return { success: "true" };
}
function disableTOTP() {
- options.setOption("totpEnabled", false)
+ options.setOption("totpEnabled", false);
return { success: "true" };
}
+function setTotpSecret(req: Request) {
+ console.log("TODO: Save Secret");
+ // totp_secret.setTotpSecret(req.body.secret);
+}
+
+function getSecret() {
+ return "TODO: Get Secret";
+}
+
export = {
verifyOTPToken,
generateSecret,
checkForTOTP,
enableTOTP,
- disableTOTP
+ disableTOTP,
+ setTotpSecret,
+ getSecret,
};
diff --git a/src/routes/routes.ts b/src/routes/routes.ts
index 6f1eb3f1d..3b3c60225 100644
--- a/src/routes/routes.ts
+++ b/src/routes/routes.ts
@@ -157,8 +157,10 @@ function register(app: express.Application) {
apiRoute(GET, "/api/totp/generate", totp.generateSecret);
apiRoute(GET, "/api/totp/enabled", totp.checkForTOTP);
- apiRoute(GET, "/api/totp/enable", totp.enableTOTP);
- apiRoute(GET, "/api/totp/disable", totp.disableTOTP);
+ apiRoute(PST, "/api/totp/enable", totp.enableTOTP);
+ apiRoute(PST, "/api/totp/disable", totp.disableTOTP);
+ apiRoute(PST, "/api/totp/set", totp.setTotpSecret);
+ apiRoute(GET, "/api/totp/get", totp.getSecret);
apiRoute(GET, "/api/tree", treeApiRoute.getTree);
apiRoute(PST, "/api/tree/load", treeApiRoute.load);
@@ -185,7 +187,7 @@ function register(app: express.Application) {
apiRoute(PUT, "/api/notes/:noteId/title", notesApiRoute.changeTitle);
apiRoute(
PST,
- "/api/notes/:noteId/duplicate/:parentNoteId",
+ "/api/notes/:noteId/duplicPOSTate/:parentNoteId",
notesApiRoute.duplicateSubtree
);
apiRoute(