From 8dc96894ea2c1dbbfc6e026499084812ce5a23a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 21:54:44 +0000 Subject: [PATCH 01/13] fix(deps): update dependency nodebb-plugin-2factor to v5.1.3 --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 0af0b7f1aa..0ca59e5ae0 100644 --- a/install/package.json +++ b/install/package.json @@ -89,7 +89,7 @@ "multiparty": "4.2.3", "@nodebb/bootswatch": "3.4.2", "nconf": "0.12.0", - "nodebb-plugin-2factor": "5.1.2", + "nodebb-plugin-2factor": "5.1.3", "nodebb-plugin-composer-default": "9.2.4", "nodebb-plugin-dbsearch": "5.1.5", "nodebb-plugin-emoji": "4.0.6", From 79cd4a36d95fc60397d7b1e53e83f0500d57cc00 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 22:12:50 +0000 Subject: [PATCH 02/13] fix(deps): update dependency jsonwebtoken to v9 --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 0ca59e5ae0..056c7346c1 100644 --- a/install/package.json +++ b/install/package.json @@ -75,7 +75,7 @@ "jquery-ui": "1.13.2", "jsesc": "3.0.2", "json2csv": "5.0.7", - "jsonwebtoken": "8.5.1", + "jsonwebtoken": "9.0.0", "less": "4.1.3", "lodash": "4.17.21", "logrotate-stream": "0.2.8", From aa873e805fcdd37e6c824d3c5d6302a9dd24ae18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 21:54:36 +0000 Subject: [PATCH 03/13] fix(deps): update dependency @socket.io/redis-adapter to v8.0.1 --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 056c7346c1..60da0583e8 100644 --- a/install/package.json +++ b/install/package.json @@ -127,7 +127,7 @@ "slideout": "1.0.1", "socket.io": "4.5.4", "socket.io-client": "4.5.4", - "@socket.io/redis-adapter": "8.0.0", + "@socket.io/redis-adapter": "8.0.1", "sortablejs": "1.15.0", "spdx-license-list": "6.6.0", "spider-detector": "2.0.0", From fdc41646d18e6e34c9258b632857529c19a50233 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 5 Jan 2023 15:59:45 -0500 Subject: [PATCH 04/13] feat: api v3 route to add email to user, optionally bypassing validation email, closes #11009 --- public/openapi/write/users/uid/emails.yaml | 51 ++++++++++++++++++++++ src/controllers/write/users.js | 18 ++++++++ src/routes/write/users.js | 1 + 3 files changed, 70 insertions(+) diff --git a/public/openapi/write/users/uid/emails.yaml b/public/openapi/write/users/uid/emails.yaml index 8bd00809c0..c6b67acf9e 100644 --- a/public/openapi/write/users/uid/emails.yaml +++ b/public/openapi/write/users/uid/emails.yaml @@ -16,6 +16,57 @@ get: responses: '200': description: user emails successfully listed + content: + application/json: + schema: + type: object + properties: + status: + $ref: ../../../components/schemas/Status.yaml#/Status + response: + type: object + properties: + emails: + type: array + items: + type: string + description: An email address +post: + tags: + - users + summary: add email to user + description: | + This operation adds an email to the user account, optionally bypassing the confirmation step if requested. + + **Note**: The confirmation bypass can only be called by super administrators or users with the `admin:users` privilege. + parameters: + - in: path + name: uid + schema: + type: integer + required: true + description: uid of the account to add the email + example: 1 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + email: + type: string + description: A single email address + example: test@example.org + skipConfirmation: + type: boolean + description: If truthy, will automatically confirm the user's email. + example: 1 + required: + - email + responses: + '200': + description: email successfully added to user account content: application/json: schema: diff --git a/src/controllers/write/users.js b/src/controllers/write/users.js index 56d547aaaf..9e400c5ce9 100644 --- a/src/controllers/write/users.js +++ b/src/controllers/write/users.js @@ -253,6 +253,24 @@ Users.getInviteGroups = async function (req, res) { return helpers.formatApiResponse(200, res, userInviteGroups.map(group => group.displayName)); }; +Users.addEmail = async (req, res) => { + const canManageUsers = await privileges.admin.can('admin:users', req.uid); + const skipConfirmation = canManageUsers && req.body.skipConfirmation; + + if (skipConfirmation) { + await user.setUserField(req.params.uid, 'email', req.body.email); + await user.email.confirmByUid(req.params.uid); + } else { + await api.users.update(req, { + uid: req.params.uid, + email: req.body.email, + }); + } + + const emails = await db.getSortedSetRangeByScore('email:uid', 0, 500, req.params.uid, req.params.uid); + helpers.formatApiResponse(200, res, { emails }); +}; + Users.listEmails = async (req, res) => { const [isPrivileged, { showemail }] = await Promise.all([ user.isPrivileged(req.uid), diff --git a/src/routes/write/users.js b/src/routes/write/users.js index 980eccc8a2..23d8d75ddd 100644 --- a/src/routes/write/users.js +++ b/src/routes/write/users.js @@ -48,6 +48,7 @@ function authenticatedRoutes() { setupApiRoute(router, 'get', '/:uid/invites/groups', [...middlewares, middleware.assert.user], controllers.write.users.getInviteGroups); setupApiRoute(router, 'get', '/:uid/emails', [...middlewares, middleware.assert.user], controllers.write.users.listEmails); + setupApiRoute(router, 'post', '/:uid/emails', [...middlewares, middleware.assert.user], controllers.write.users.addEmail); setupApiRoute(router, 'get', '/:uid/emails/:email', [...middlewares, middleware.assert.user], controllers.write.users.getEmail); setupApiRoute(router, 'post', '/:uid/emails/:email/confirm', [...middlewares, middleware.assert.user], controllers.write.users.confirmEmail); From 38175b5e716d5ffd4067bacd2bac6725a8ae49d0 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sat, 21 Jan 2023 14:34:01 -0500 Subject: [PATCH 05/13] test: fix broken test --- src/categories/index.js | 1 - src/categories/update.js | 1 - test/categories.js | 5 +++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/categories/index.js b/src/categories/index.js index a95d862e77..619f756642 100644 --- a/src/categories/index.js +++ b/src/categories/index.js @@ -131,7 +131,6 @@ Categories.getModeratorUids = async function (cids) { return _.uniq(sets.uids[index].concat(_.flatten(sets.groupNames[index].map(g => map[g])))); }); - console.log('what', moderatorUids); return moderatorUids; }; diff --git a/src/categories/update.js b/src/categories/update.js index ec1c2edb1e..d4be83edb8 100644 --- a/src/categories/update.js +++ b/src/categories/update.js @@ -11,7 +11,6 @@ const cache = require('../cache'); module.exports = function (Categories) { Categories.update = async function (modified) { const cids = Object.keys(modified); - console.log('updating', cids); await Promise.all(cids.map(cid => updateCategory(cid, modified[cid]))); return cids; }; diff --git a/test/categories.js b/test/categories.js index 284d0a0696..008110a074 100644 --- a/test/categories.js +++ b/test/categories.js @@ -826,7 +826,7 @@ describe('Categories', () => { }); }); - describe.only('Categories.getModeratorUids', () => { + describe('Categories.getModeratorUids', () => { let cid; before(async () => { @@ -865,7 +865,8 @@ describe('Categories', () => { const payload = {}; payload[cid] = { disabled: 1 }; await Categories.update(payload); - const uids = await Categories.getModeratorUids([1, 2]); + const uids = await Categories.getModeratorUids([cid, 2]); + console.log(uids); assert(!uids[0].includes('1')); }); From cfb484e775c1335c1cd12bf1aef85b4ef532a1ba Mon Sep 17 00:00:00 2001 From: Misty Release Bot Date: Mon, 23 Jan 2023 09:17:53 +0000 Subject: [PATCH 06/13] Latest translations and fallbacks --- public/language/vi/admin/settings/advanced.json | 2 +- public/language/vi/admin/settings/email.json | 2 +- public/language/vi/admin/settings/reputation.json | 2 +- public/language/vi/admin/settings/user.json | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/public/language/vi/admin/settings/advanced.json b/public/language/vi/admin/settings/advanced.json index 4f4b14039f..961593854c 100644 --- a/public/language/vi/admin/settings/advanced.json +++ b/public/language/vi/admin/settings/advanced.json @@ -20,7 +20,7 @@ "headers.coep-help": "Khi được bật (mặc định), sẽ đặt tiêu đề thành require-corp", "headers.coop": "Cross-Origin-Opener-Policy", "headers.corp": "Cross-Origin-Resource-Policy", - "headers.permissions-policy": "Permissions-Policy", + "headers.permissions-policy": "Quyền-Chính sách", "headers.permissions-policy-help": "Allows setting permissions policy header, for example \"geolocation=*, camera=()\", see this for more info.", "hsts": "Bảo Vệ Truyền Tải Nghiêm Ngặt", "hsts.enabled": "Đã bật HSTS (đề nghị)", diff --git a/public/language/vi/admin/settings/email.json b/public/language/vi/admin/settings/email.json index cdd5a01772..39332d35cb 100644 --- a/public/language/vi/admin/settings/email.json +++ b/public/language/vi/admin/settings/email.json @@ -6,7 +6,7 @@ "from-help": "Tên người gửi hiển thị trong email.", "confirmation-settings": "Xác nhận", - "confirmation.expiry": "Hours to keep email confirmation link valid", + "confirmation.expiry": "Số giờ để giữ cho liên kết xác nhận email hợp lệ", "smtp-transport": "Truyền Tải SMTP", "smtp-transport.enabled": "Bật truyền tải SMTP", diff --git a/public/language/vi/admin/settings/reputation.json b/public/language/vi/admin/settings/reputation.json index ba1d868e2b..968d57555d 100644 --- a/public/language/vi/admin/settings/reputation.json +++ b/public/language/vi/admin/settings/reputation.json @@ -27,5 +27,5 @@ "flags.action-on-resolve": "Do the following when a flag is resolved", "flags.action-on-reject": "Do the following when a flag is rejected", "flags.action.nothing": "Do nothing", - "flags.action.rescind": "Rescind the notification send to moderators/administrators" + "flags.action.rescind": "Hủy bỏ gửi thông báo cho người điều hành/quản trị viên" } \ No newline at end of file diff --git a/public/language/vi/admin/settings/user.json b/public/language/vi/admin/settings/user.json index 2ed9abdd02..920b8135b3 100644 --- a/public/language/vi/admin/settings/user.json +++ b/public/language/vi/admin/settings/user.json @@ -1,7 +1,7 @@ { "authentication": "Xác thực", "email-confirm-interval": "Người dùng không thể gửi lại email xác nhận cho đến khi", - "email-confirm-interval2": "minutes have elapsed", + "email-confirm-interval2": "phút đã trôi qua", "allow-login-with": "Cho phép đăng nhập với", "allow-login-with.username-email": "Tên Đăng Nhập hoặc Email", "allow-login-with.username": "Chỉ Tên Đăng Nhập", @@ -29,8 +29,8 @@ "session-time-days": "Ngày", "session-time-seconds": "Giây", "session-time-help": "Giá trị này dùng để điều chỉnh thời gian người dùng đăng nhập khi họ chọn "Nhớ Tôi" lúc đăng nhập. Lưu ý chỉ một trong những giá trị này sẽ được dùng. Nếu không có giá trị giây chúng tôi sẽ dùng ngày. Nếu không có ngày mặc định là 14 ngày.", - "session-duration": "Session length if \"Remember Me\" is not checked (seconds)", - "session-duration-help": "By default — or if set to 0 — a user will stay logged in for the duration of the session (e.g. however long the browser window/tab remains open). Set this value to explicitly invalidate the session after the specified number of seconds.", + "session-duration": "Thời lượng phiên nếu \"Ghi nhớ tôi\" không được chọn (giây)", + "session-duration-help": "Theo mặc định — hoặc nếu đặt thành 0 — người dùng sẽ duy trì trạng thái đăng nhập trong suốt thời gian của phiên (VD: cửa sổ/tab trình duyệt vẫn mở trong bao lâu). Đặt giá trị này để vô hiệu hóa rõ ràng phiên sau số giây đã chỉ định.", "online-cutoff": "Số phút sau khi người dùng được coi là không hoạt động", "online-cutoff-help": "Nếu người dùng không thao tác trong khoảng thời gian này, được coi là không hoạt động và không nhận được cập nhật theo thời gian thực.", "registration": "Đăng Ký Người Dùng", From f295174e0772b5b18d052b4c0403694d61c98123 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Sat, 21 Jan 2023 14:34:01 -0500 Subject: [PATCH 07/13] test: fix broken test --- src/categories/index.js | 1 - src/categories/update.js | 1 - test/categories.js | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/categories/index.js b/src/categories/index.js index a95d862e77..619f756642 100644 --- a/src/categories/index.js +++ b/src/categories/index.js @@ -131,7 +131,6 @@ Categories.getModeratorUids = async function (cids) { return _.uniq(sets.uids[index].concat(_.flatten(sets.groupNames[index].map(g => map[g])))); }); - console.log('what', moderatorUids); return moderatorUids; }; diff --git a/src/categories/update.js b/src/categories/update.js index ec1c2edb1e..d4be83edb8 100644 --- a/src/categories/update.js +++ b/src/categories/update.js @@ -11,7 +11,6 @@ const cache = require('../cache'); module.exports = function (Categories) { Categories.update = async function (modified) { const cids = Object.keys(modified); - console.log('updating', cids); await Promise.all(cids.map(cid => updateCategory(cid, modified[cid]))); return cids; }; diff --git a/test/categories.js b/test/categories.js index 284d0a0696..4a92929864 100644 --- a/test/categories.js +++ b/test/categories.js @@ -826,7 +826,7 @@ describe('Categories', () => { }); }); - describe.only('Categories.getModeratorUids', () => { + describe('Categories.getModeratorUids', () => { let cid; before(async () => { @@ -865,7 +865,7 @@ describe('Categories', () => { const payload = {}; payload[cid] = { disabled: 1 }; await Categories.update(payload); - const uids = await Categories.getModeratorUids([1, 2]); + const uids = await Categories.getModeratorUids([cid, 2]); assert(!uids[0].includes('1')); }); From 7d04e95226bf22f8db415be24ebf8f9352bd29c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 23 Jan 2023 11:09:19 -0500 Subject: [PATCH 08/13] fix: #11194, allow access to sub dashboard pages --- src/privileges/admin.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/privileges/admin.js b/src/privileges/admin.js index 5a733d30f4..166236ac76 100644 --- a/src/privileges/admin.js +++ b/src/privileges/admin.js @@ -66,6 +66,7 @@ privsAdmin.routeMap = { uploadDefaultAvatar: 'admin:settings', }; privsAdmin.routePrefixMap = { + 'dashboard/': 'admin:dashboard', 'manage/categories/': 'admin:categories', 'manage/privileges/': 'admin:privileges', 'manage/groups/': 'admin:groups', From 9c250b78b05ca2abf31a79971ed0c60ca07664ec Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2023 11:27:57 -0500 Subject: [PATCH 09/13] fix(deps): pinning sub dependency json-schema-ref-parser to 9.0.9 ref: https://github.com/APIDevTools/json-schema-ref-parser/issues/298 --- install/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 1af9a00cf6..7dc6237452 100644 --- a/install/package.json +++ b/install/package.json @@ -167,7 +167,8 @@ "smtp-server": "3.11.0" }, "resolutions": { - "*/jquery": "3.6.3" + "*/jquery": "3.6.3", + "@apidevtools/json-schema-ref-parser": "9.0.9" }, "bugs": { "url": "https://github.com/NodeBB/NodeBB/issues" From 0bffd3d93cd8a6f286d3a796ec0448c38d57b526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 23 Jan 2023 11:40:17 -0500 Subject: [PATCH 10/13] fix: #11195, allow users with admin:users privilege to delete users in acp --- src/api/users.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/api/users.js b/src/api/users.js index c23f2c04d6..e0382c95cd 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -307,18 +307,17 @@ async function isPrivilegedOrSelfAndPasswordMatch(caller, data) { async function processDeletion({ uid, method, password, caller }) { const isTargetAdmin = await user.isAdministrator(uid); const isSelf = parseInt(uid, 10) === parseInt(caller.uid, 10); - const isAdmin = await user.isAdministrator(caller.uid); + const hasAdminPrivilege = await privileges.admin.can('admin:users', caller.uid); if (isSelf && meta.config.allowAccountDelete !== 1) { throw new Error('[[error:account-deletion-disabled]]'); - } else if (!isSelf && !isAdmin) { + } else if (!isSelf && !hasAdminPrivilege) { throw new Error('[[error:no-privileges]]'); } else if (isTargetAdmin) { throw new Error('[[error:cant-delete-admin]'); } // Privilege checks -- only deleteAccount is available for non-admins - const hasAdminPrivilege = await privileges.admin.can('admin:users', caller.uid); if (!hasAdminPrivilege && ['delete', 'deleteContent'].includes(method)) { throw new Error('[[error:no-privileges]]'); } From a788bd1344825ad4759e39d6e98d8bf3695bd639 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2023 12:31:43 -0500 Subject: [PATCH 11/13] revert: 9c250b78b05ca2abf31a79971ed0c60ca07664ec, fix: comment out broken test for now --- install/package.json | 3 +-- test/api.js | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/install/package.json b/install/package.json index 7dc6237452..1af9a00cf6 100644 --- a/install/package.json +++ b/install/package.json @@ -167,8 +167,7 @@ "smtp-server": "3.11.0" }, "resolutions": { - "*/jquery": "3.6.3", - "@apidevtools/json-schema-ref-parser": "9.0.9" + "*/jquery": "3.6.3" }, "bugs": { "url": "https://github.com/NodeBB/NodeBB/issues" diff --git a/test/api.js b/test/api.js index cc13650770..53774304cf 100644 --- a/test/api.js +++ b/test/api.js @@ -228,14 +228,15 @@ describe('API', async () => { setup = true; } - it('should pass OpenAPI v3 validation', async () => { + // Test failing due to https://github.com/APIDevTools/json-schema-ref-parser/issues/298 + /* it('should pass OpenAPI v3 validation', async () => { try { await SwaggerParser.validate(readApiPath); await SwaggerParser.validate(writeApiPath); } catch (e) { assert.ifError(e); } - }); + }); */ readApi = await SwaggerParser.dereference(readApiPath); writeApi = await SwaggerParser.dereference(writeApiPath); From 00e48803a6f0f589621a37b228b139b7e3cec498 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2023 15:11:08 -0500 Subject: [PATCH 12/13] fix(deps): downgrade swagger-parser to v9 --- install/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/package.json b/install/package.json index 1af9a00cf6..c2c63ced4b 100644 --- a/install/package.json +++ b/install/package.json @@ -148,7 +148,7 @@ "zxcvbn": "4.4.2" }, "devDependencies": { - "@apidevtools/swagger-parser": "10.0.3", + "@apidevtools/swagger-parser": "9.0.0", "@commitlint/cli": "17.3.0", "@commitlint/config-angular": "17.3.0", "coveralls": "3.1.1", From fecd84d1a01bf1d448128725c8980ce190d127eb Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Mon, 23 Jan 2023 15:19:24 -0500 Subject: [PATCH 13/13] revert: a788bd1344825ad4759e39d6e98d8bf3695bd639 --- test/api.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/api.js b/test/api.js index 53774304cf..cc13650770 100644 --- a/test/api.js +++ b/test/api.js @@ -228,15 +228,14 @@ describe('API', async () => { setup = true; } - // Test failing due to https://github.com/APIDevTools/json-schema-ref-parser/issues/298 - /* it('should pass OpenAPI v3 validation', async () => { + it('should pass OpenAPI v3 validation', async () => { try { await SwaggerParser.validate(readApiPath); await SwaggerParser.validate(writeApiPath); } catch (e) { assert.ifError(e); } - }); */ + }); readApi = await SwaggerParser.dereference(readApiPath); writeApi = await SwaggerParser.dereference(writeApiPath);