Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/RocketChat#589' into protocols
Browse files Browse the repository at this point in the history
  • Loading branch information
shedoev committed Oct 26, 2020
2 parents 0dc10ef + 296cf0d commit 91ab85f
Show file tree
Hide file tree
Showing 18 changed files with 716 additions and 46 deletions.
5 changes: 4 additions & 1 deletion app/api/server/lib/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ export async function findUsersToAutocomplete({ uid, selector }) {
};
}


export async function findUser(_id) {
const cursor = await Users.findOne({ _id });
return cursor;
}
19 changes: 18 additions & 1 deletion app/api/server/v1/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { getFullUserDataByIdOrUsername } from '../../../lib/server/functions/getFullUserData';
import { API } from '../api';
import { setStatusText } from '../../../lib/server';
import { findUsersToAutocomplete } from '../lib/users';
import { findUsersToAutocomplete, findUser } from '../lib/users';
import { getUserForCheck, emailCheck } from '../../../2fa/server/code';
import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKey';
import { setUserStatus } from '../../../../imports/users-presence/server/activeUsers';
Expand All @@ -29,9 +29,14 @@ API.v1.addRoute('users.create', { authRequired: true }, {
check(this.bodyParams, {
email: String,
name: String,
surname: String,
patronymic: String,
password: String,
username: String,
active: Match.Maybe(Boolean),
organization: Match.Maybe(String),
position: Match.Maybe(String),
phone: Match.Maybe(String),
bio: Match.Maybe(String),
nickname: Match.Maybe(String),
statusText: Match.Maybe(String),
Expand Down Expand Up @@ -464,8 +469,13 @@ API.v1.addRoute('users.update', { authRequired: true, twoFactorRequired: true },
data: Match.ObjectIncluding({
email: Match.Maybe(String),
name: Match.Maybe(String),
surname: Match.Maybe(String),
patronymic: Match.Maybe(String),
password: Match.Maybe(String),
username: Match.Maybe(String),
organization: Match.Maybe(String),
position: Match.Maybe(String),
phone: Match.Maybe(String),
bio: Match.Maybe(String),
nickname: Match.Maybe(String),
statusText: Match.Maybe(String),
Expand Down Expand Up @@ -869,3 +879,10 @@ API.v1.addRoute('users.resetE2EKey', { authRequired: true, twoFactorRequired: tr
return API.v1.success();
},
});

API.v1.addRoute('users.getOne', { authRequired: true }, {
get() {
const { query } = this.parseJsonQuery();
return API.v1.success(Promise.await(findUser(query._id)));
},
});
4 changes: 4 additions & 0 deletions app/lib/server/functions/getFullUserData.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { hasPermission } from '../../../authorization';
const logger = new Logger('getFullUserData');

const defaultFields = {
surname: 1,
name: 1,
patronymic: 1,
username: 1,
nickname: 1,
status: 1,
Expand All @@ -23,6 +25,8 @@ const defaultFields = {

const fullFields = {
emails: 1,
organization: 1,
position: 1,
phone: 1,
statusConnection: 1,
bio: 1,
Expand Down
22 changes: 21 additions & 1 deletion app/lib/server/functions/saveUserIdentity.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { setUsername } from './setUsername';
import { setRealName } from './setRealName';
import { setSurname } from './setSurname';
import { setPatronymic } from './setPatronymic';
import { Messages, Rooms, Subscriptions, LivechatDepartmentAgents, Users } from '../../../models/server';
import { FileUpload } from '../../../file-upload/server';
import { updateGroupDMsName } from './updateGroupDMsName';
Expand All @@ -9,20 +11,26 @@ import { updateGroupDMsName } from './updateGroupDMsName';
* @param {string} userId user performing the action
* @param {object} changes changes to the user
*/
export function saveUserIdentity(userId, { _id, name: rawName, username: rawUsername }) {
export function saveUserIdentity(userId, { _id, name: rawName, username: rawUsername, surname: rawSurname, patronymic: rawPatronymc }) {
if (!_id) {
return false;
}

const name = String(rawName).trim();
const username = String(rawUsername).trim();
const surname = String(rawSurname).trim();
const patronymic = String(rawPatronymc).trim();

const user = Users.findOneById(_id);

const previousUsername = user.username;
const previousName = user.name;
const previousSurname = user.surname;
const previousPatronymic = user.patronymic;
const nameChanged = previousName !== name;
const usernameChanged = previousUsername !== username;
const surnameChanged = previousSurname !== surname;
const patronymicChanged = previousPatronymic !== patronymic;

if (typeof rawUsername !== 'undefined' && usernameChanged) {
if (!setUsername(_id, username, user)) {
Expand All @@ -37,6 +45,18 @@ export function saveUserIdentity(userId, { _id, name: rawName, username: rawUser
}
}

if (typeof rawSurname !== 'undefined' && surnameChanged) {
if (!setSurname(_id, surname, user)) {
return false;
}
}

if (typeof rawPatronymc !== 'undefined' && patronymicChanged) {
if (!setPatronymic(_id, patronymic, user)) {
return false;
}
}

// if coming from old username, update all references
if (previousUsername && usernameChanged) {
if (typeof rawUsername !== 'undefined') {
Expand Down
35 changes: 35 additions & 0 deletions app/lib/server/functions/setPatronymic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meteor } from 'meteor/meteor';
import s from 'underscore.string';

import { Users } from '../../../models/server';
import { settings } from '../../../settings';
import { hasPermission } from '../../../authorization';
import { RateLimiter } from '../lib';

export const _setPatronymic = function(userId, patronymic, fullUser) {
patronymic = s.trim(patronymic);

if (!userId || (settings.get('Accounts_RequireNameForSignUp') && !patronymic)) {
return false;
}

const user = fullUser || Users.findOneById(userId);

// User already has desired name, return
if (s.trim(user.patronymic) === patronymic) {
return user;
}

if (patronymic) {
Users.setPatronymic(user._id, patronymic);
} else {
Users.unsetPatronymic(user._id);
}
user.patronymic = patronymic;

return user;
};

export const setPatronymic = RateLimiter.limitFunction(_setPatronymic, 1, 60000, {
0() { return !Meteor.userId() || !hasPermission(Meteor.userId(), 'edit-other-user-info'); }, // Administrators have permission to change others names, so don't limit those
});
35 changes: 35 additions & 0 deletions app/lib/server/functions/setSurname.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meteor } from 'meteor/meteor';
import s from 'underscore.string';

import { Users } from '../../../models/server';
import { settings } from '../../../settings';
import { hasPermission } from '../../../authorization';
import { RateLimiter } from '../lib';

export const _setSurname = function(userId, surname, fullUser) {
surname = s.trim(surname);

if (!userId || (settings.get('Accounts_RequireNameForSignUp') && !surname)) {
return false;
}

const user = fullUser || Users.findOneById(userId);

// User already has desired name, return
if (s.trim(user.surname) === surname) {
return user;
}

if (surname) {
Users.setSurname(user._id, surname);
} else {
Users.unsetSurname(user._id);
}
user.surname = surname;

return user;
};

export const setSurname = RateLimiter.limitFunction(_setSurname, 1, 60000, {
0() { return !Meteor.userId() || !hasPermission(Meteor.userId(), 'edit-other-user-info'); }, // Administrators have permission to change others names, so don't limit those
});
8 changes: 8 additions & 0 deletions app/lib/server/startup/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ settings.addGroup('Accounts', function() {
type: 'boolean',
public: true,
});
this.add('Accounts_AllowOrganizationChange', true, {
type: 'boolean',
public: true,
});
this.add('Accounts_AllowPositionChange', true, {
type: 'boolean',
public: true,
});
this.add('Accounts_AllowUserStatusMessageChange', true, {
type: 'boolean',
public: true,
Expand Down
136 changes: 136 additions & 0 deletions app/models/server/models/Users.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export class Users extends Base {

this.tryEnsureIndex({ roles: 1 }, { sparse: 1 });
this.tryEnsureIndex({ name: 1 });
this.tryEnsureIndex({ surname: 1 });
this.tryEnsureIndex({ patronymic: 1 });
this.tryEnsureIndex({ organization: 1 });
this.tryEnsureIndex({ position: 1 });
this.tryEnsureIndex({ phone: 1 });
this.tryEnsureIndex({ bio: 1 }, { sparse: 1 });
this.tryEnsureIndex({ nickname: 1 }, { sparse: 1 });
this.tryEnsureIndex({ createdAt: 1 });
Expand Down Expand Up @@ -1048,6 +1053,34 @@ export class Users extends Base {
return this.update(query, update);
}

setSurname(_id, surname) {
const update = {
$set: {
surname,
},
};
return this.update(_id, update);
}

unsetSurname(_id) {
const update = {
$unset: {
surname: 1,
},
};
return this.update(_id, update);
}

addSurname(_id, surname) {
const update = {
$set: {
surname,
},
};

return this.update(_id, update);
}

setName(_id, name) {
const update = {
$set: {
Expand All @@ -1068,6 +1101,34 @@ export class Users extends Base {
return this.update(_id, update);
}

setPatronymic(_id, patronymic) {
const update = {
$set: {
patronymic,
},
};
return this.update(_id, update);
}

unsetPatronymic(_id) {
const update = {
$unset: {
patronymic: 1,
},
};
return this.update(_id, update);
}

addPatronymic(_id, patronymic) {
const update = {
$set: {
patronymic,
},
};

return this.update(_id, update);
}

setCustomFields(_id, fields) {
const values = {};
Object.keys(fields).forEach((key) => {
Expand Down Expand Up @@ -1196,6 +1257,81 @@ export class Users extends Base {
return this.update(_id, update);
}

setOrganization(_id, organization) {
const update = {
...organization.trim() ? {
$set: {
organization,
},
} : {
$unset: {
organization: 1,
},
},
};
return this.update(_id, update);
}

addOrganization(_id, organization) {
const update = {
$set: {
organization,
},
};

return this.update(_id, update);
}

setPosition(_id, position) {
const update = {
...position.trim() ? {
$set: {
position,
},
} : {
$unset: {
position: 1,
},
},
};
return this.update(_id, update);
}

addPosition(_id, position) {
const update = {
$set: {
position,
},
};

return this.update(_id, update);
}

setPhone(_id, phone) {
const update = {
...phone.trim() ? {
$set: {
phone,
},
} : {
$unset: {
phone: 1,
},
},
};
return this.update(_id, update);
}

addPhone(_id, phone) {
const update = {
$set: {
phone,
},
};

return this.update(_id, update);
}

setBio(_id, bio = '') {
const update = {
...bio.trim() ? {
Expand Down
Loading

0 comments on commit 91ab85f

Please sign in to comment.