Skip to content

Commit

Permalink
Merge branch 'develop' into ee-livechat-waiting-queue-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
murtaza98 authored May 14, 2021
2 parents 2b50040 + 4713f3a commit 26a7704
Show file tree
Hide file tree
Showing 42 changed files with 498 additions and 263 deletions.
42 changes: 23 additions & 19 deletions app/api/server/v1/channels.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
import _ from 'underscore';

import { Rooms, Subscriptions, Messages, Uploads, Integrations, Users } from '../../../models';
import { Rooms, Subscriptions, Messages, Uploads, Integrations, Users } from '../../../models/server';
import { hasPermission, hasAtLeastOnePermission, hasAllPermission } from '../../../authorization/server';
import { mountIntegrationQueryBasedOnPermissions } from '../../../integrations/server/lib/mountQueriesBasedOnPermission';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { API } from '../api';
import { settings } from '../../../settings';
import { settings } from '../../../settings/server';
import { Team } from '../../../../server/sdk';
import { findUsersOfRoom } from '../../../../server/lib/findUsersOfRoom';


// Returns the channel IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
Expand Down Expand Up @@ -575,29 +577,31 @@ API.v1.addRoute('channels.members', { authRequired: true }, {
return API.v1.unauthorized();
}

const { offset, count } = this.getPaginationItems();
const { offset: skip, count: limit } = this.getPaginationItems();
const { sort = {} } = this.parseJsonQuery();

const subscriptions = Subscriptions.findByRoomId(findResult._id, {
fields: { 'u._id': 1 },
sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count,
});

const total = subscriptions.count();
check(this.queryParams, Match.ObjectIncluding({
status: Match.Maybe([String]),
filter: Match.Maybe(String),
}));
const { status, filter } = this.queryParams;

const members = subscriptions.fetch().map((s) => s.u && s.u._id);
const cursor = findUsersOfRoom({
rid: findResult._id,
...status && { status: { $in: status } },
skip,
limit,
filter,
...sort?.username && { sort: { username: sort.username } },
});

const users = Users.find({ _id: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, statusText: 1, utcOffset: 1 },
sort: { username: sort.username != null ? sort.username : 1 },
}).fetch();
const total = cursor.count();
const members = cursor.fetch();

return API.v1.success({
members: users,
count: users.length,
offset,
members,
count: members.length,
offset: skip,
total,
});
},
Expand Down
49 changes: 28 additions & 21 deletions app/api/server/v1/groups.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import _ from 'underscore';
import { Meteor } from 'meteor/meteor';
import { Match } from 'meteor/check';
import { Match, check } from 'meteor/check';

import { mountIntegrationQueryBasedOnPermissions } from '../../../integrations/server/lib/mountQueriesBasedOnPermission';
import { Subscriptions, Rooms, Messages, Uploads, Integrations, Users } from '../../../models/server';
import { hasPermission, hasAtLeastOnePermission, canAccessRoom, hasAllPermission } from '../../../authorization/server';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { API } from '../api';
import { Team } from '../../../../server/sdk';
import { findUsersOfRoom } from '../../../../server/lib/findUsersOfRoom';

// Returns the private group subscription IF found otherwise it will return the failure of why it didn't. Check the `statusCode` property
export function findPrivateGroupByIdOrName({ params, userId, checkedArchived = true }) {
Expand All @@ -23,6 +24,7 @@ export function findPrivateGroupByIdOrName({ params, userId, checkedArchived = t
fname: 1,
prid: 1,
archived: 1,
broadcast: 1,
},
};
const room = params.roomId
Expand Down Expand Up @@ -54,6 +56,7 @@ export function findPrivateGroupByIdOrName({ params, userId, checkedArchived = t
ro: room.ro,
t: room.t,
name: roomName,
broadcast: room.broadcast,
};
}

Expand Down Expand Up @@ -491,36 +494,40 @@ API.v1.addRoute('groups.listAll', { authRequired: true }, {

API.v1.addRoute('groups.members', { authRequired: true }, {
get() {
const findResult = findPrivateGroupByIdOrName({ params: this.requestParams(), userId: this.userId });
const room = Rooms.findOneById(findResult.rid, { fields: { broadcast: 1 } });
const findResult = findPrivateGroupByIdOrName({
params: this.requestParams(),
userId: this.userId,
});

if (room.broadcast && !hasPermission(this.userId, 'view-broadcast-member-list')) {
if (findResult.broadcast && !hasPermission(this.userId, 'view-broadcast-member-list')) {
return API.v1.unauthorized();
}

const { offset, count } = this.getPaginationItems();
const { offset: skip, count: limit } = this.getPaginationItems();
const { sort = {} } = this.parseJsonQuery();

const subscriptions = Subscriptions.findByRoomId(findResult.rid, {
fields: { 'u._id': 1 },
sort: { 'u.username': sort.username != null ? sort.username : 1 },
skip: offset,
limit: count,
});

const total = subscriptions.count();
check(this.queryParams, Match.ObjectIncluding({
status: Match.Maybe([String]),
filter: Match.Maybe(String),
}));
const { status, filter } = this.queryParams;

const members = subscriptions.fetch().map((s) => s.u && s.u._id);
const cursor = findUsersOfRoom({
rid: findResult.rid,
...status && { status: { $in: status } },
skip,
limit,
filter,
...sort?.username && { sort: { username: sort.username } },
});

const users = Users.find({ _id: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, statusText: 1, utcOffset: 1 },
sort: { username: sort.username != null ? sort.username : 1 },
}).fetch();
const total = cursor.count();
const members = cursor.fetch();

return API.v1.success({
members: users,
count: users.length,
offset,
members,
count: members.length,
offset: skip,
total,
});
},
Expand Down
37 changes: 24 additions & 13 deletions app/api/server/v1/im.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';

import { Subscriptions, Uploads, Users, Messages, Rooms } from '../../../models';
import { hasPermission } from '../../../authorization';
import { Subscriptions, Uploads, Users, Messages, Rooms } from '../../../models/server';
import { hasPermission } from '../../../authorization/server';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { settings } from '../../../settings';
import { settings } from '../../../settings/server';
import { API } from '../api';
import { getDirectMessageByNameOrIdWithOptionToJoin } from '../../../lib/server/functions/getDirectMessageByNameOrIdWithOptionToJoin';

Expand Down Expand Up @@ -202,22 +203,32 @@ API.v1.addRoute(['dm.members', 'im.members'], { authRequired: true }, {

const { offset, count } = this.getPaginationItems();
const { sort } = this.parseJsonQuery();
const cursor = Subscriptions.findByRoomId(findResult.room._id, {
sort: { 'u.username': sort && sort.username ? sort.username : 1 },

check(this.queryParams, Match.ObjectIncluding({
status: Match.Maybe([String]),
filter: Match.Maybe(String),
}));
const { status, filter } = this.queryParams;

const extraQuery = {
_id: { $in: findResult.room.uids },
...status && { status: { $in: status } },
};

const options = {
sort: { username: sort && sort.username ? sort.username : 1 },
fields: { _id: 1, username: 1, name: 1, status: 1, statusText: 1, utcOffset: 1 },
skip: offset,
limit: count,
});
};

const total = cursor.count();
const members = cursor.fetch().map((s) => s.u && s.u.username);
const cursor = Users.findByActiveUsersExcept(filter, [], options, null, [extraQuery]);

const users = Users.find({ username: { $in: members } }, {
fields: { _id: 1, username: 1, name: 1, status: 1, statusText: 1, utcOffset: 1 },
sort: { username: sort && sort.username ? sort.username : 1 },
}).fetch();
const members = cursor.fetch();
const total = cursor.count();

return API.v1.success({
members: users,
members,
count: members.length,
offset,
total,
Expand Down
4 changes: 2 additions & 2 deletions app/api/server/v1/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ API.v1.addRoute('rooms.cleanHistory', { authRequired: true }, {

const inclusive = this.bodyParams.inclusive || false;

Meteor.runAsUser(this.userId, () => Meteor.call('cleanRoomHistory', {
const count = Meteor.runAsUser(this.userId, () => Meteor.call('cleanRoomHistory', {
roomId: findResult._id,
latest,
oldest,
Expand All @@ -207,7 +207,7 @@ API.v1.addRoute('rooms.cleanHistory', { authRequired: true }, {
fromUsers: this.bodyParams.users,
}));

return API.v1.success();
return API.v1.success({ count });
},
});

Expand Down
14 changes: 12 additions & 2 deletions app/apps/server/communication/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ export class AppsRestApi {
},
post() {
let buff;
let permissionsGranted;

if (this.bodyParams.url) {
if (settings.get('Apps_Framework_Development_Mode') !== true) {
Expand Down Expand Up @@ -470,14 +471,23 @@ export class AppsRestApi {
return API.v1.failure({ error: 'Direct updating of an App is disabled.' });
}

buff = multipartFormDataHandler(this.request)?.app;
const formData = multipartFormDataHandler(this.request);
buff = formData?.app;
permissionsGranted = (() => {
try {
const permissions = JSON.parse(formData?.permissions || '');
return permissions.length ? permissions : undefined;
} catch {
return undefined;
}
})();
}

if (!buff) {
return API.v1.failure({ error: 'Failed to get a file to install for the App. ' });
}

const aff = Promise.await(manager.update(buff, this.bodyParams.permissionsGranted));
const aff = Promise.await(manager.update(buff, permissionsGranted));
const info = aff.getAppInfo();

if (aff.hasStorageError()) {
Expand Down
5 changes: 4 additions & 1 deletion app/authorization/client/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import { registerAdminSidebarItem } from '../../../client/views/admin';
Meteor.startup(() => {
CachedCollectionManager.onLogin(async () => {
const { roles } = await APIClient.v1.get('roles.list');
roles.forEach((role) => Roles.insert(role));
// if a role is checked before this collection is populated, it will return undefined
for await (const role of roles) {
await Roles.upsert({ _id: role._id }, role);
}
});

registerAdminSidebarItem({
Expand Down
2 changes: 1 addition & 1 deletion app/authorization/server/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ Meteor.startup(function() {
{ _id: 'send-omnichannel-chat-transcript', roles: ['livechat-manager', 'admin'] },
{ _id: 'mail-messages', roles: ['admin'] },
{ _id: 'toggle-room-e2e-encryption', roles: ['owner'] },
{ _id: 'message-impersonate', roles: ['bot'] },
{ _id: 'message-impersonate', roles: ['bot', 'app'] },
{ _id: 'create-team', roles: ['admin', 'user'] },
{ _id: 'delete-team', roles: ['admin', 'owner'] },
{ _id: 'edit-team', roles: ['admin', 'owner'] },
Expand Down
6 changes: 2 additions & 4 deletions app/e2e/client/rocketchat.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,6 @@ class E2E extends Emitter {

async requestPassword() {
return new Promise((resolve) => {
let showAlert;

const showModal = () => {
modal.open({
title: TAPi18n.__('Enter_E2E_password_to_decode_your_key'),
Expand All @@ -314,11 +312,11 @@ class E2E extends Emitter {
}
}, () => {
failedToDecodeKey = false;
showAlert();
this.closeAlert();
});
};

showAlert = () => {
const showAlert = () => {
this.openAlert({
title: TAPi18n.__('Enter_your_E2E_password'),
html: TAPi18n.__('Click_here_to_enter_your_encryption_password'),
Expand Down
1 change: 1 addition & 0 deletions app/lib/server/functions/getFullUserData.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export function getFullUserDataByIdOrUsername({ userId, filterId, filterUsername
fields,
};
const user = Users.findOneByIdOrUsername(filterId || filterUsername, options);
user.canViewAllInfo = canViewAllInfo;

return myself ? user : removePasswordInfo(user);
}
Expand Down
2 changes: 1 addition & 1 deletion app/message-pin/client/views/pinnedMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Template.pinnedMessages.onCreated(function() {
pinned: true,
rid: this.data.rid,
_updatedAt: {
$gt: new Date(),
$gte: new Date(),
},
};

Expand Down
2 changes: 1 addition & 1 deletion app/models/server/models/Users.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ export class Users extends Base {
}

// if the search term is empty, don't need to have the $or statement (because it would be an empty regex)
if (searchTerm === '') {
if (!searchTerm) {
const query = {
$and: [
{
Expand Down
3 changes: 2 additions & 1 deletion app/ui-cached-collection/client/models/CachedCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ export class CachedCollection extends Emitter {
});
}
if (room) {
RoomManager.close(room.t + room.name);
room.name && RoomManager.close(room.t + room.name);
!room.name && RoomManager.close(room.t + room._id);
}
this.collection.remove(record._id);
} else {
Expand Down
2 changes: 1 addition & 1 deletion app/ui-clean-history/client/index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import './lib/startup';
import './lib/tabBar';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const template = lazy(() => import('../../../../client/views/room/contextualBar/
addAction('clean-history', ({ room }) => {
const hasPermission = usePermission('clean-channel-history', room._id);
return useMemo(() => (hasPermission ? {
groups: ['channel', 'group', 'direct'],
groups: ['channel', 'group', 'team', 'direct'],
id: 'clean-history',
full: true,
title: 'Prune_Messages',
Expand Down
3 changes: 2 additions & 1 deletion app/ui-master/client/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ Template.main.helpers({
if (!user || (user.services.totp !== undefined && user.services.totp.enabled) || (user.services.email2fa !== undefined && user.services.email2fa.enabled)) {
return false;
}
const is2faEnabled = settings.get('Accounts_TwoFactorAuthentication_Enabled');

const mandatoryRole = Roles.findOne({ _id: { $in: user.roles }, mandatory2fa: true });
return mandatoryRole !== undefined;
return mandatoryRole !== undefined && is2faEnabled;
},
CustomScriptLoggedOut: () => {
const script = settings.get('Custom_Script_Logged_Out') || '';
Expand Down
Loading

0 comments on commit 26a7704

Please sign in to comment.