From f33c8849d84fac75655f8ec61d63b82808ab4d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Tue, 30 Jul 2024 21:30:00 -0400 Subject: [PATCH] feat: show custom fields on edit/profile --- .../en-GB/admin/manage/user-custom-fields.json | 1 + src/controllers/accounts/edit.js | 5 ++++- src/controllers/accounts/helpers.js | 17 +++++++++++++++++ src/controllers/accounts/profile.js | 6 ++++-- src/controllers/admin/users.js | 2 +- src/socket.io/admin/user.js | 1 + src/user/data.js | 12 ++++++++++-- src/user/profile.js | 1 + .../manage-custom-user-fields-modal.tpl | 1 + 9 files changed, 40 insertions(+), 6 deletions(-) diff --git a/public/language/en-GB/admin/manage/user-custom-fields.json b/public/language/en-GB/admin/manage/user-custom-fields.json index 41e3cb8e0c..bf2546385c 100644 --- a/public/language/en-GB/admin/manage/user-custom-fields.json +++ b/public/language/en-GB/admin/manage/user-custom-fields.json @@ -8,6 +8,7 @@ "name": "Name", "type": "Type", "input-type-text": "Input (Text)", + "input-type-link": "Input (Link)", "input-type-number": "Input (Number)", "input-type-select": "Select", "select-options": "Options", diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index 599f898c24..c687279698 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -7,6 +7,7 @@ const groups = require('../../groups'); const privileges = require('../../privileges'); const plugins = require('../../plugins'); const file = require('../../file'); +const accountHelpers = require('./helpers'); const editController = module.exports; @@ -25,11 +26,13 @@ editController.get = async function (req, res, next) { allowMultipleBadges, } = userData; - const [canUseSignature, canManageUsers] = await Promise.all([ + const [canUseSignature, canManageUsers, customUserFields] = await Promise.all([ privileges.global.can('signature', req.uid), privileges.admin.can('admin:users', req.uid), + accountHelpers.getCustomUserFields(userData), ]); + userData.customUserFields = customUserFields; userData.maximumSignatureLength = meta.config.maximumSignatureLength; userData.maximumAboutMeLength = meta.config.maximumAboutMeLength; userData.maximumProfileImageSize = meta.config.maximumProfileImageSize; diff --git a/src/controllers/accounts/helpers.js b/src/controllers/accounts/helpers.js index a504adb43e..6ffd837ea7 100644 --- a/src/controllers/accounts/helpers.js +++ b/src/controllers/accounts/helpers.js @@ -134,6 +134,23 @@ helpers.getUserDataByUserSlug = async function (userslug, callerUID, query = {}) return hookData.userData; }; +helpers.getCustomUserFields = async function (userData) { + const keys = await db.getSortedSetRange('user-custom-fields', 0, -1); + const fields = (await db.getObjects(keys.map(k => `user-custom-field:${k}`))).filter(Boolean); + fields.forEach((f) => { + f['select-options'] = f['select-options'].split('\n').filter(Boolean).map( + opt => ({ + value: opt, + selected: opt === userData[f.key], + }) + ); + if (userData[f.key]) { + f.value = validator.escape(String(userData[f.key])); + } + }); + return fields; +}; + function escape(value) { return translator.escape(validator.escape(String(value || ''))); } diff --git a/src/controllers/accounts/profile.js b/src/controllers/accounts/profile.js index 9a2c349916..f99b1f9fcd 100644 --- a/src/controllers/accounts/profile.js +++ b/src/controllers/accounts/profile.js @@ -9,6 +9,7 @@ const categories = require('../../categories'); const plugins = require('../../plugins'); const privileges = require('../../privileges'); const helpers = require('../helpers'); +const accountHelpers = require('./helpers'); const utils = require('../../utils'); const profileController = module.exports; @@ -21,12 +22,13 @@ profileController.get = async function (req, res, next) { await incrementProfileViews(req, userData); - const [latestPosts, bestPosts] = await Promise.all([ + const [latestPosts, bestPosts, customUserFields] = await Promise.all([ getLatestPosts(req.uid, userData), getBestPosts(req.uid, userData), + accountHelpers.getCustomUserFields(userData), posts.parseSignature(userData, req.uid), ]); - + userData.customUserFields = customUserFields; userData.posts = latestPosts; // for backwards compat. userData.latestPosts = latestPosts; userData.bestPosts = bestPosts; diff --git a/src/controllers/admin/users.js b/src/controllers/admin/users.js index a6e25c18ec..b9f844f0c3 100644 --- a/src/controllers/admin/users.js +++ b/src/controllers/admin/users.js @@ -295,7 +295,7 @@ usersController.getCSV = async function (req, res, next) { }); }; -usersController.customFields = async function (req, res, next) { +usersController.customFields = async function (req, res) { const keys = await db.getSortedSetRange('user-custom-fields', 0, -1); const fields = await db.getObjects(keys.map(k => `user-custom-field:${k}`)); fields.forEach((field) => { diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 86ab52b196..f9f06f13bc 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -201,6 +201,7 @@ User.saveCustomFields = async function (socket, fields) { await db.setObjectBulk( fields.map(field => [`user-custom-field:${field.key}`, field]) ); + await user.reloadCustomFieldWhitelist(); }; User.deleteCustomField = async function (socket, key) { diff --git a/src/user/data.js b/src/user/data.js index d0940ff98e..d86a099dfd 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -28,6 +28,8 @@ module.exports = function (User) { 'cover:position', 'groupTitle', 'mutedUntil', 'mutedReason', ]; + let customFieldWhiteList = null; + User.guestData = { uid: 0, username: '[[global:guest]]', @@ -46,6 +48,10 @@ module.exports = function (User) { let iconBackgrounds; + User.reloadCustomFieldWhitelist = async () => { + customFieldWhiteList = await db.getSortedSetRange('user-custom-fields', 0, -1); + }; + User.getUsersFields = async function (uids, fields) { if (!Array.isArray(uids) || !uids.length) { return []; @@ -58,10 +64,12 @@ module.exports = function (User) { ensureRequiredFields(fields, fieldsToRemove); const uniqueUids = _.uniq(uids).filter(uid => uid > 0); - + if (!customFieldWhiteList) { + await User.reloadCustomFieldWhitelist(); + } const results = await plugins.hooks.fire('filter:user.whitelistFields', { uids: uids, - whitelist: fieldWhitelist.slice(), + whitelist: _.uniq(fieldWhitelist.concat(customFieldWhiteList)), }); if (!fields.length) { fields = results.whitelist; diff --git a/src/user/profile.js b/src/user/profile.js index 9d65037bbe..39e278c151 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -17,6 +17,7 @@ module.exports = function (User) { let fields = [ 'username', 'email', 'fullname', 'website', 'location', 'groupTitle', 'birthday', 'signature', 'aboutme', + ...await db.getSortedSetRange('user-custom-fields', 0, -1), ]; if (Array.isArray(extraFields)) { fields = _.uniq(fields.concat(extraFields)); diff --git a/src/views/admin/partials/manage-custom-user-fields-modal.tpl b/src/views/admin/partials/manage-custom-user-fields-modal.tpl index a0f04fb1a9..73984b904b 100644 --- a/src/views/admin/partials/manage-custom-user-fields-modal.tpl +++ b/src/views/admin/partials/manage-custom-user-fields-modal.tpl @@ -3,6 +3,7 @@