From 299c1de74e1b156862257063fa29645a3efc28c2 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Tue, 9 Jul 2024 14:15:44 -0500 Subject: [PATCH] Password changing Signed-off-by: Armored Dragon --- backend/core/core.js | 17 ++-- eslint.config.mjs | 2 +- .../views/themes/default/css/settings.css | 38 ++++++++ .../views/themes/default/css/settings.scss | 41 +++++++++ .../views/themes/default/ejs/authorEdit.ejs | 25 ++++- .../views/themes/default/js/editAuthor.js | 43 +++++++-- package-lock.json | 91 +++++++------------ 7 files changed, 180 insertions(+), 77 deletions(-) diff --git a/backend/core/core.js b/backend/core/core.js index 03c3bfc..1de436c 100644 --- a/backend/core/core.js +++ b/backend/core/core.js @@ -7,6 +7,7 @@ let s3; const crypto = require("crypto"); const validate = require("../form_validation"); const permissions = require("../permissions"); +const bcrypt = require("bcrypt"); const md = require("markdown-it")() .use(require("markdown-it-underline")) .use(require("markdown-it-footnote")) @@ -100,23 +101,25 @@ async function getUser({ user_id, username, include_password = false }) { } // TODO: Rename patchUser async function editUser({ requester_id, user_id, user_content }) { + const valid_settings = ['display_name', 'password', 'role']; // Valid settings that can be changed + let user = await getUser({ user_id: user_id }); if (!user.success) return _r(false, "User not found"); user = user.data; // TODO: // If there was a role change, see if the acting user can make these changes + const setting_name = user_content.setting_name + if (!valid_settings.includes(setting_name)) return _r(false, "Invalid setting."); - // TODO: - // If there was a password change, - // check to see if the user can make these changes - // Hash the password + if (setting_name == 'password'){ + user_content.value = await bcrypt.hash(user_content.value, 10); + } - // FIXME: Not secure. ASAP! let formatted = {}; - formatted[user_content.setting_name] = user_content.value; + formatted[setting_name] = user_content.value; - await prisma.user.update({ where: { id: user.id }, data: formatted }); + await prisma.user.update({ where: { id: user.id }, data: formatted }) return _r(true); } async function deleteUser({ user_id }) { diff --git a/eslint.config.mjs b/eslint.config.mjs index 299f664..57e8920 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,4 +1,4 @@ import globals from "globals"; import pluginJs from "@eslint/js"; -export default [{ files: ["**/*.js"], languageOptions: { sourceType: "commonjs" } }, { languageOptions: { globals: globals.browser } }, { rules: { "no-unused-vars": "error", "no-undef": "error", indent: ["error", "tab", { tabWidth: 4 }] } }, pluginJs.configs.recommended]; +export default [{ files: ["**/*.js"], languageOptions: { sourceType: "commonjs" } }, { languageOptions: { globals: globals.browser } }, { rules: { "no-unused-vars": "error", "no-undef": "error", "indent": ["error", "tab", { tabWidth: 4 }], "semi-style": ["error", "last"], } }, pluginJs.configs.recommended]; diff --git a/frontend/views/themes/default/css/settings.css b/frontend/views/themes/default/css/settings.css index fe0b93c..68e550d 100644 --- a/frontend/views/themes/default/css/settings.css +++ b/frontend/views/themes/default/css/settings.css @@ -159,4 +159,42 @@ input:checked + .slider:before { .slider.round:before { border-radius: 50%; +} + +dialog { + border-radius: 5px; + border: 0; + min-width: 300px; +} +dialog .title { + font-size: 1.1rem; + text-align: center; + margin-bottom: 1rem; +} +dialog .entry { + width: 100%; + margin-bottom: 0.5rem; +} +dialog .entry input { + width: 100%; + margin: 0; + box-sizing: border-box; + font-size: 1.1rem; +} +dialog .status { + margin-bottom: 1rem; + color: red; + text-align: center; +} +dialog .horizontal-button-container { + display: flex; + flex-direction: row; +} +dialog .horizontal-button-container * { + flex-grow: 1; + margin: 0 0.1rem; +} + +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.5); } \ No newline at end of file diff --git a/frontend/views/themes/default/css/settings.scss b/frontend/views/themes/default/css/settings.scss index f931841..cf358c8 100644 --- a/frontend/views/themes/default/css/settings.scss +++ b/frontend/views/themes/default/css/settings.scss @@ -171,3 +171,44 @@ input:checked + .slider:before { .slider.round:before { border-radius: 50%; } + +dialog { + border-radius: 5px; + border: 0; + min-width: 300px; + + .title { + font-size: 1.1rem; + text-align: center; + margin-bottom: 1rem; + } + + .entry { + width: 100%; + margin-bottom: 0.5rem; + input { + width: 100%; + margin: 0; + box-sizing: border-box; + font-size: 1.1rem; + } + } + + .status { + margin-bottom: 1rem; + color: red; + text-align: center; + } + + .horizontal-button-container { + display: flex; + flex-direction: row; + * { + flex-grow: 1; + margin: 0 0.1rem; + } + } + } + dialog::backdrop { + background-color: rgba(0, 0, 0, 0.5); + } \ No newline at end of file diff --git a/frontend/views/themes/default/ejs/authorEdit.ejs b/frontend/views/themes/default/ejs/authorEdit.ejs index 9bcf489..909e0ff 100644 --- a/frontend/views/themes/default/ejs/authorEdit.ejs +++ b/frontend/views/themes/default/ejs/authorEdit.ejs @@ -8,6 +8,29 @@ Yet-Another-Blog + +
+ Change Password +
+
+
Current password
+ +
+
+
New password
+ +
+
+
Confirm password
+ +
+
Please enter your current password.
+
+ + +
+
+ <%- include("partials/header.ejs") %>
@@ -21,7 +44,7 @@
Change Password
- +
Change Profile Picture
diff --git a/frontend/views/themes/default/js/editAuthor.js b/frontend/views/themes/default/js/editAuthor.js index 6856e07..343ad78 100644 --- a/frontend/views/themes/default/js/editAuthor.js +++ b/frontend/views/themes/default/js/editAuthor.js @@ -1,12 +1,37 @@ async function changeValue(setting_name, element) { - const form = { - setting_name: setting_name, - value: element.value, - id: window.location.href.split("/")[4], - }; - const response = await request(`/api/web/user`, "PATCH", form); + const form = { + setting_name: setting_name, + value: element.value, + id: window.location.href.split("/")[4], + }; + const response = await request(`/api/web/user`, "PATCH", form); - // TODO: On failure, notify the user - if (response.body.success) { - } + // TODO: On failure, notify the user + if (response.body.success) { + alert("Successfully changed password"); + } } +const change_password_dialog = qs("#change-password-dialog"); + +qs("#change-password-button").addEventListener("click", () => change_password_dialog.showModal()); +qs("#cp-cancel").addEventListener("click", () => change_password_dialog.close()); + +function changePasswordInputUpdate() { + const status = qs("#change-password-dialog .status"); + const current_password = qs("#cp-current"); + const new_password_1 = qs("#cp-new-1"); + const new_password_2 = qs("#cp-new-2"); + + if (current_password.value === "") return (status.innerText = "Please enter your current password."); + + if (new_password_1.value !== new_password_2.value) return (status.innerText = "New password does not match."); + + return (status.innerHTML = " "); +} + +function sendPasswordUpdate() { + const new_password_1 = qs("#cp-new-1"); + // Check fields match + // Send post update + changeValue("password", new_password_1); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index cddce6f..54d0dfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2112,12 +2112,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2350,9 +2351,10 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2480,9 +2482,10 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", "dependencies": { "jake": "^10.8.5" }, @@ -2744,16 +2747,17 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -2823,33 +2827,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -2857,21 +2839,8 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -2982,10 +2951,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3456,6 +3426,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -4729,9 +4700,10 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -4787,6 +4759,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" },