diff --git a/public/openapi/read/config.yaml b/public/openapi/read/config.yaml index 946a2bfacd..5d1307a271 100644 --- a/public/openapi/read/config.yaml +++ b/public/openapi/read/config.yaml @@ -137,4 +137,10 @@ get: hideCategoryLastPost: type: boolean enableQuickReply: - type: boolean \ No newline at end of file + type: boolean + iconBackgrounds: + type: array + items: + type: string + description: A valid CSS colour code + example: '#fff' \ No newline at end of file diff --git a/src/user/data.js b/src/user/data.js index b06717e89c..7b80bb1ee1 100644 --- a/src/user/data.js +++ b/src/user/data.js @@ -199,8 +199,13 @@ module.exports = function (User) { // User Icons if (requestedFields.includes('picture') && user.username && parseInt(user.uid, 10) && !meta.config.defaultAvatar) { const iconBackgrounds = await User.getIconBackgrounds(user.uid); + let bgColor = await User.getUserField(user.uid, 'icon:bgColor'); + if (!iconBackgrounds.includes(bgColor)) { + bgColor = Array.prototype.reduce.call(user.username, (cur, next) => cur + next.charCodeAt(), 0); + bgColor = iconBackgrounds[bgColor % iconBackgrounds.length]; + } user['icon:text'] = (user.username[0] || '').toUpperCase(); - user['icon:bgColor'] = await User.getUserField(user.uid, 'icon:bgColor') || iconBackgrounds[Array.prototype.reduce.call(user.username, (cur, next) => cur + next.charCodeAt(), 0) % iconBackgrounds.length]; + user['icon:bgColor'] = bgColor; } if (user.hasOwnProperty('joindate')) { diff --git a/test/user.js b/test/user.js index e87f0923b5..ac5e60e7bc 100644 --- a/test/user.js +++ b/test/user.js @@ -740,6 +740,23 @@ describe('User', () => { }); }); + it('should return an icon text and valid background if username and picture is explicitly requested', async () => { + const payload = await User.getUserFields(testUid, ['username', 'picture']); + const validBackgrounds = await User.getIconBackgrounds(testUid); + assert.strictEqual(payload['icon:text'], userData.username.slice(0, 1).toUpperCase()); + assert(payload['icon:bgColor']); + assert(validBackgrounds.includes(payload['icon:bgColor'])); + }); + + it('should return a valid background, even if an invalid background colour is set', async () => { + await User.setUserField(testUid, 'icon:bgColor', 'teal'); + const payload = await User.getUserFields(testUid, ['username', 'picture']); + const validBackgrounds = await User.getIconBackgrounds(testUid); + + assert(payload['icon:bgColor']); + assert(validBackgrounds.includes(payload['icon:bgColor'])); + }); + it('should return private data if field is whitelisted', (done) => { function filterMethod(data, callback) { data.whitelist.push('another_secret');