From 1b8483f12d9a29e0e4ed9d2e8d464f2c1bac8271 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sun, 21 Jan 2018 20:56:46 +0100 Subject: [PATCH 01/23] Add user settings / preferences API endpoint #8694 --- packages/rocketchat-api/server/v1/users.js | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 234e73e83ac6..6f11d33d3e3a 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -270,3 +270,64 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { return data ? RocketChat.API.v1.success({data}) : RocketChat.API.v1.unauthorized(); } }); + +RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { + get() { + const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); + if (user.settings) { + let preferences = user.settings.preferences + preferences.language = user.language + + return RocketChat.API.v1.success({ + preferences: preferences + }); + } else { + return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); + } + } +}); + +RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { + post() { + check(this.bodyParams, { + userId: String, + data: Match.ObjectIncluding({ + newRoomNotification: Match.Maybe(String), + newMessageNotification: Match.Maybe(String), + useEmojis: Match.Maybe(Boolean), + convertAsciiEmoji: Match.Maybe(Boolean), + saveMobileBandwidth: Match.Maybe(Boolean), + collapseMediaByDefault: Match.Maybe(Boolean), + autoImageLoad: Match.Maybe(Boolean), + emailNotificationMode: Match.Maybe(String), + roomsListExhibitionMode: Match.Maybe(String), + unreadAlert: Match.Maybe(Boolean), + notificationsSoundVolume: Match.Maybe(Number), + desktopNotifications: Match.Maybe(String), + mobileNotifications: Match.Maybe(String), + enableAutoAway: Match.Maybe(Boolean), + highlights: Match.Maybe(Array), + desktopNotificationDuration: Match.Maybe(Number), + viewMode: Match.Maybe(Number), + hideUsernames: Match.Maybe(Boolean), + hideRoles: Match.Maybe(Boolean), + hideAvatars: Match.Maybe(Boolean), + hideFlexTab: Match.Maybe(Boolean), + sendOnEnter: Match.Maybe(String), + roomCounterSidebar: Match.Maybe(Boolean), + language: Match.Maybe(String) + }) + }); + + if (this.bodyParams.data.language) { + const language = this.bodyParams.data.language; + delete this.bodyParams.data.language; + } + + const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data }); + + Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); + + return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: preferences }) }); + } +}); From f30d581e6a7d3969cf5c45ad348a6353fcabdef9 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sun, 21 Jan 2018 21:11:33 +0100 Subject: [PATCH 02/23] Thx coday bot: missing semicolons --- packages/rocketchat-api/server/v1/users.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 6f11d33d3e3a..bd4ab3ea3221 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -275,11 +275,11 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); if (user.settings) { - let preferences = user.settings.preferences - preferences.language = user.language + let preferences = user.settings.preferences; + preferences.language = user.language; return RocketChat.API.v1.success({ - preferences: preferences + preferences: preferences; }); } else { return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); @@ -322,9 +322,11 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { if (this.bodyParams.data.language) { const language = this.bodyParams.data.language; delete this.bodyParams.data.language; + const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data, language: language }); + } else { + const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data }); } - const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data }); Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); From 28b299334081393a6be73faa95e964ac228b0164 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sun, 21 Jan 2018 21:12:34 +0100 Subject: [PATCH 03/23] Thx coday bot: property shorthand expected --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index bd4ab3ea3221..e4a0a80b8c5d 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -279,7 +279,7 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { preferences.language = user.language; return RocketChat.API.v1.success({ - preferences: preferences; + preferences; }); } else { return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); From c8f843b23bab09af4f3ce1fb53053d61f40f7f1a Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sun, 21 Jan 2018 21:15:47 +0100 Subject: [PATCH 04/23] unneded ; --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index e4a0a80b8c5d..d4cae16b1a93 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -279,7 +279,7 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { preferences.language = user.language; return RocketChat.API.v1.success({ - preferences; + preferences }); } else { return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); From b2c75b4d400328f37b96faa6ab5c76e3a14a932a Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sun, 21 Jan 2018 21:22:03 +0100 Subject: [PATCH 05/23] making tests happy --- packages/rocketchat-api/server/v1/users.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index d4cae16b1a93..039ee598046f 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -275,8 +275,8 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); if (user.settings) { - let preferences = user.settings.preferences; - preferences.language = user.language; + const preferences = user.settings.preferences; + preferences['language'] = user.language; return RocketChat.API.v1.success({ preferences From c5c204284a4428f27308436daf40eeab549b479a Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:09:12 +0100 Subject: [PATCH 06/23] updating mongo --- packages/rocketchat-api/server/v1/users.js | 10 +++++----- packages/rocketchat-lib/server/functions/saveUser.js | 10 +++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 039ee598046f..cc5d6327f01d 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -271,7 +271,7 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { } }); -RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { +RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: false }, { get() { const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); if (user.settings) { @@ -319,15 +319,15 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { }) }); + let preferences if (this.bodyParams.data.language) { - const language = this.bodyParams.data.language; + let language = this.bodyParams.data.language; delete this.bodyParams.data.language; - const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data, language: language }); + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: this.language }); } else { - const preferences = _.extend({ _id: this.bodyParams.userId }, { preferences: this.bodyParams.data }); + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }}); } - Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: preferences }) }); diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js index ed727b385fa5..7ccf85dcbdda 100644 --- a/packages/rocketchat-lib/server/functions/saveUser.js +++ b/packages/rocketchat-lib/server/functions/saveUser.js @@ -72,7 +72,8 @@ RocketChat.saveUser = function(userId, userData) { const updateUser = { $set: { name: userData.name, - roles: userData.roles || ['user'] + roles: userData.roles || ['user'], + settings: userData.settings } }; @@ -163,6 +164,13 @@ RocketChat.saveUser = function(userId, userData) { updateUser.$set.roles = userData.roles; } + if (userData.settings) { + updateUser.$set.settings = { preferences: {} }; + for (var key in userData.settings.preferences) { + updateUser.$set.settings.preferences[key] = userData.settings.preferences[key]; + } + } + if (typeof userData.requirePasswordChange !== 'undefined') { updateUser.$set.requirePasswordChange = userData.requirePasswordChange; } From 01f499fe98e879052872087894ab1a12e46eb702 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:14:02 +0100 Subject: [PATCH 07/23] missing semicolon --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index cc5d6327f01d..52db1a85da16 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -319,7 +319,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { }) }); - let preferences + let preferences; if (this.bodyParams.data.language) { let language = this.bodyParams.data.language; delete this.bodyParams.data.language; From e0c2b8fa473cb89f01c930f62a8619e5954abb2c Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:19:36 +0100 Subject: [PATCH 08/23] formatting --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 52db1a85da16..18b65f3fb04a 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -321,7 +321,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { let preferences; if (this.bodyParams.data.language) { - let language = this.bodyParams.data.language; + let language = this.bodyParams.data.language; delete this.bodyParams.data.language; preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: this.language }); } else { From c99bfcc803f36ee9ceab15738456288fd5a61c88 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:23:13 +0100 Subject: [PATCH 09/23] formatting --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 18b65f3fb04a..a3ccf4f12c92 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -323,7 +323,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { if (this.bodyParams.data.language) { let language = this.bodyParams.data.language; delete this.bodyParams.data.language; - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: this.language }); + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: language }); } else { preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }}); } From c7972144c261f88fadb936e7724879c9fcc6ab67 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:27:46 +0100 Subject: [PATCH 10/23] formatting --- packages/rocketchat-api/server/v1/users.js | 2 +- packages/rocketchat-lib/server/functions/saveUser.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index a3ccf4f12c92..6e7fdada41e5 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -321,7 +321,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { let preferences; if (this.bodyParams.data.language) { - let language = this.bodyParams.data.language; + const language = this.bodyParams.data.language; delete this.bodyParams.data.language; preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: language }); } else { diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js index 7ccf85dcbdda..a2cb5134798d 100644 --- a/packages/rocketchat-lib/server/functions/saveUser.js +++ b/packages/rocketchat-lib/server/functions/saveUser.js @@ -166,8 +166,10 @@ RocketChat.saveUser = function(userId, userData) { if (userData.settings) { updateUser.$set.settings = { preferences: {} }; - for (var key in userData.settings.preferences) { - updateUser.$set.settings.preferences[key] = userData.settings.preferences[key]; + if (userData.settings.preferences) { + for (let key in userData.settings.preferences) { + updateUser.$set.settings.preferences[key] = userData.settings.preferences[key]; + } } } From 4cc4c48fa6e9be7f5a766eff2ec343fdade793e3 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Mon, 22 Jan 2018 11:44:34 +0100 Subject: [PATCH 11/23] formatting --- packages/rocketchat-api/server/v1/users.js | 2 +- packages/rocketchat-lib/server/functions/saveUser.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 6e7fdada41e5..e4c4c58e1ed5 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -323,7 +323,7 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { if (this.bodyParams.data.language) { const language = this.bodyParams.data.language; delete this.bodyParams.data.language; - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language: language }); + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language }); } else { preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }}); } diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js index a2cb5134798d..e5c7dd10af5e 100644 --- a/packages/rocketchat-lib/server/functions/saveUser.js +++ b/packages/rocketchat-lib/server/functions/saveUser.js @@ -166,8 +166,8 @@ RocketChat.saveUser = function(userId, userData) { if (userData.settings) { updateUser.$set.settings = { preferences: {} }; - if (userData.settings.preferences) { - for (let key in userData.settings.preferences) { + for (const key in userData.settings.preferences) { + if (userData.settings.preferences[key]) { updateUser.$set.settings.preferences[key] = userData.settings.preferences[key]; } } From d0d7f594111f99f48ed639798663dc1b7bbd3eb9 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Tue, 23 Jan 2018 15:26:43 +0100 Subject: [PATCH 12/23] users.getPreferences always requires authentication --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index e4c4c58e1ed5..43822762a7a2 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -271,7 +271,7 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { } }); -RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: false }, { +RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); if (user.settings) { From e336ddba3eea55c8909a037537d68e19bf05d1ff Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 00:49:47 +0100 Subject: [PATCH 13/23] going by single quotes --- packages/rocketchat-api/server/v1/users.js | 659 +++++++++------------ 1 file changed, 292 insertions(+), 367 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 856049ccebad..85772c43be56 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -1,409 +1,338 @@ -import _ from "underscore"; -import Busboy from "busboy"; - -RocketChat.API.v1.addRoute( - "users.create", - { authRequired: true }, - { - post() { - check(this.bodyParams, { - email: String, - name: String, - password: String, - username: String, - active: Match.Maybe(Boolean), - roles: Match.Maybe(Array), - joinDefaultChannels: Match.Maybe(Boolean), - requirePasswordChange: Match.Maybe(Boolean), - sendWelcomeEmail: Match.Maybe(Boolean), - verified: Match.Maybe(Boolean), - customFields: Match.Maybe(Object) - }); - - //New change made by pull request #5152 - if (typeof this.bodyParams.joinDefaultChannels === "undefined") { - this.bodyParams.joinDefaultChannels = true; - } - - if (this.bodyParams.customFields) { - RocketChat.validateCustomFields(this.bodyParams.customFields); - } - - const newUserId = RocketChat.saveUser(this.userId, this.bodyParams); +import _ from 'underscore'; +import Busboy from 'busboy'; + +RocketChat.API.v1.addRoute('users.create', { authRequired: true }, { + post() { + check(this.bodyParams, { + email: String, + name: String, + password: String, + username: String, + active: Match.Maybe(Boolean), + roles: Match.Maybe(Array), + joinDefaultChannels: Match.Maybe(Boolean), + requirePasswordChange: Match.Maybe(Boolean), + sendWelcomeEmail: Match.Maybe(Boolean), + verified: Match.Maybe(Boolean), + customFields: Match.Maybe(Object) + }); + + //New change made by pull request #5152 + if (typeof this.bodyParams.joinDefaultChannels === 'undefined') { + this.bodyParams.joinDefaultChannels = true; + } - if (this.bodyParams.customFields) { - RocketChat.saveCustomFieldsWithoutValidation(newUserId, this.bodyParams.customFields); - } + if (this.bodyParams.customFields) { + RocketChat.validateCustomFields(this.bodyParams.customFields); + } - if (typeof this.bodyParams.active !== "undefined") { - Meteor.runAsUser(this.userId, () => { - Meteor.call("setUserActiveStatus", newUserId, this.bodyParams.active); - }); - } + const newUserId = RocketChat.saveUser(this.userId, this.bodyParams); - return RocketChat.API.v1.success({ - user: RocketChat.models.Users.findOneById(newUserId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) - }); + if (this.bodyParams.customFields) { + RocketChat.saveCustomFieldsWithoutValidation(newUserId, this.bodyParams.customFields); } - } -); - -RocketChat.API.v1.addRoute( - "users.delete", - { authRequired: true }, - { - post() { - if (!RocketChat.authz.hasPermission(this.userId, "delete-user")) { - return RocketChat.API.v1.unauthorized(); - } - const user = this.getUserFromParams(); + if (typeof this.bodyParams.active !== 'undefined') { Meteor.runAsUser(this.userId, () => { - Meteor.call("deleteUser", user._id); + Meteor.call('setUserActiveStatus', newUserId, this.bodyParams.active); }); - - return RocketChat.API.v1.success(); } + + return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(newUserId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) }); } -); - -RocketChat.API.v1.addRoute( - "users.getAvatar", - { authRequired: false }, - { - get() { - const user = this.getUserFromParams(); - - const url = RocketChat.getURL(`/avatar/${user.username}`, { cdn: false, full: true }); - this.response.setHeader("Location", url); - - return { - statusCode: 307, - body: url - }; +}); + +RocketChat.API.v1.addRoute('users.delete', { authRequired: true }, { + post() { + if (!RocketChat.authz.hasPermission(this.userId, 'delete-user')) { + return RocketChat.API.v1.unauthorized(); } - } -); - -RocketChat.API.v1.addRoute( - "users.getPresence", - { authRequired: true }, - { - get() { - if (this.isUserFromParams()) { - const user = RocketChat.models.Users.findOneById(this.userId); - return RocketChat.API.v1.success({ - presence: user.status, - connectionStatus: user.statusConnection, - lastLogin: user.lastLogin - }); - } - const user = this.getUserFromParams(); + const user = this.getUserFromParams(); - return RocketChat.API.v1.success({ - presence: user.status - }); - } + Meteor.runAsUser(this.userId, () => { + Meteor.call('deleteUser', user._id); + }); + + return RocketChat.API.v1.success(); } -); +}); -RocketChat.API.v1.addRoute( - "users.info", - { authRequired: true }, - { - get() { - const user = this.getUserFromParams(); +RocketChat.API.v1.addRoute('users.getAvatar', { authRequired: false }, { + get() { + const user = this.getUserFromParams(); - let result; - Meteor.runAsUser(this.userId, () => { - result = Meteor.call("getFullUserData", { filter: user.username, limit: 1 }); - }); + const url = RocketChat.getURL(`/avatar/${ user.username }`, { cdn: false, full: true }); + this.response.setHeader('Location', url); - if (!result || result.length !== 1) { - return RocketChat.API.v1.failure(`Failed to get the user data for the userId of "${user._id}".`); - } + return { + statusCode: 307, + body: url + }; + } +}); +RocketChat.API.v1.addRoute('users.getPresence', { authRequired: true }, { + get() { + if (this.isUserFromParams()) { + const user = RocketChat.models.Users.findOneById(this.userId); return RocketChat.API.v1.success({ - user: result[0] + presence: user.status, + connectionStatus: user.statusConnection, + lastLogin: user.lastLogin }); } + + const user = this.getUserFromParams(); + + return RocketChat.API.v1.success({ + presence: user.status + }); } -); - -RocketChat.API.v1.addRoute( - "users.list", - { authRequired: true }, - { - get() { - if (!RocketChat.authz.hasPermission(this.userId, "view-d-room")) { - return RocketChat.API.v1.unauthorized(); - } +}); - const { offset, count } = this.getPaginationItems(); - const { sort, fields, query } = this.parseJsonQuery(); +RocketChat.API.v1.addRoute('users.info', { authRequired: true }, { + get() { + const user = this.getUserFromParams(); - const users = RocketChat.models.Users.find(query, { - sort: sort ? sort : { username: 1 }, - skip: offset, - limit: count, - fields - }).fetch(); + let result; + Meteor.runAsUser(this.userId, () => { + result = Meteor.call('getFullUserData', { filter: user.username, limit: 1 }); + }); - return RocketChat.API.v1.success({ - users, - count: users.length, - offset, - total: RocketChat.models.Users.find(query).count() - }); + if (!result || result.length !== 1) { + return RocketChat.API.v1.failure(`Failed to get the user data for the userId of "${ user._id }".`); } - } -); - -RocketChat.API.v1.addRoute( - "users.register", - { authRequired: false }, - { - post() { - if (this.userId) { - return RocketChat.API.v1.failure("Logged in users can not register again."); - } - //We set their username here, so require it - //The `registerUser` checks for the other requirements - check( - this.bodyParams, - Match.ObjectIncluding({ - username: String - }) - ); + return RocketChat.API.v1.success({ + user: result[0] + }); + } +}); - //Register the user - const userId = Meteor.call("registerUser", this.bodyParams); +RocketChat.API.v1.addRoute('users.list', { authRequired: true }, { + get() { + if (!RocketChat.authz.hasPermission(this.userId, 'view-d-room')) { + return RocketChat.API.v1.unauthorized(); + } - //Now set their username - Meteor.runAsUser(userId, () => Meteor.call("setUsername", this.bodyParams.username)); + const { offset, count } = this.getPaginationItems(); + const { sort, fields, query } = this.parseJsonQuery(); + + const users = RocketChat.models.Users.find(query, { + sort: sort ? sort : { username: 1 }, + skip: offset, + limit: count, + fields + }).fetch(); + + return RocketChat.API.v1.success({ + users, + count: users.length, + offset, + total: RocketChat.models.Users.find(query).count() + }); + } +}); - return RocketChat.API.v1.success({ - user: RocketChat.models.Users.findOneById(userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) - }); +RocketChat.API.v1.addRoute('users.register', { authRequired: false }, { + post() { + if (this.userId) { + return RocketChat.API.v1.failure('Logged in users can not register again.'); } - } -); - -RocketChat.API.v1.addRoute( - "users.resetAvatar", - { authRequired: true }, - { - post() { - const user = this.getUserFromParams(); - - if (user._id === this.userId) { - Meteor.runAsUser(this.userId, () => Meteor.call("resetAvatar")); - } else if (RocketChat.authz.hasPermission(this.userId, "edit-other-user-info")) { - Meteor.runAsUser(user._id, () => Meteor.call("resetAvatar")); - } else { - return RocketChat.API.v1.unauthorized(); - } - return RocketChat.API.v1.success(); + //We set their username here, so require it + //The `registerUser` checks for the other requirements + check(this.bodyParams, Match.ObjectIncluding({ + username: String + })); + + //Register the user + const userId = Meteor.call('registerUser', this.bodyParams); + + //Now set their username + Meteor.runAsUser(userId, () => Meteor.call('setUsername', this.bodyParams.username)); + + return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) }); + } +}); + +RocketChat.API.v1.addRoute('users.resetAvatar', { authRequired: true }, { + post() { + const user = this.getUserFromParams(); + + if (user._id === this.userId) { + Meteor.runAsUser(this.userId, () => Meteor.call('resetAvatar')); + } else if (RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) { + Meteor.runAsUser(user._id, () => Meteor.call('resetAvatar')); + } else { + return RocketChat.API.v1.unauthorized(); } + + return RocketChat.API.v1.success(); } -); - -RocketChat.API.v1.addRoute( - "users.setAvatar", - { authRequired: true }, - { - post() { - check( - this.bodyParams, - Match.ObjectIncluding({ - avatarUrl: Match.Maybe(String), - userId: Match.Maybe(String), - username: Match.Maybe(String) - }) - ); - - let user; - if (this.isUserFromParams()) { - user = Meteor.users.findOne(this.userId); - } else if (RocketChat.authz.hasPermission(this.userId, "edit-other-user-info")) { - user = this.getUserFromParams(); +}); + +RocketChat.API.v1.addRoute('users.setAvatar', { authRequired: true }, { + post() { + check(this.bodyParams, Match.ObjectIncluding({ + avatarUrl: Match.Maybe(String), + userId: Match.Maybe(String), + username: Match.Maybe(String) + })); + + let user; + if (this.isUserFromParams()) { + user = Meteor.users.findOne(this.userId); + } else if (RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) { + user = this.getUserFromParams(); + } else { + return RocketChat.API.v1.unauthorized(); + } + + Meteor.runAsUser(user._id, () => { + if (this.bodyParams.avatarUrl) { + RocketChat.setUserAvatar(user, this.bodyParams.avatarUrl, '', 'url'); } else { - return RocketChat.API.v1.unauthorized(); + const busboy = new Busboy({ headers: this.request.headers }); + + Meteor.wrapAsync((callback) => { + busboy.on('file', Meteor.bindEnvironment((fieldname, file, filename, encoding, mimetype) => { + if (fieldname !== 'image') { + return callback(new Meteor.Error('invalid-field')); + } + + const imageData = []; + file.on('data', Meteor.bindEnvironment((data) => { + imageData.push(data); + })); + + file.on('end', Meteor.bindEnvironment(() => { + RocketChat.setUserAvatar(user, Buffer.concat(imageData), mimetype, 'rest'); + callback(); + })); + + })); + this.request.pipe(busboy); + })(); } + }); - Meteor.runAsUser(user._id, () => { - if (this.bodyParams.avatarUrl) { - RocketChat.setUserAvatar(user, this.bodyParams.avatarUrl, "", "url"); - } else { - const busboy = new Busboy({ headers: this.request.headers }); - - Meteor.wrapAsync(callback => { - busboy.on( - "file", - Meteor.bindEnvironment((fieldname, file, filename, encoding, mimetype) => { - if (fieldname !== "image") { - return callback(new Meteor.Error("invalid-field")); - } - - const imageData = []; - file.on( - "data", - Meteor.bindEnvironment(data => { - imageData.push(data); - }) - ); - - file.on( - "end", - Meteor.bindEnvironment(() => { - RocketChat.setUserAvatar(user, Buffer.concat(imageData), mimetype, "rest"); - callback(); - }) - ); - }) - ); - this.request.pipe(busboy); - })(); - } - }); - - return RocketChat.API.v1.success(); - } + return RocketChat.API.v1.success(); } -); - -RocketChat.API.v1.addRoute( - "users.update", - { authRequired: true }, - { - post() { - check(this.bodyParams, { - userId: String, - data: Match.ObjectIncluding({ - email: Match.Maybe(String), - name: Match.Maybe(String), - password: Match.Maybe(String), - username: Match.Maybe(String), - active: Match.Maybe(Boolean), - roles: Match.Maybe(Array), - joinDefaultChannels: Match.Maybe(Boolean), - requirePasswordChange: Match.Maybe(Boolean), - sendWelcomeEmail: Match.Maybe(Boolean), - verified: Match.Maybe(Boolean), - customFields: Match.Maybe(Object) - }) - }); +}); + +RocketChat.API.v1.addRoute('users.update', { authRequired: true }, { + post() { + check(this.bodyParams, { + userId: String, + data: Match.ObjectIncluding({ + email: Match.Maybe(String), + name: Match.Maybe(String), + password: Match.Maybe(String), + username: Match.Maybe(String), + active: Match.Maybe(Boolean), + roles: Match.Maybe(Array), + joinDefaultChannels: Match.Maybe(Boolean), + requirePasswordChange: Match.Maybe(Boolean), + sendWelcomeEmail: Match.Maybe(Boolean), + verified: Match.Maybe(Boolean), + customFields: Match.Maybe(Object) + }) + }); - const userData = _.extend({ _id: this.bodyParams.userId }, this.bodyParams.data); + const userData = _.extend({ _id: this.bodyParams.userId }, this.bodyParams.data); - Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, userData)); + Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, userData)); - if (this.bodyParams.data.customFields) { - RocketChat.saveCustomFields(this.bodyParams.userId, this.bodyParams.data.customFields); - } - - if (typeof this.bodyParams.data.active !== "undefined") { - Meteor.runAsUser(this.userId, () => { - Meteor.call("setUserActiveStatus", this.bodyParams.userId, this.bodyParams.data.active); - }); - } + if (this.bodyParams.data.customFields) { + RocketChat.saveCustomFields(this.bodyParams.userId, this.bodyParams.data.customFields); + } - return RocketChat.API.v1.success({ - user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) + if (typeof this.bodyParams.data.active !== 'undefined') { + Meteor.runAsUser(this.userId, () => { + Meteor.call('setUserActiveStatus', this.bodyParams.userId, this.bodyParams.data.active); }); } + + return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: RocketChat.API.v1.defaultFieldsToExclude }) }); } -); - -RocketChat.API.v1.addRoute( - "users.createToken", - { authRequired: true }, - { - post() { - const user = this.getUserFromParams(); - let data; - Meteor.runAsUser(this.userId, () => { - data = Meteor.call("createToken", user._id); +}); + +RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { + post() { + const user = this.getUserFromParams(); + let data; + Meteor.runAsUser(this.userId, () => { + data = Meteor.call('createToken', user._id); + }); + return data ? RocketChat.API.v1.success({data}) : RocketChat.API.v1.unauthorized(); + } +}); + +RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { + get() { + const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); + if (user.settings) { + const preferences = user.settings.preferences; + preferences['language'] = user.language; + + return RocketChat.API.v1.success({ + preferences }); - return data ? RocketChat.API.v1.success({ data }) : RocketChat.API.v1.unauthorized(); + } else { + return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); } } -); - -RocketChat.API.v1.addRoute( - "users.getPreferences", - { authRequired: true }, - { - get() { - const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); - if (user.settings) { - const preferences = user.settings.preferences; - preferences["language"] = user.language; - - return RocketChat.API.v1.success({ - preferences - }); - } else { - return RocketChat.API.v1.failure(TAPi18n.__("Accounts_Default_User_Preferences").toUpperCase()); - } +}); + +RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { + post() { + check(this.bodyParams, { + userId: String, + data: Match.ObjectIncluding({ + newRoomNotification: Match.Maybe(String), + newMessageNotification: Match.Maybe(String), + useEmojis: Match.Maybe(Boolean), + convertAsciiEmoji: Match.Maybe(Boolean), + saveMobileBandwidth: Match.Maybe(Boolean), + collapseMediaByDefault: Match.Maybe(Boolean), + autoImageLoad: Match.Maybe(Boolean), + emailNotificationMode: Match.Maybe(String), + roomsListExhibitionMode: Match.Maybe(String), + unreadAlert: Match.Maybe(Boolean), + notificationsSoundVolume: Match.Maybe(Number), + desktopNotifications: Match.Maybe(String), + mobileNotifications: Match.Maybe(String), + enableAutoAway: Match.Maybe(Boolean), + highlights: Match.Maybe(Array), + desktopNotificationDuration: Match.Maybe(Number), + viewMode: Match.Maybe(Number), + hideUsernames: Match.Maybe(Boolean), + hideRoles: Match.Maybe(Boolean), + hideAvatars: Match.Maybe(Boolean), + hideFlexTab: Match.Maybe(Boolean), + sendOnEnter: Match.Maybe(String), + roomCounterSidebar: Match.Maybe(Boolean), + language: Match.Maybe(String) + }) + }); + + let preferences; + if (this.bodyParams.data.language) { + const language = this.bodyParams.data.language; + delete this.bodyParams.data.language; + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language }); + } else { + preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }}); } - } -); - -RocketChat.API.v1.addRoute( - "users.setPreferences", - { authRequired: true }, - { - post() { - check(this.bodyParams, { - userId: String, - data: Match.ObjectIncluding({ - newRoomNotification: Match.Maybe(String), - newMessageNotification: Match.Maybe(String), - useEmojis: Match.Maybe(Boolean), - convertAsciiEmoji: Match.Maybe(Boolean), - saveMobileBandwidth: Match.Maybe(Boolean), - collapseMediaByDefault: Match.Maybe(Boolean), - autoImageLoad: Match.Maybe(Boolean), - emailNotificationMode: Match.Maybe(String), - roomsListExhibitionMode: Match.Maybe(String), - unreadAlert: Match.Maybe(Boolean), - notificationsSoundVolume: Match.Maybe(Number), - desktopNotifications: Match.Maybe(String), - mobileNotifications: Match.Maybe(String), - enableAutoAway: Match.Maybe(Boolean), - highlights: Match.Maybe(Array), - desktopNotificationDuration: Match.Maybe(Number), - viewMode: Match.Maybe(Number), - hideUsernames: Match.Maybe(Boolean), - hideRoles: Match.Maybe(Boolean), - hideAvatars: Match.Maybe(Boolean), - hideFlexTab: Match.Maybe(Boolean), - sendOnEnter: Match.Maybe(String), - roomCounterSidebar: Match.Maybe(Boolean), - language: Match.Maybe(String) - }) - }); - let preferences; - if (this.bodyParams.data.language) { - const language = this.bodyParams.data.language; - delete this.bodyParams.data.language; - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language }); - } else { - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data } }); - } + Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); - Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); - - return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: preferences }) }); - } + return RocketChat.API.v1.success({ user: RocketChat.models.Users.findOneById(this.bodyParams.userId, { fields: preferences }) }); } -); +}); /** This API returns the logged user roles. @@ -411,20 +340,16 @@ RocketChat.API.v1.addRoute( Method: GET Route: api/v1/user.roles */ -RocketChat.API.v1.addRoute( - "user.roles", - { authRequired: true }, - { - get() { - let currentUserRoles = {}; +RocketChat.API.v1.addRoute('user.roles', { authRequired: true }, { + get() { + let currentUserRoles = {}; - const result = Meteor.runAsUser(this.userId, () => Meteor.call("getUserRoles")); + const result = Meteor.runAsUser(this.userId, () => Meteor.call('getUserRoles')); - if (Array.isArray(result) && result.length > 0) { - currentUserRoles = result[0]; - } - - return RocketChat.API.v1.success(currentUserRoles); + if (Array.isArray(result) && result.length > 0) { + currentUserRoles = result[0]; } + + return RocketChat.API.v1.success(currentUserRoles); } -); +}); From cee2461cf36e5a8baadb91374b0f9f6ab599b91d Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 11:02:33 +0100 Subject: [PATCH 14/23] default to the user registered if none is passed --- packages/rocketchat-api/server/v1/users.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 85772c43be56..d2a6ecf0b5e7 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -290,7 +290,7 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { post() { check(this.bodyParams, { - userId: String, + userId: Match.Maybe(String), data: Match.ObjectIncluding({ newRoomNotification: Match.Maybe(String), newMessageNotification: Match.Maybe(String), @@ -320,12 +320,13 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { }); let preferences; + let userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId; if (this.bodyParams.data.language) { const language = this.bodyParams.data.language; delete this.bodyParams.data.language; - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }, language }); + preferences = _.extend({ _id: userId, settings: { preferences: this.bodyParams.data }, language }); } else { - preferences = _.extend({ _id: this.bodyParams.userId, settings: { preferences: this.bodyParams.data }}); + preferences = _.extend({ _id: userId, settings: { preferences: this.bodyParams.data }}); } Meteor.runAsUser(this.userId, () => RocketChat.saveUser(this.userId, preferences)); From b3295a5fd461bb8c689b9ff9d78b603ab76e3189 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 11:10:45 +0100 Subject: [PATCH 15/23] adding new params requested by @karlprieb --- packages/rocketchat-api/server/v1/users.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index d2a6ecf0b5e7..6aaae323c3a1 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -315,12 +315,18 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { hideFlexTab: Match.Maybe(Boolean), sendOnEnter: Match.Maybe(String), roomCounterSidebar: Match.Maybe(Boolean), - language: Match.Maybe(String) + language: Match.Maybe(String), + sidebarShowFavorites: Match.Optional(Boolean), + sidebarShowUnread: Match.Optional(Boolean), + sidebarSortby: Match.Optional(String), + sidebarViewMode: Match.Optional(String), + sidebarHideAvatar: Match.Optional(Boolean), + mergeChannels: Match.Optional(Boolean) }) }); let preferences; - let userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId; + const userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId; if (this.bodyParams.data.language) { const language = this.bodyParams.data.language; delete this.bodyParams.data.language; From f203b276e322b1280b2979bf96e2ee8fa63ab361 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 15:12:58 +0100 Subject: [PATCH 16/23] get own preferences only --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 6aaae323c3a1..1255deaf1f11 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -273,7 +273,7 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { - const user = this.isUserFromParams() ? RocketChat.models.Users.findOneById(this.userId) : this.getUserFromParams(); + const user = this.getUserFromParams(); if (user.settings) { const preferences = user.settings.preferences; preferences['language'] = user.language; From 9adf9fc344c0dd00c620312016e0fc20affc0785 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 19:42:32 +0100 Subject: [PATCH 17/23] adding muteFocusedConversations param on @karlprieb request --- packages/rocketchat-api/server/v1/users.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 1255deaf1f11..edfd86180c68 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -321,7 +321,8 @@ RocketChat.API.v1.addRoute('users.setPreferences', { authRequired: true }, { sidebarSortby: Match.Optional(String), sidebarViewMode: Match.Optional(String), sidebarHideAvatar: Match.Optional(Boolean), - mergeChannels: Match.Optional(Boolean) + mergeChannels: Match.Optional(Boolean), + muteFocusedConversations: Match.Optional(Boolean) }) }); From 2db5a9447cc42b9cb20c588122f8cb8ba175905f Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Fri, 16 Feb 2018 21:05:46 +0100 Subject: [PATCH 18/23] giving a more sensible error message --- packages/rocketchat-api/server/v1/users.js | 2 +- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index edfd86180c68..8f640f151738 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -282,7 +282,7 @@ RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { preferences }); } else { - return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences').toUpperCase()); + return RocketChat.API.v1.failure(TAPi18n.__('Accounts_Default_User_Preferences_not_available').toUpperCase()); } } }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 9b728820ef71..a1d7677ddf14 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -45,6 +45,7 @@ "Accounts_Default_User_Preferences_audioNotifications": "Audio Notifications Default Alert", "Accounts_Default_User_Preferences_desktopNotifications": "Desktop Notifications Default Alert", "Accounts_Default_User_Preferences_mobileNotifications": "Mobile Notifications Default Alert", + "Accounts_Default_User_Preferences_not_available": "Failed to retrieve User Preferences because of they haven't been set up by the user yet", "Accounts_denyUnverifiedEmail": "Deny unverified email", "Accounts_EmailVerification": "Email Verification", "Accounts_EmailVerification_Description": "Make sure you have correct SMTP settings to use this feature", From e36f95d4c6f51d62209d7cd6f10b630f96e770f8 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sat, 17 Feb 2018 16:21:06 +0100 Subject: [PATCH 19/23] replacing this.getUserFromParams() for this.userId, due to legit security concerns --- packages/rocketchat-api/server/v1/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 8f640f151738..2c88eaf80139 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -273,7 +273,7 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { - const user = this.getUserFromParams(); + const user = this.userId; if (user.settings) { const preferences = user.settings.preferences; preferences['language'] = user.language; From c9641167e46dc168edab120c129bd3587e818862 Mon Sep 17 00:00:00 2001 From: Joaquin GT Date: Sat, 17 Feb 2018 16:27:03 +0100 Subject: [PATCH 20/23] fixing typo on i18n --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index a1d7677ddf14..970d77e15f1c 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -45,7 +45,7 @@ "Accounts_Default_User_Preferences_audioNotifications": "Audio Notifications Default Alert", "Accounts_Default_User_Preferences_desktopNotifications": "Desktop Notifications Default Alert", "Accounts_Default_User_Preferences_mobileNotifications": "Mobile Notifications Default Alert", - "Accounts_Default_User_Preferences_not_available": "Failed to retrieve User Preferences because of they haven't been set up by the user yet", + "Accounts_Default_User_Preferences_not_available": "Failed to retrieve User Preferences because they haven't been set up by the user yet", "Accounts_denyUnverifiedEmail": "Deny unverified email", "Accounts_EmailVerification": "Email Verification", "Accounts_EmailVerification_Description": "Make sure you have correct SMTP settings to use this feature", From 19a8ad6ea3a889ca2c75271466b25ad273401d11 Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Mon, 19 Feb 2018 23:04:06 -0300 Subject: [PATCH 21/23] added findOne call to retrieve the user, and remove verification which didn't allow false values to be saved --- packages/rocketchat-api/server/v1/users.js | 2 +- packages/rocketchat-lib/server/functions/saveUser.js | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/rocketchat-api/server/v1/users.js b/packages/rocketchat-api/server/v1/users.js index 2c88eaf80139..ab92925e3c39 100644 --- a/packages/rocketchat-api/server/v1/users.js +++ b/packages/rocketchat-api/server/v1/users.js @@ -273,7 +273,7 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, { RocketChat.API.v1.addRoute('users.getPreferences', { authRequired: true }, { get() { - const user = this.userId; + const user = RocketChat.models.Users.findOneById(this.userId); if (user.settings) { const preferences = user.settings.preferences; preferences['language'] = user.language; diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js index e5c7dd10af5e..9f45ed155c33 100644 --- a/packages/rocketchat-lib/server/functions/saveUser.js +++ b/packages/rocketchat-lib/server/functions/saveUser.js @@ -165,12 +165,7 @@ RocketChat.saveUser = function(userId, userData) { } if (userData.settings) { - updateUser.$set.settings = { preferences: {} }; - for (const key in userData.settings.preferences) { - if (userData.settings.preferences[key]) { - updateUser.$set.settings.preferences[key] = userData.settings.preferences[key]; - } - } + updateUser.$set.settings = { preferences: userData.settings.preferences }; } if (typeof userData.requirePasswordChange !== 'undefined') { From d81d1f7c04325b8142569b7054e79131769abfcb Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Mon, 19 Feb 2018 23:04:24 -0300 Subject: [PATCH 22/23] added tests for this endpoint --- tests/data/user.js | 29 ++++++++++++++++++++++++++++- tests/end-to-end/api/01-users.js | 31 ++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/tests/data/user.js b/tests/data/user.js index 92294f99dfcf..4198b2c10d70 100644 --- a/tests/data/user.js +++ b/tests/data/user.js @@ -1,7 +1,34 @@ export const username = `user.test.${ Date.now() }`; export const email = `${ username }@rocket.chat`; export const password = 'rocket.chat'; - export const adminUsername = 'rocketchat.internal.admin.test'; export const adminEmail = `${ adminUsername }@rocket.chat`; export const adminPassword = adminUsername; +export const preferences = { + data: { + newRoomNotification: 'door', + newMessageNotification: 'chime', + muteFocusedConversations: true, + useEmojis: true, + convertAsciiEmoji: true, + saveMobileBandwidth: true, + collapseMediaByDefault: false, + autoImageLoad: true, + emailNotificationMode: 'all', + roomsListExhibitionMode: 'category', + unreadAlert: true, + notificationsSoundVolume: 100, + desktopNotifications: 'default', + mobileNotifications: 'default', + enableAutoAway: true, + highlights: [], + desktopNotificationDuration: 0, + viewMode: 0, + hideUsernames: false, + hideRoles: false, + hideAvatars: false, + hideFlexTab: false, + sendOnEnter: 'normal', + roomCounterSidebar: false + } +}; diff --git a/tests/end-to-end/api/01-users.js b/tests/end-to-end/api/01-users.js index 77bf902518cb..5ded4ec1e7b6 100644 --- a/tests/end-to-end/api/01-users.js +++ b/tests/end-to-end/api/01-users.js @@ -3,7 +3,7 @@ /* eslint no-unused-vars: 0 */ import {getCredentials, api, login, request, credentials, apiEmail, apiUsername, targetUser, log} from '../../data/api-data.js'; -import {adminEmail, password} from '../../data/user.js'; +import {adminEmail, password, preferences} from '../../data/user.js'; import {imgURL} from '../../data/interactions.js'; import {customFieldText, clearCustomFields, setCustomFields} from '../../data/custom-fields.js'; @@ -377,4 +377,33 @@ describe('[Users]', function() { .end(done); }); }); + + describe('[/users.setPreferences]', () => { + it('should set some preferences by user when execute successfully', (done) => { + preferences.userId = credentials['X-User-Id']; + request.post(api('users.setPreferences')) + .set(credentials) + .send(preferences) + .expect(200) + .expect('Content-Type', 'application/json') + .expect((res) => { + expect(res.body.user.settings.preferences).to.be.eql(preferences.data); + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + }); + + describe('[/users.getPreferences]', () => { + it('should return all preferences when execute successfully', (done) => { + request.get(api('users.getPreferences')) + .set(credentials) + .expect(200) + .expect('Content-Type', 'application/json') + .expect((res) => { + expect(res.body).to.have.property('success', true); + }) + .end(done); + }); + }); }); From 68ceaf7fff556b302957ca102dc9378a1010d51e Mon Sep 17 00:00:00 2001 From: Marcos Vinicius Spessatto Defendi Date: Tue, 20 Feb 2018 13:37:15 -0300 Subject: [PATCH 23/23] fix test about getPreferences endpoint --- tests/end-to-end/api/01-users.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end-to-end/api/01-users.js b/tests/end-to-end/api/01-users.js index 5ded4ec1e7b6..cf8708eb8564 100644 --- a/tests/end-to-end/api/01-users.js +++ b/tests/end-to-end/api/01-users.js @@ -401,6 +401,7 @@ describe('[Users]', function() { .expect(200) .expect('Content-Type', 'application/json') .expect((res) => { + expect(res.body.preferences).to.be.eql(preferences.data); expect(res.body).to.have.property('success', true); }) .end(done);