diff --git a/packages/core/__e2e__/monographs.test.js b/packages/core/__e2e__/monographs.test.js
index 91e5159a3..8582e6cbd 100644
--- a/packages/core/__e2e__/monographs.test.js
+++ b/packages/core/__e2e__/monographs.test.js
@@ -18,12 +18,7 @@ along with this program. If not, see .
*/
import { databaseTest, noteTest, StorageInterface } from "../__tests__/utils";
-
-const user = {
- email: process.env.EMAIL,
- password: process.env.PASSWORD,
- hashedPassword: process.env.HASHED_PASSWORD
-};
+import { login } from "./utils";
jest.setTimeout(15 * 1000);
@@ -53,7 +48,7 @@ afterAll(async () => {
test("publish a monograph", () =>
noteTest().then(async ({ db, id }) => {
- await db.user.login(user.email, user.password, user.hashedPassword);
+ await login(db);
await db.monographs.init();
const monographId = await db.monographs.publish(id);
@@ -68,7 +63,7 @@ test("publish a monograph", () =>
test("update a published monograph", () =>
noteTest().then(async ({ db, id }) => {
- await db.user.login(user.email, user.password, user.hashedPassword);
+ await login(db);
await db.monographs.init();
const monographId = await db.monographs.publish(id);
@@ -85,7 +80,7 @@ test("update a published monograph", () =>
test("unpublish a monograph", () =>
noteTest().then(async ({ db, id }) => {
- await db.user.login(user.email, user.password, user.hashedPassword);
+ await login(db);
await db.monographs.init();
await db.monographs.publish(id);
diff --git a/packages/core/__e2e__/token-manager.test.js b/packages/core/__e2e__/token-manager.test.js
index a101b0ed0..3246a1dca 100644
--- a/packages/core/__e2e__/token-manager.test.js
+++ b/packages/core/__e2e__/token-manager.test.js
@@ -19,6 +19,7 @@ along with this program. If not, see .
import DB from "../api";
import StorageInterface from "../__mocks__/storage.mock";
+import { login } from "./utils";
const user = {
email: process.env.EMAIL,
@@ -30,9 +31,7 @@ test("refresh token concurrently", async () => {
const db = new DB(StorageInterface);
await db.init();
- await expect(
- db.user.login(user.email, user.password, user.hashedPassword)
- ).resolves.not.toThrow();
+ await expect(login(db)).resolves.not.toThrow();
const token = await db.user.tokenManager.getToken();
expect(token).toBeDefined();
@@ -51,9 +50,7 @@ test("refresh token using the same refresh_token multiple time", async () => {
const db = new DB(StorageInterface);
await db.init();
- await expect(
- db.user.login(user.email, user.password, user.hashedPassword)
- ).resolves.not.toThrow();
+ await expect(login(db)).resolves.not.toThrow();
const token = await db.user.tokenManager.getToken();
expect(token).toBeDefined();
diff --git a/packages/core/__e2e__/user-manager.test.js b/packages/core/__e2e__/user-manager.test.js
index df28ada2f..ea1d47a86 100644
--- a/packages/core/__e2e__/user-manager.test.js
+++ b/packages/core/__e2e__/user-manager.test.js
@@ -18,12 +18,7 @@ along with this program. If not, see .
*/
import { databaseTest } from "../__tests__/utils";
-
-const user = {
- email: process.env.EMAIL,
- password: process.env.PASSWORD,
- hashed: process.env.HASHED_PASSWORD
-};
+import { login, user } from "./utils";
// test("signup user and check for token", async () => {
// const db = new DB(StorageInterface);
@@ -40,9 +35,7 @@ test(
"login user and check for token",
() =>
databaseTest().then(async (db) => {
- await expect(
- db.user.login(user.email, user.password, user.hashed)
- ).resolves.not.toThrow();
+ await expect(login(db)).resolves.not.toThrow();
await expect(db.user.tokenManager.getToken()).resolves.toBeDefined();
}),
@@ -53,7 +46,7 @@ test(
"login user and get user data",
() =>
databaseTest().then(async (db) => {
- await db.user.login(user.email, user.password, user.hashed);
+ await login(db);
const userData = await db.user.getUser();
expect(userData.email).toBe(user.email);
@@ -65,7 +58,7 @@ test(
"login user and logout user",
() =>
databaseTest().then(async (db) => {
- await db.user.login(user.email, user.password, user.hashed);
+ await login(db);
await expect(db.user.logout()).resolves.not.toThrow();
}),
diff --git a/packages/core/__e2e__/utils.js b/packages/core/__e2e__/utils.js
new file mode 100644
index 000000000..78821dccf
--- /dev/null
+++ b/packages/core/__e2e__/utils.js
@@ -0,0 +1,36 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2022 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { authenticator } from "otplib";
+
+export const user = {
+ email: process.env.EMAIL,
+ password: process.env.PASSWORD,
+ hashed: process.env.HASHED_PASSWORD,
+ totpSecret: process.env.TOTP_SECRET
+};
+
+export async function login(db) {
+ await db.user.authenticateEmail(user.email);
+
+ const token = authenticator.generate(user.totpSecret);
+ await db.user.authenticateMultiFactorCode(token, "app");
+
+ await db.user.authenticatePassword(user.email, user.password, user.hashed);
+}
diff --git a/packages/core/api/user-manager.js b/packages/core/api/user-manager.js
index 9ab795926..bf2ddb7ef 100644
--- a/packages/core/api/user-manager.js
+++ b/packages/core/api/user-manager.js
@@ -147,51 +147,6 @@ class UserManager {
EV.publish(EVENTS.userLoggedIn, user);
}
- /**
- * @deprecated Please use `authenticateEmail`, `authenticateMultiFactorCode` & `authenticatePassword` for login
- */
- async login(email, password, hashedPassword = undefined) {
- return this._login({ email, password, hashedPassword });
- }
-
- /**
- * @deprecated Please use `authenticateEmail`, `authenticateMultiFactorCode` & `authenticatePassword` for login
- */
- async mfaLogin(email, password, { code, method }) {
- return this._login({ email, password, code, method });
- }
-
- /**
- * @private
- */
- async _login({ email, password, hashedPassword, code, method }) {
- email = email && email.toLowerCase();
-
- if (!hashedPassword && password) {
- hashedPassword = await this._storage.hash(password, email);
- }
-
- await this.tokenManager.saveToken(
- await http.post(`${constants.AUTH_HOST}${ENDPOINTS.token}`, {
- username: email,
- password: hashedPassword,
- grant_type: code ? "mfa" : "password",
- scope: "notesnook.sync offline_access openid IdentityServerApi",
- client_id: "notesnook",
- "mfa:code": code,
- "mfa:method": method
- })
- );
-
- const user = await this.fetchUser();
- await this._storage.deriveCryptoKey(`_uk_@${user.email}`, {
- password,
- salt: user.salt
- });
-
- EV.publish(EVENTS.userLoggedIn, user);
- }
-
async getSessions() {
const token = await this.tokenManager.getAccessToken();
if (!token) return;
diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json
index d53576737..b7c8a3c12 100644
--- a/packages/core/package-lock.json
+++ b/packages/core/package-lock.json
@@ -41,7 +41,8 @@
"jest": "^28.1.3",
"jest-fetch-mock": "^3.0.3",
"jsdom": "^20.0.0",
- "mockdate": "^3.0.5"
+ "mockdate": "^3.0.5",
+ "otplib": "^12.0.1"
}
},
"node_modules/@ampproject/remapping": {
@@ -2520,6 +2521,53 @@
"node": ">= 10"
}
},
+ "node_modules/@otplib/core": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz",
+ "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==",
+ "dev": true
+ },
+ "node_modules/@otplib/plugin-crypto": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz",
+ "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==",
+ "dev": true,
+ "dependencies": {
+ "@otplib/core": "^12.0.1"
+ }
+ },
+ "node_modules/@otplib/plugin-thirty-two": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz",
+ "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==",
+ "dev": true,
+ "dependencies": {
+ "@otplib/core": "^12.0.1",
+ "thirty-two": "^1.0.2"
+ }
+ },
+ "node_modules/@otplib/preset-default": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz",
+ "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==",
+ "dev": true,
+ "dependencies": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/plugin-crypto": "^12.0.1",
+ "@otplib/plugin-thirty-two": "^12.0.1"
+ }
+ },
+ "node_modules/@otplib/preset-v11": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz",
+ "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==",
+ "dev": true,
+ "dependencies": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/plugin-crypto": "^12.0.1",
+ "@otplib/plugin-thirty-two": "^12.0.1"
+ }
+ },
"node_modules/@selderee/plugin-htmlparser2": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.9.0.tgz",
@@ -8345,6 +8393,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/otplib": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz",
+ "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==",
+ "dev": true,
+ "dependencies": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/preset-default": "^12.0.1",
+ "@otplib/preset-v11": "^12.0.1"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -9167,6 +9226,15 @@
"node": "*"
}
},
+ "node_modules/thirty-two": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
+ "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.2.6"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -11398,6 +11466,53 @@
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz",
"integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ=="
},
+ "@otplib/core": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/core/-/core-12.0.1.tgz",
+ "integrity": "sha512-4sGntwbA/AC+SbPhbsziRiD+jNDdIzsZ3JUyfZwjtKyc/wufl1pnSIaG4Uqx8ymPagujub0o92kgBnB89cuAMA==",
+ "dev": true
+ },
+ "@otplib/plugin-crypto": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-crypto/-/plugin-crypto-12.0.1.tgz",
+ "integrity": "sha512-qPuhN3QrT7ZZLcLCyKOSNhuijUi9G5guMRVrxq63r9YNOxxQjPm59gVxLM+7xGnHnM6cimY57tuKsjK7y9LM1g==",
+ "dev": true,
+ "requires": {
+ "@otplib/core": "^12.0.1"
+ }
+ },
+ "@otplib/plugin-thirty-two": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/plugin-thirty-two/-/plugin-thirty-two-12.0.1.tgz",
+ "integrity": "sha512-MtT+uqRso909UkbrrYpJ6XFjj9D+x2Py7KjTO9JDPhL0bJUYVu5kFP4TFZW4NFAywrAtFRxOVY261u0qwb93gA==",
+ "dev": true,
+ "requires": {
+ "@otplib/core": "^12.0.1",
+ "thirty-two": "^1.0.2"
+ }
+ },
+ "@otplib/preset-default": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/preset-default/-/preset-default-12.0.1.tgz",
+ "integrity": "sha512-xf1v9oOJRyXfluBhMdpOkr+bsE+Irt+0D5uHtvg6x1eosfmHCsCC6ej/m7FXiWqdo0+ZUI6xSKDhJwc8yfiOPQ==",
+ "dev": true,
+ "requires": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/plugin-crypto": "^12.0.1",
+ "@otplib/plugin-thirty-two": "^12.0.1"
+ }
+ },
+ "@otplib/preset-v11": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/@otplib/preset-v11/-/preset-v11-12.0.1.tgz",
+ "integrity": "sha512-9hSetMI7ECqbFiKICrNa4w70deTUfArtwXykPUvSHWOdzOlfa9ajglu7mNCntlvxycTiOAXkQGwjQCzzDEMRMg==",
+ "dev": true,
+ "requires": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/plugin-crypto": "^12.0.1",
+ "@otplib/plugin-thirty-two": "^12.0.1"
+ }
+ },
"@selderee/plugin-htmlparser2": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.9.0.tgz",
@@ -16263,6 +16378,17 @@
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
"dev": true
},
+ "otplib": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz",
+ "integrity": "sha512-xDGvUOQjop7RDgxTQ+o4pOol0/3xSZzawTiPKRrHnQWAy0WjhNs/5HdIDJCrqC4MBynmjXgULc6YfioaxZeFgg==",
+ "dev": true,
+ "requires": {
+ "@otplib/core": "^12.0.1",
+ "@otplib/preset-default": "^12.0.1",
+ "@otplib/preset-v11": "^12.0.1"
+ }
+ },
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -16885,6 +17011,12 @@
}
}
},
+ "thirty-two": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
+ "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
+ "dev": true
+ },
"tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
diff --git a/packages/core/package.json b/packages/core/package.json
index 241d2bdd1..3db1cedab 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -27,7 +27,8 @@
"jest": "^28.1.3",
"jest-fetch-mock": "^3.0.3",
"jsdom": "^20.0.0",
- "mockdate": "^3.0.5"
+ "mockdate": "^3.0.5",
+ "otplib": "^12.0.1"
},
"scripts": {
"test:e2e": "env-cmd -e e2e jest --forceExit",