Skip to content

Commit

Permalink
Merge branch 'develop' into fix/missing-customfields-on-upload-api
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigok authored Apr 20, 2024
2 parents e25535e + 2c677b8 commit ef99b59
Show file tree
Hide file tree
Showing 50 changed files with 724 additions and 84 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-news-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed issue with login via SAML not redirecting to invite link
5 changes: 5 additions & 0 deletions .changeset/great-moles-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---

Encrypt file descriptions in E2EE rooms
7 changes: 7 additions & 0 deletions .changeset/nervous-elephants-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@rocket.chat/model-typings': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Added a new setting to automatically disable users from LDAP that can no longer be found by the background sync
5 changes: 5 additions & 0 deletions .changeset/strange-comics-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed an issue where an endpoint was called before checking configuration that enables automatic translation when launching the application
5 changes: 5 additions & 0 deletions apps/meteor/.meteorMocks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import sinon from 'sinon';

export const Meteor = {
loginWithSamlToken: sinon.stub(),
};
6 changes: 6 additions & 0 deletions apps/meteor/app/api/server/api.helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { IUser } from '@rocket.chat/core-typings';

import { hasAllPermissionAsync, hasAtLeastOnePermissionAsync } from '../../authorization/server/functions/hasPermission';
import { apiDeprecationLogger } from '../../lib/server/lib/deprecationWarningLogger';

type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | '*';
export type PermissionsPayload = {
Expand Down Expand Up @@ -101,3 +102,8 @@ export function checkPermissions(options: { permissionsRequired?: PermissionsReq
// If reached here, options.permissionsRequired contained an invalid payload
return false;
}

export function parseDeprecation(methodThis: any, { alternatives, version }: { version: string; alternatives?: string[] }): void {
const infoMessage = alternatives?.length ? ` Please use the alternative(s): ${alternatives.join(',')}` : '';
apiDeprecationLogger.endpoint(methodThis.request.route, version, methodThis.response, infoMessage);
}
7 changes: 3 additions & 4 deletions apps/meteor/app/api/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ import { isObject } from '../../../lib/utils/isObject';
import { getRestPayload } from '../../../server/lib/logger/logPayloads';
import { checkCodeForUser } from '../../2fa/server/code';
import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission';
import { apiDeprecationLogger } from '../../lib/server/lib/deprecationWarningLogger';
import { metrics } from '../../metrics/server';
import { settings } from '../../settings/server';
import { getDefaultUserFields } from '../../utils/server/functions/getDefaultUserFields';
import type { PermissionsPayload } from './api.helpers';
import { checkPermissionsForInvocation, checkPermissions } from './api.helpers';
import { checkPermissionsForInvocation, checkPermissions, parseDeprecation } from './api.helpers';
import type {
FailureResult,
InternalError,
Expand Down Expand Up @@ -588,8 +587,8 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
const connection = { ...generateConnection(this.requestIp, this.request.headers), token: this.token };

try {
if (options.deprecationVersion) {
apiDeprecationLogger.endpoint(this.request.route, options.deprecationVersion, this.response, options.deprecationInfo || '');
if (options.deprecation) {
parseDeprecation(this, options.deprecation);
}

await api.enforceRateLimit(objectForRateLimitMatch, this.request, this.response, this.userId);
Expand Down
6 changes: 4 additions & 2 deletions apps/meteor/app/api/server/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ export type Options = (
) & {
validateParams?: ValidateFunction | { [key in Method]?: ValidateFunction };
authOrAnonRequired?: true;
deprecationVersion?: string;
deprecationInfo?: string;
deprecation?: {
version: string;
alternatives?: string[];
};
};

export type PartialThis = {
Expand Down
9 changes: 8 additions & 1 deletion apps/meteor/app/api/server/v1/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,14 @@ API.v1.addRoute(

API.v1.addRoute(
'channels.images',
{ authRequired: true, validateParams: isRoomsImagesProps, deprecationVersion: '7.0.0', deprecationInfo: 'Use /v1/rooms.images instead.' },
{
authRequired: true,
validateParams: isRoomsImagesProps,
deprecation: {
version: '7.0.0',
alternatives: ['rooms.images'],
},
},
{
async get() {
const room = await Rooms.findOneById<Pick<IRoom, '_id' | 't' | 'teamId' | 'prid'>>(this.queryParams.roomId, {
Expand Down
6 changes: 4 additions & 2 deletions apps/meteor/app/api/server/v1/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { SystemLogger } from '../../../../server/lib/logger/system';
import { getLogs } from '../../../../server/stream/stdout';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { passwordPolicy } from '../../../lib/server';
import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields';
import { getURL } from '../../../utils/server/getURL';
Expand Down Expand Up @@ -409,10 +408,13 @@ API.v1.addRoute(
{
authRequired: false,
validateParams: validateParamsPwGetPolicyRest,
deprecation: {
version: '7.0.0',
alternatives: ['pw.getPolicy'],
},
},
{
async get() {
apiDeprecationLogger.endpoint(this.request.route, '7.0.0', this.response, ' Use pw.getPolicy instead.');
check(
this.queryParams,
Match.ObjectIncluding({
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/autotranslate/client/lib/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '../../../../client/views/room/MessageList/lib/autoTranslate';
import { hasPermission } from '../../../authorization/client';
import { Subscriptions, Messages } from '../../../models/client';
import { settings } from '../../../settings/client';
import { sdk } from '../../../utils/client/lib/SDKClient';

let userLanguage = 'en';
Expand Down Expand Up @@ -102,7 +103,7 @@ export const AutoTranslate = {

Tracker.autorun(async (c) => {
const uid = Meteor.userId();
if (!uid || !hasPermission('auto-translate')) {
if (!settings.get('AutoTranslate_Enabled') || !uid || !hasPermission('auto-translate')) {
return;
}

Expand Down
14 changes: 14 additions & 0 deletions apps/meteor/app/e2e/client/rocketchat.e2e.room.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,20 @@ export class E2ERoom extends Emitter {
return this.encryptText(data);
}

encryptAttachmentDescription(description, _id) {
const ts = new Date();

const data = new TextEncoder('UTF-8').encode(
EJSON.stringify({
userId: this.userId,
text: description,
_id,
ts,
}),
);
return this.encryptText(data);
}

// Decrypt messages

async decryptMessage(message) {
Expand Down
57 changes: 49 additions & 8 deletions apps/meteor/app/e2e/client/rocketchat.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import QueryString from 'querystring';
import URL from 'url';

import type { IE2EEMessage, IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings';
import { isE2EEMessage } from '@rocket.chat/core-typings';
import { isE2EEMessage, isFileAttachment } from '@rocket.chat/core-typings';
import { Emitter } from '@rocket.chat/emitter';
import EJSON from 'ejson';
import { Meteor } from 'meteor/meteor';
Expand Down Expand Up @@ -422,19 +422,60 @@ class E2E extends Emitter {

const data = await e2eRoom.decrypt(message.msg);

if (!data) {
return message;
}

const decryptedMessage: IE2EEMessage = {
...message,
msg: data.text,
e2e: 'done',
...(data && {
msg: data.text,
e2e: 'done',
}),
};

const decryptedMessageWithQuote = await this.parseQuoteAttachment(decryptedMessage);

return decryptedMessageWithQuote;
const decryptedMessageWithAttachments = await this.decryptMessageAttachments(decryptedMessageWithQuote);

return decryptedMessageWithAttachments;
}

async decryptMessageAttachments(message: IMessage): Promise<IMessage> {
const { attachments } = message;

if (!attachments || !attachments.length) {

Check warning on line 443 in apps/meteor/app/e2e/client/rocketchat.e2e.ts

View workflow job for this annotation

GitHub Actions / 🔎 Code Check / Code Lint

Prefer using an optional chain expression instead, as it's more concise and easier to read
return message;
}

const e2eRoom = await this.getInstanceByRoomId(message.rid);

if (!e2eRoom) {
return message;
}

const decryptedAttachments = await Promise.all(
attachments.map(async (attachment) => {
if (!isFileAttachment(attachment)) {
return attachment;
}

if (!attachment.description) {
return attachment;
}

const data = await e2eRoom.decrypt(attachment.description);

if (!data) {
return attachment;
}

attachment.description = data.text;
return attachment;
}),
);

return {
...message,
attachments: decryptedAttachments,
e2e: 'done',
};
}

async decryptPendingMessages(): Promise<void> {
Expand Down
14 changes: 12 additions & 2 deletions apps/meteor/app/file-upload/server/methods/sendFileMessage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import type { MessageAttachment, FileAttachmentProps, IUser, IUpload, AtLeast, FilesAndAttachments } from '@rocket.chat/core-typings';
import type {
MessageAttachment,
FileAttachmentProps,
IUser,
IUpload,
AtLeast,
FilesAndAttachments,
IMessage,
} from '@rocket.chat/core-typings';
import { Rooms, Uploads, Users } from '@rocket.chat/models';
import type { ServerMethods } from '@rocket.chat/ui-contexts';
import { Match, check } from 'meteor/check';
Expand Down Expand Up @@ -178,6 +186,8 @@ export const sendFileMessage = async (
msg: Match.Optional(String),
tmid: Match.Optional(String),
customFields: Match.Optional(String),
t: Match.Optional(String),
e2e: Match.Optional(String),
}),
);

Expand All @@ -189,7 +199,7 @@ export const sendFileMessage = async (
file: files[0],
files,
attachments,
...msgData,
...(msgData as Partial<IMessage>),
...(msgData?.customFields && { customFields: JSON.parse(msgData.customFields) }),
msg: msgData?.msg ?? '',
groupable: msgData?.groupable ?? false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ export class ImportDataConverter {
}

const userId = await this.insertUser(data);
data._id = userId;
insertedIds.add(userId);

if (!this._options.skipDefaultChannels) {
Expand Down
5 changes: 4 additions & 1 deletion apps/meteor/app/livechat/imports/server/rest/inquiries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ API.v1.addRoute(
authRequired: true,
permissionsRequired: ['view-l-room'],
validateParams: isGETLivechatInquiriesQueuedParams,
deprecationVersion: '7.0.0',
deprecation: {
version: '7.0.0',
alternatives: ['livechat/inquiries.queuedForUser'],
},
},
{
async get() {
Expand Down
6 changes: 4 additions & 2 deletions apps/meteor/app/livechat/server/api/v1/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ API.v1.addRoute(

API.v1.addRoute(
'livechat/room.transfer',
{ validateParams: isPOSTLivechatRoomTransferParams, deprecationVersion: '7.0.0' },
{ validateParams: isPOSTLivechatRoomTransferParams, deprecation: { version: '7.0.0' } },
{
async post() {
const { rid, token, department } = this.bodyParams;
Expand Down Expand Up @@ -364,7 +364,9 @@ API.v1.addRoute(
authRequired: true,
permissionsRequired: ['change-livechat-room-visitor'],
validateParams: isPUTLivechatRoomVisitorParams,
deprecationVersion: '7.0.0',
deprecation: {
version: '7.0.0',
},
},
{
async put() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface IServiceProviderOptions {
metadataTemplate: string;
callbackUrl: string;

// The id attribute is filled midway through some operations
// The id and redirectUrl attributes are filled midway through some operations
id?: string;
redirectUrl?: string;
}
12 changes: 10 additions & 2 deletions apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class SAML {
case 'sloRedirect':
return this.processSLORedirectAction(req, res);
case 'authorize':
return this.processAuthorizeAction(res, service, samlObject);
return this.processAuthorizeAction(req, res, service, samlObject);
case 'validate':
return this.processValidateAction(req, res, service, samlObject);
default:
Expand Down Expand Up @@ -378,12 +378,20 @@ export class SAML {
}

private static async processAuthorizeAction(
req: IIncomingMessage,
res: ServerResponse,
service: IServiceProviderOptions,
samlObject: ISAMLAction,
): Promise<void> {
service.id = samlObject.credentialToken;

// Allow redirecting to internal domains when login process is complete
const { referer } = req.headers;
const siteUrl = settings.get<string>('Site_Url');
if (typeof referer === 'string' && referer.startsWith(siteUrl)) {
service.redirectUrl = referer;
}

const serviceProvider = new SAMLServiceProvider(service);
let url: string | undefined;

Expand Down Expand Up @@ -430,7 +438,7 @@ export class SAML {
};

await this.storeCredential(credentialToken, loginResult);
const url = Meteor.absoluteUrl(SAMLUtils.getValidationActionRedirectPath(credentialToken));
const url = Meteor.absoluteUrl(SAMLUtils.getValidationActionRedirectPath(credentialToken, service.redirectUrl));
res.writeHead(302, {
Location: url,
});
Expand Down
5 changes: 3 additions & 2 deletions apps/meteor/app/meteor-accounts-saml/server/lib/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ export class SAMLUtils {
return newTemplate;
}

public static getValidationActionRedirectPath(credentialToken: string): string {
public static getValidationActionRedirectPath(credentialToken: string, redirectUrl?: string): string {
const redirectUrlParam = redirectUrl ? `&redirectUrl=${encodeURIComponent(redirectUrl)}` : '';
// the saml_idp_credentialToken param is needed by the mobile app
return `saml/${credentialToken}?saml_idp_credentialToken=${credentialToken}`;
return `saml/${credentialToken}?saml_idp_credentialToken=${credentialToken}${redirectUrlParam}`;
}

public static log(obj: any, ...args: Array<any>): void {
Expand Down
Loading

0 comments on commit ef99b59

Please sign in to comment.