Skip to content

Commit

Permalink
Merge branch 'develop' into feat/create-contact-endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
tapiarafael committed Aug 23, 2024
2 parents 1f3d928 + 27f9249 commit c79fe52
Show file tree
Hide file tree
Showing 49 changed files with 1,019 additions and 165 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-spiders-pay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes an issue where the Announcement modal with long words was adding a horizontal scrollbar
5 changes: 0 additions & 5 deletions .changeset/kind-drinks-joke.md

This file was deleted.

7 changes: 7 additions & 0 deletions .changeset/ninety-hounds-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rocket.chat/rest-typings': patch
'@rocket.chat/meteor': patch
'@rocket.chat/i18n': patch
---

Fix: Show correct user info actions for non-members in channels.
7 changes: 7 additions & 0 deletions .changeset/stupid-fishes-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rocket.chat/core-typings': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Added a new setting to enable/disable file encryption in an end to end encrypted room.
15 changes: 15 additions & 0 deletions .changeset/violet-radios-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@rocket.chat/core-typings': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Fixed a bug related to uploading end to end encrypted file.

E2EE files and uploads are uploaded as files of mime type `application/octet-stream` as we can't reveal the mime type of actual content since it is encrypted and has to be kept confidential.

The server resolves the mime type of encrypted file as `application/octet-stream` but it wasn't playing nicely with existing settings related to whitelisted and blacklisted media types.

E2EE files upload was getting blocked if `application/octet-stream` is not a whitelisted media type.

Now this PR solves this issue by always accepting E2EE uploads even if `application/octet-stream` is not whitelisted but it will block the upload if `application/octet-stream` is black listed.
40 changes: 38 additions & 2 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { Media } from '@rocket.chat/core-services';
import type { IRoom, IUpload } from '@rocket.chat/core-typings';
import { Messages, Rooms, Users, Uploads } from '@rocket.chat/models';
import { Messages, Rooms, Users, Uploads, Subscriptions } from '@rocket.chat/models';
import type { Notifications } from '@rocket.chat/rest-typings';
import { isGETRoomsNameExists, isRoomsImagesProps, isRoomsMuteUnmuteUserProps, isRoomsExportProps } from '@rocket.chat/rest-typings';
import {
isGETRoomsNameExists,
isRoomsImagesProps,
isRoomsMuteUnmuteUserProps,
isRoomsExportProps,
isRoomsIsMemberProps,
} from '@rocket.chat/rest-typings';
import { Meteor } from 'meteor/meteor';

import { isTruthy } from '../../../../lib/isTruthy';
Expand Down Expand Up @@ -783,6 +789,36 @@ API.v1.addRoute(
},
);

API.v1.addRoute(
'rooms.isMember',
{
authRequired: true,
validateParams: isRoomsIsMemberProps,
},
{
async get() {
const { roomId, userId, username } = this.queryParams;
const [room, user] = await Promise.all([
findRoomByIdOrName({
params: { roomId },
}) as Promise<IRoom>,
Users.findOneByIdOrUsername(userId || username),
]);

if (!user?._id) {
return API.v1.failure('error-user-not-found');
}

if (await canAccessRoomAsync(room, { _id: this.user._id })) {
return API.v1.success({
isMember: (await Subscriptions.countByRoomIdAndUserId(room._id, user._id)) > 0,
});
}
return API.v1.unauthorized();
},
},
);

API.v1.addRoute(
'rooms.muteUser',
{ authRequired: true, validateParams: isRoomsMuteUnmuteUserProps },
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { saveRoomReadOnly } from '../functions/saveRoomReadOnly';
import { saveRoomSystemMessages } from '../functions/saveRoomSystemMessages';
import { saveRoomTopic } from '../functions/saveRoomTopic';
import { saveRoomType } from '../functions/saveRoomType';
import { saveStreamingOptions } from '../functions/saveStreamingOptions';

type RoomSettings = {
roomAvatar: string;
Expand All @@ -37,7 +36,6 @@ type RoomSettings = {
systemMessages: MessageTypesValues[];
default: boolean;
joinCode: string;
streamingOptions: NonNullable<IRoom['streamingOptions']>;
retentionEnabled: boolean;
retentionMaxAge: number;
retentionExcludePinned: boolean;
Expand Down Expand Up @@ -272,9 +270,6 @@ const settingSavers: RoomSettingsSavers = {
void Team.update(user._id, room.teamId, { type, updateRoom: false });
}
},
async streamingOptions({ value, rid }) {
await saveStreamingOptions(rid, value);
},
async readOnly({ value, room, rid, user }) {
if (value !== room.ro) {
await saveRoomReadOnly(rid, value, user);
Expand Down Expand Up @@ -354,7 +349,6 @@ const fields: (keyof RoomSettings)[] = [
'systemMessages',
'default',
'joinCode',
'streamingOptions',
'retentionEnabled',
'retentionMaxAge',
'retentionExcludePinned',
Expand Down
10 changes: 8 additions & 2 deletions apps/meteor/app/file-upload/server/lib/FileUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import URL from 'url';
import { hashLoginToken } from '@rocket.chat/account-utils';
import { Apps, AppEvents } from '@rocket.chat/apps';
import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions';
import type { IUpload } from '@rocket.chat/core-typings';
import { isE2EEUpload, type IUpload } from '@rocket.chat/core-typings';
import { Users, Avatars, UserDataFiles, Uploads, Settings, Subscriptions, Messages, Rooms } from '@rocket.chat/models';
import type { NextFunction } from 'connect';
import filesize from 'filesize';
Expand Down Expand Up @@ -170,7 +170,13 @@ export const FileUpload = {
throw new Meteor.Error('error-file-too-large', reason);
}

if (!fileUploadIsValidContentType(file?.type)) {
if (!settings.get('E2E_Enable_Encrypt_Files') && isE2EEUpload(file)) {
const reason = i18n.t('Encrypted_file_not_allowed', { lng: language });
throw new Meteor.Error('error-invalid-file-type', reason);
}

// E2EE files are of type - application/octet-stream, application/octet-stream is whitelisted for E2EE files.
if (!fileUploadIsValidContentType(file?.type, isE2EEUpload(file) ? 'application/octet-stream' : undefined)) {
const reason = i18n.t('File_type_is_not_accepted', { lng: language });
throw new Meteor.Error('error-invalid-file-type', reason);
}
Expand Down
4 changes: 4 additions & 0 deletions apps/meteor/app/livechat/server/api/lib/livechat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export function findGuest(token: string): Promise<ILivechatVisitor | null> {
});
}

export function findGuestWithoutActivity(token: string): Promise<ILivechatVisitor | null> {
return LivechatVisitors.getVisitorByToken(token, { projection: { name: 1, username: 1, token: 1, visitorEmails: 1, department: 1 } });
}

export async function findRoom(token: string, rid?: string): Promise<IOmnichannelRoom | null> {
const fields = {
t: 1,
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/livechat/server/api/v1/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { isGETAgentNextToken, isPOSTLivechatAgentStatusProps } from '@rocket.cha
import { API } from '../../../../api/server';
import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission';
import { Livechat as LivechatTyped } from '../../lib/LivechatTyped';
import { RoutingManager } from '../../lib/RoutingManager';
import { findRoom, findGuest, findAgent, findOpenRoom } from '../lib/livechat';

API.v1.addRoute('livechat/agent.info/:rid/:token', {
Expand Down Expand Up @@ -48,7 +49,7 @@ API.v1.addRoute(
}
}

const agentData = await LivechatTyped.getNextAgent(department);
const agentData = await RoutingManager.getNextAgent(department);
if (!agentData) {
throw new Error('agent-not-found');
}
Expand Down
7 changes: 4 additions & 3 deletions apps/meteor/app/livechat/server/api/v1/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { isGETLivechatConfigParams } from '@rocket.chat/rest-typings';
import mem from 'mem';

import { API } from '../../../../api/server';
import { settings as serverSettings } from '../../../../settings/server';
import { Livechat } from '../../lib/LivechatTyped';
import { settings, findOpenRoom, getExtraConfigInfo, findAgent } from '../lib/livechat';
import { settings, findOpenRoom, getExtraConfigInfo, findAgent, findGuestWithoutActivity } from '../lib/livechat';

const cachedSettings = mem(settings, { maxAge: process.env.TEST_MODE === 'true' ? 1 : 1000, cacheKey: JSON.stringify });

Expand All @@ -12,7 +13,7 @@ API.v1.addRoute(
{ validateParams: isGETLivechatConfigParams },
{
async get() {
const enabled = Livechat.enabled();
const enabled = serverSettings.get<boolean>('Livechat_enabled');

if (!enabled) {
return API.v1.success({ config: { enabled: false } });
Expand All @@ -23,7 +24,7 @@ API.v1.addRoute(
const config = await cachedSettings({ businessUnit });

const status = await Livechat.online(department);
const guest = token ? await Livechat.findGuest(token) : null;
const guest = token ? await findGuestWithoutActivity(token) : null;

const room = guest ? await findOpenRoom(guest.token) : undefined;
const agent = guest && room && room.servedBy && (await findAgent(room.servedBy._id));
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/livechat/server/api/v1/transcript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { isPOSTLivechatTranscriptParams, isPOSTLivechatTranscriptRequestParams }
import { i18n } from '../../../../../server/lib/i18n';
import { API } from '../../../../api/server';
import { Livechat } from '../../lib/LivechatTyped';
import { sendTranscript } from '../../lib/sendTranscript';

API.v1.addRoute(
'livechat/transcript',
{ validateParams: isPOSTLivechatTranscriptParams },
{
async post() {
const { token, rid, email } = this.bodyParams;
if (!(await Livechat.sendTranscript({ token, rid, email }))) {
if (!(await sendTranscript({ token, rid, email }))) {
return API.v1.failure({ message: i18n.t('Error_sending_livechat_transcript') });
}

Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/hooks/saveContactLastChat.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isOmnichannelRoom } from '@rocket.chat/core-typings';
import { LivechatVisitors } from '@rocket.chat/models';

import { callbacks } from '../../../../lib/callbacks';
import { Livechat } from '../lib/LivechatTyped';

callbacks.add(
'livechat.newRoom',
Expand All @@ -19,7 +19,7 @@ callbacks.add(
_id,
ts: new Date(),
};
await Livechat.updateLastChat(guestId, lastChat);
await LivechatVisitors.setLastChatById(guestId, lastChat);
},
callbacks.priority.MEDIUM,
'livechat-save-last-chat',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { isOmnichannelRoom } from '@rocket.chat/core-typings';
import { LivechatRooms } from '@rocket.chat/models';

import { callbacks } from '../../../../lib/callbacks';
import { Livechat } from '../lib/LivechatTyped';
import type { CloseRoomParams } from '../lib/LivechatTyped';
import { sendTranscript } from '../lib/sendTranscript';

type LivechatCloseCallbackParams = {
room: IOmnichannelRoom;
Expand All @@ -30,10 +30,7 @@ const sendEmailTranscriptOnClose = async (params: LivechatCloseCallbackParams):

const { email, subject, requestedBy: user } = transcriptData;

await Promise.all([
Livechat.sendTranscript({ token, rid, email, subject, user }),
LivechatRooms.unsetEmailTranscriptRequestedByRoomId(rid),
]);
await Promise.all([sendTranscript({ token, rid, email, subject, user }), LivechatRooms.unsetEmailTranscriptRequestedByRoomId(rid)]);

delete room.transcriptRequest;

Expand Down
50 changes: 2 additions & 48 deletions apps/meteor/app/livechat/server/lib/LivechatTyped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ import { RoutingManager } from './RoutingManager';
import { isDepartmentCreationAvailable } from './isDepartmentCreationAvailable';
import type { CloseRoomParams, CloseRoomParamsByUser, CloseRoomParamsByVisitor } from './localTypes';
import { parseTranscriptRequest } from './parseTranscriptRequest';
import { sendTranscript as sendTranscriptFunc } from './sendTranscript';

type RegisterGuestType = Partial<Pick<ILivechatVisitor, 'token' | 'name' | 'department' | 'status' | 'username'>> & {
id?: string;
Expand Down Expand Up @@ -163,22 +162,6 @@ class LivechatClass {
this.webhookLogger = this.logger.section('Webhook');
}

findGuest(token: string) {
return LivechatVisitors.getVisitorByToken(token, {
projection: {
name: 1,
username: 1,
token: 1,
visitorEmails: 1,
department: 1,
},
});
}

enabled() {
return Boolean(settings.get('Livechat_enabled'));
}

async online(department?: string, skipNoAgentSetting = false, skipFallbackCheck = false): Promise<boolean> {
Livechat.logger.debug(`Checking online agents ${department ? `for department ${department}` : ''}`);
if (!skipNoAgentSetting && settings.get('Livechat_accept_chats_with_no_agents')) {
Expand All @@ -203,10 +186,6 @@ class LivechatClass {
return agentsOnline;
}

getNextAgent(department?: string): Promise<SelectedAgent | null | undefined> {
return RoutingManager.getNextAgent(department);
}

async getOnlineAgents(department?: string, agent?: SelectedAgent | null): Promise<FindCursor<ILivechatAgent> | undefined> {
if (agent?.agentId) {
return Users.findOnlineAgents(agent.agentId);
Expand Down Expand Up @@ -451,7 +430,7 @@ class LivechatClass {
agent?: SelectedAgent;
extraData?: Record<string, unknown>;
}) {
if (!this.enabled()) {
if (!settings.get('Livechat_enabled')) {
throw new Meteor.Error('error-omnichannel-is-disabled');
}

Expand Down Expand Up @@ -502,7 +481,7 @@ class LivechatClass {
agent?: SelectedAgent,
extraData?: E,
) {
if (!this.enabled()) {
if (!settings.get('Livechat_enabled')) {
throw new Meteor.Error('error-omnichannel-is-disabled');
}
Livechat.logger.debug(`Attempting to find or create a room for visitor ${guest._id}`);
Expand Down Expand Up @@ -876,15 +855,6 @@ class LivechatClass {
}
}

async updateLastChat(contactId: string, lastChat: Required<ILivechatVisitor['lastChat']>) {
const updateUser = {
$set: {
lastChat,
},
};
await LivechatVisitors.updateById(contactId, updateUser);
}

notifyRoomVisitorChange(roomId: string, visitor: ILivechatVisitor) {
void api.broadcast('omnichannel.room', roomId, {
type: 'visitorData',
Expand Down Expand Up @@ -1907,22 +1877,6 @@ class LivechatClass {

return departmentDB;
}

async sendTranscript({
token,
rid,
email,
subject,
user,
}: {
token: string;
rid: string;
email: string;
subject?: string;
user?: Pick<IUser, '_id' | 'name' | 'username' | 'utcOffset'> | null;
}): Promise<boolean> {
return sendTranscriptFunc({ token, rid, email, subject, user });
}
}

export const Livechat = new LivechatClass();
Expand Down
Loading

0 comments on commit c79fe52

Please sign in to comment.