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 @@