Skip to content

Commit

Permalink
Merge branch 'develop' into fix/color-tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris committed Jan 20, 2023
2 parents 5a6e4a8 + c1142a5 commit 0f7f9a2
Show file tree
Hide file tree
Showing 118 changed files with 2,174 additions and 675 deletions.
7 changes: 1 addition & 6 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,5 @@
}
],
"typescript.tsdk": "./node_modules/typescript/lib",
"cSpell.words": [
"livechat",
"omnichannel",
"photoswipe",
"tmid"
]
"cSpell.words": ["katex", "livechat", "omnichannel", "photoswipe", "tmid"]
}
30 changes: 28 additions & 2 deletions apps/meteor/app/2fa/client/overrideMeteorCall.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Meteor } from 'meteor/meteor';

import { t } from '../../utils/client';
import { process2faReturn } from '../../../client/lib/2fa/process2faReturn';
import { process2faReturn, process2faAsyncReturn } from '../../../client/lib/2fa/process2faReturn';
import { isTotpInvalidError } from '../../../client/lib/2fa/utils';

const { call } = Meteor;
const { call, callAsync } = Meteor;

type Callback = {
(error: unknown): void;
Expand Down Expand Up @@ -34,8 +34,34 @@ const callWithoutTotp = (methodName: string, args: unknown[], callback: Callback
});
});

const callAsyncWithTotp =
(methodName: string, args: unknown[]) =>
async (twoFactorCode: string, twoFactorMethod: string): Promise<unknown> => {
try {
const result = await callAsync(methodName, ...args, { twoFactorCode, twoFactorMethod });

return result;
} catch (error: unknown) {
if (isTotpInvalidError(error)) {
throw new Error(twoFactorMethod === 'password' ? t('Invalid_password') : t('Invalid_two_factor_code'));
}

throw error;
}
};

Meteor.call = function (methodName: string, ...args: unknown[]): unknown {
const callback = args.length > 0 && typeof args[args.length - 1] === 'function' ? (args.pop() as Callback) : (): void => undefined;

return callWithoutTotp(methodName, args, callback)();
};

Meteor.callAsync = async function _callAsyncWithTotp(methodName: string, ...args: unknown[]): Promise<unknown> {
const promise = callAsync(methodName, ...args);

return process2faAsyncReturn({
promise,
onCode: callAsyncWithTotp(methodName, args),
emailOrUsername: undefined,
});
};
35 changes: 35 additions & 0 deletions apps/meteor/app/api/server/v1/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import type { IUser } from '@rocket.chat/core-typings';

import { API } from '../api';
import { handleSuggestedGroupKey } from '../../../e2e/server/functions/handleSuggestedGroupKey';

API.v1.addRoute(
'e2e.fetchMyKeys',
Expand Down Expand Up @@ -195,3 +196,37 @@ API.v1.addRoute(
},
},
);

API.v1.addRoute(
'e2e.acceptSuggestedGroupKey',
{
authRequired: true,
validateParams: ise2eGetUsersOfRoomWithoutKeyParamsGET,
},
{
async post() {
const { rid } = this.bodyParams;

await handleSuggestedGroupKey('accept', rid, this.userId, 'e2e.acceptSuggestedGroupKey');

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

API.v1.addRoute(
'e2e.rejectSuggestedGroupKey',
{
authRequired: true,
validateParams: ise2eGetUsersOfRoomWithoutKeyParamsGET,
},
{
async post() {
const { rid } = this.bodyParams;

await handleSuggestedGroupKey('reject', rid, this.userId, 'e2e.rejectSuggestedGroupKey');

return API.v1.success();
},
},
);
33 changes: 24 additions & 9 deletions apps/meteor/app/autotranslate/client/lib/actionButton.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { isTranslatedMessage } from '@rocket.chat/core-typings';

import { AutoTranslate } from './autotranslate';
import { settings } from '../../../settings/client';
import { hasAtLeastOnePermission } from '../../../authorization/client';
import { MessageAction } from '../../../ui-utils/client/lib/MessageAction';
import { messageArgs } from '../../../../client/lib/utils/messageArgs';
import { Messages } from '../../../models/client';
import {
hasTranslationLanguageInAttachments,
hasTranslationLanguageInMessage,
} from '../../../../client/views/room/MessageList/lib/autoTranslate';

Meteor.startup(() => {
AutoTranslate.init();
Expand All @@ -22,21 +25,27 @@ Meteor.startup(() => {
action(_, props) {
const { message = messageArgs(this).msg } = props;
const language = AutoTranslate.getLanguage(message.rid);
if (!isTranslatedMessage(message) || !message.translations[language]) {
// } && !_.find(message.attachments, attachment => { return attachment.translations && attachment.translations[language]; })) {
if (!hasTranslationLanguageInMessage(message, language) && !hasTranslationLanguageInAttachments(message.attachments, language)) {
(AutoTranslate.messageIdsToWait as any)[message._id] = true;
Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } });
Meteor.call('autoTranslate.translateMessage', message, language);
}
const action = 'autoTranslateShowInverse' in message ? '$unset' : '$set';
Messages.update({ _id: message._id }, { [action]: { autoTranslateShowInverse: true } });
},
condition({ message, user }) {
condition({ message, subscription, user }) {
if (!user) {
return false;
}
const language = subscription?.autoTranslateLanguage || AutoTranslate.getLanguage(message.rid) || '';

return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && message.autoTranslateShowInverse);
return Boolean(
(message?.u &&
message.u._id !== user._id &&
subscription?.autoTranslate &&
(message as { autoTranslateShowInverse?: boolean }).autoTranslateShowInverse) ||
(!hasTranslationLanguageInMessage(message, language) && !hasTranslationLanguageInAttachments(message.attachments, language)),
);
},
order: 90,
});
Expand All @@ -48,21 +57,27 @@ Meteor.startup(() => {
action(_, props) {
const { message = messageArgs(this).msg } = props;
const language = AutoTranslate.getLanguage(message.rid);
if (!isTranslatedMessage(message) || !message.translations[language]) {
// } && !_.find(message.attachments, attachment => { return attachment.translations && attachment.translations[language]; })) {
if (!hasTranslationLanguageInMessage(message, language) && !hasTranslationLanguageInAttachments(message.attachments, language)) {
(AutoTranslate.messageIdsToWait as any)[message._id] = true;
Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } });
Meteor.call('autoTranslate.translateMessage', message, language);
}
const action = 'autoTranslateShowInverse' in message ? '$unset' : '$set';
Messages.update({ _id: message._id }, { [action]: { autoTranslateShowInverse: true } });
},
condition({ message, user }) {
condition({ message, subscription, user }) {
const language = subscription?.autoTranslateLanguage || AutoTranslate.getLanguage(message.rid) || '';
if (!user) {
return false;
}

return Boolean(message?.u && message.u._id !== user._id && isTranslatedMessage(message) && !message.autoTranslateShowInverse);
return Boolean(
message?.u &&
message.u._id !== user._id &&
subscription?.autoTranslate &&
!(message as { autoTranslateShowInverse?: boolean }).autoTranslateShowInverse &&
(hasTranslationLanguageInMessage(message, language) || hasTranslationLanguageInAttachments(message.attachments, language)),
);
},
order: 90,
});
Expand Down
30 changes: 14 additions & 16 deletions apps/meteor/app/autotranslate/client/lib/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ import type {
IUser,
MessageAttachmentDefault,
} from '@rocket.chat/core-typings';
import { isTranslatedMessageAttachment } from '@rocket.chat/core-typings';

import { Subscriptions, Messages } from '../../../models/client';
import { hasPermission } from '../../../authorization/client';
import { call } from '../../../../client/lib/utils/call';
import {
hasTranslationLanguageInAttachments,
hasTranslationLanguageInMessage,
} from '../../../../client/views/room/MessageList/lib/autoTranslate';

let userLanguage = 'en';
let username = '';
Expand Down Expand Up @@ -55,6 +60,9 @@ export const AutoTranslate = {
language: string,
autoTranslateShowInverse: boolean,
): MessageAttachmentDefault[] {
if (!isTranslatedMessageAttachment(attachments)) {
return attachments;
}
for (const attachment of attachments) {
if (attachment.author_name !== username) {
if (attachment.text && attachment.translations && attachment.translations[language]) {
Expand Down Expand Up @@ -134,16 +142,11 @@ export const createAutoTranslateMessageRenderer = (): ((message: ITranslatedMess
message.translations = {};
}
if (!!subscription?.autoTranslate !== !!message.autoTranslateShowInverse) {
const hasAttachmentsTranslate =
message.attachments?.some(
(attachment) =>
'translations' in attachment &&
typeof attachment.translations === 'object' &&
autoTranslateLanguage in attachment.translations,
) ?? false;

message.translations.original = message.html;
if (message.translations[autoTranslateLanguage] && !hasAttachmentsTranslate) {
if (
message.translations[autoTranslateLanguage] &&
!hasTranslationLanguageInAttachments(message.attachments, autoTranslateLanguage)
) {
message.html = message.translations[autoTranslateLanguage];
}

Expand All @@ -155,12 +158,6 @@ export const createAutoTranslateMessageRenderer = (): ((message: ITranslatedMess
);
}
}
} else if (message.attachments && message.attachments.length > 0) {
message.attachments = AutoTranslate.translateAttachments(
message.attachments,
autoTranslateLanguage,
!!message.autoTranslateShowInverse,
);
}
return message;
};
Expand All @@ -177,7 +174,8 @@ export const createAutoTranslateMessageStreamHandler = (): ((message: ITranslate
subscription &&
subscription.autoTranslate === true &&
message.msg &&
(!message.translations || !message.translations[language])
(!message.translations ||
(!hasTranslationLanguageInMessage(message, language) && !hasTranslationLanguageInAttachments(message.attachments, language)))
) {
// || (message.attachments && !_.find(message.attachments, attachment => { return attachment.translations && attachment.translations[language]; }))
Messages.update({ _id: message._id }, { $set: { autoTranslateFetching: true } });
Expand Down
7 changes: 5 additions & 2 deletions apps/meteor/app/autotranslate/server/autotranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,13 @@ export abstract class AutoTranslate {
Meteor.defer(() => {
for (const [index, attachment] of message.attachments?.entries() ?? []) {
if (attachment.description || attachment.text) {
const translations = this._translateAttachmentDescriptions(attachment, targetLanguages);
// Removes the initial link `[ ](quoterl)` from quote message before translation
const translatedText = attachment?.text?.replace(/\[(.*?)\]\(.*?\)/g, '$1') || attachment?.text;
const attachmentMessage = { ...attachment, text: translatedText };
const translations = this._translateAttachmentDescriptions(attachmentMessage, targetLanguages);

if (!_.isEmpty(translations)) {
Messages.addAttachmentTranslations(message._id, index, translations);
Messages.addTranslations(message._id, translations, TranslationProviderRegistry[Provider]);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions apps/meteor/app/autotranslate/server/googleTranslate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class GoogleAutoTranslate extends AutoTranslate {
params: {
key: this.apiKey,
target: language,
format: 'text',
},
query,
});
Expand Down Expand Up @@ -190,6 +191,7 @@ class GoogleAutoTranslate extends AutoTranslate {
params: {
key: this.apiKey,
target: language,
format: 'text',
},
query,
});
Expand Down
8 changes: 6 additions & 2 deletions apps/meteor/app/e2e/client/rocketchat.e2e.room.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,8 @@ export class E2ERoom extends Emitter {
const decryptedKey = await decryptRSA(e2e.privateKey, groupKey);
this.sessionKeyExportedString = toString(decryptedKey);
} catch (error) {
return this.error('Error decrypting group key: ', error);
this.error('Error decrypting group key: ', error);
return false;
}

this.keyID = Base64.encode(this.sessionKeyExportedString).slice(0, 12);
Expand All @@ -275,8 +276,11 @@ export class E2ERoom extends Emitter {
// Key has been obtained. E2E is now in session.
this.groupSessionKey = key;
} catch (error) {
return this.error('Error importing group key: ', error);
this.error('Error importing group key: ', error);
return false;
}

return true;
}

async createGroupKey() {
Expand Down
12 changes: 12 additions & 0 deletions apps/meteor/app/e2e/client/rocketchat.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ class E2E extends Emitter {
});
}

async acceptSuggestedKey(rid: string): Promise<void> {
await APIClient.post('/v1/e2e.acceptSuggestedGroupKey', {
rid,
});
}

async rejectSuggestedKey(rid: string): Promise<void> {
await APIClient.post('/v1/e2e.rejectSuggestedGroupKey', {
rid,
});
}

getKeysFromLocalStorage(): KeyPair {
return {
public_key: Meteor._localStorage.getItem('public_key'),
Expand Down
29 changes: 29 additions & 0 deletions apps/meteor/app/e2e/server/functions/handleSuggestedGroupKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Meteor } from 'meteor/meteor';
import { Subscriptions } from '@rocket.chat/models';

export async function handleSuggestedGroupKey(
handle: 'accept' | 'reject',
rid: string,
userId: string | null,
method: string,
): Promise<void> {
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method });
}

const sub = await Subscriptions.findOneByRoomIdAndUserId(rid, userId);
if (!sub) {
throw new Meteor.Error('error-subscription-not-found', 'Subscription not found', { method });
}

const suggestedKey = String(sub.E2ESuggestedKey ?? '').trim();
if (!suggestedKey) {
throw new Meteor.Error('error-no-suggested-key-available', 'No suggested key available', { method });
}

if (handle === 'accept') {
await Subscriptions.setGroupE2EKey(sub._id, suggestedKey);
}

await Subscriptions.unsetGroupE2ESuggestedKey(sub._id);
}
17 changes: 0 additions & 17 deletions apps/meteor/app/e2e/server/methods/updateGroupKey.js

This file was deleted.

Loading

0 comments on commit 0f7f9a2

Please sign in to comment.