Skip to content

Commit

Permalink
Merge branch 'develop' into fix/retention-threads
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris authored Jun 20, 2024
2 parents 7002dd5 + 1428778 commit 1dc145d
Show file tree
Hide file tree
Showing 36 changed files with 279 additions and 63 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-cameras-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixed an issue where private encrypted room creation was being forced even when E2EE feature was disabled.
5 changes: 5 additions & 0 deletions .changeset/hungry-waves-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed file name being incorrectly sent from the client when uploading assets
6 changes: 6 additions & 0 deletions .changeset/plenty-buses-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Disable "Reply in direct message", "Copy link" and "Forward message" message menu items for encrypted messages as they don't apply to encrypted messages and also disable apps menu items and show a warning.
6 changes: 6 additions & 0 deletions .changeset/popular-bulldogs-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/i18n': patch
'@rocket.chat/meteor': patch
---

Disable slash commands in encrypted rooms and show a disabled warning.
24 changes: 16 additions & 8 deletions apps/meteor/app/livechat/server/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,22 @@ Meteor.startup(async () => {
});
await createDefaultBusinessHourIfNotExists();

settings.watch<boolean>('Livechat_enable_business_hours', async (value) => {
logger.debug(`Starting business hour manager ${value}`);
if (value) {
await businessHourManager.startManager();
return;
}
await businessHourManager.stopManager();
});
settings.watch<boolean>(
'Livechat_enable_business_hours',
async (value) => {
logger.debug(`Starting business hour manager ${value}`);
if (value) {
await businessHourManager.startManager();
return;
}
await businessHourManager.stopManager();
},
process.env.TEST_MODE === 'true'
? {
debounce: 10,
}
: undefined,
);

settings.watch<string>('Livechat_Routing_Method', () => {
void RoutingManager.startQueue();
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/ui-utils/client/lib/MessageAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type MessageActionContext =

type MessageActionType = 'communication' | 'interaction' | 'duplication' | 'apps' | 'management';

type MessageActionConditionProps = {
export type MessageActionConditionProps = {
message: IMessage;
user: IUser | undefined;
room: IRoom;
Expand Down Expand Up @@ -65,6 +65,7 @@ export type MessageActionConfig = {
) => any;
condition?: (props: MessageActionConditionProps) => Promise<boolean> | boolean;
type?: MessageActionType;
disabled?: (props: MessageActionConditionProps) => boolean;
};

class MessageAction {
Expand Down
11 changes: 10 additions & 1 deletion apps/meteor/app/ui-utils/client/lib/messageActionDefault.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { IMessage } from '@rocket.chat/core-typings';
import { isRoomFederated } from '@rocket.chat/core-typings';
import { isE2EEMessage, isRoomFederated } from '@rocket.chat/core-typings';
import { Meteor } from 'meteor/meteor';
import moment from 'moment';

Expand Down Expand Up @@ -63,6 +63,9 @@ Meteor.startup(async () => {
},
order: 0,
group: 'menu',
disabled({ message }) {
return isE2EEMessage(message);
},
});

MessageAction.addButton({
Expand All @@ -87,6 +90,9 @@ Meteor.startup(async () => {
},
order: 0,
group: 'message',
disabled({ message }) {
return isE2EEMessage(message);
},
});

MessageAction.addButton({
Expand Down Expand Up @@ -139,6 +145,9 @@ Meteor.startup(async () => {
},
order: 5,
group: 'menu',
disabled({ message }) {
return isE2EEMessage(message);
},
});

MessageAction.addButton({
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/components/GenericMenu/GenericMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const GenericMenu = ({ title, icon = 'menu', disabled, onAction, ...props }: Gen

const hasIcon = itemsList.some(({ icon }) => icon);
const handleItems = (items: GenericMenuItemProps[]) =>
hasIcon ? items.map((item) => ({ ...item, gap: !item.icon && !item.status })) : items;
hasIcon ? items.map((item) => ({ ...item, gap: item.gap ?? (!item.icon && !item.status) })) : items;

const isMenuEmpty = !(sections && sections.length > 0) && !(items && items.length > 0);

Expand Down
5 changes: 3 additions & 2 deletions apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ export type GenericMenuItemProps = {
disabled?: boolean;
description?: ReactNode;
gap?: boolean;
tooltip?: string;
};

const GenericMenuItem = ({ icon, content, addon, status, gap }: GenericMenuItemProps) => (
const GenericMenuItem = ({ icon, content, addon, status, gap, tooltip }: GenericMenuItemProps) => (
<>
{gap && <MenuItemColumn />}
{icon && <MenuItemIcon name={icon} />}
{status && <MenuItemColumn>{status}</MenuItemColumn>}
{content && <MenuItemContent>{content}</MenuItemContent>}
{content && <MenuItemContent title={tooltip}>{content}</MenuItemContent>}
{addon && <MenuItemInput>{addon}</MenuItemInput>}
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useUniqueId } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { MouseEvent, ReactElement } from 'react';
import React from 'react';

import type { MessageActionConfig } from '../../../../app/ui-utils/client/lib/MessageAction';
import type { MessageActionConditionProps, MessageActionConfig } from '../../../../app/ui-utils/client/lib/MessageAction';
import GenericMenu from '../../GenericMenu/GenericMenu';
import type { GenericMenuItemProps } from '../../GenericMenu/GenericMenuItem';

Expand All @@ -19,11 +20,13 @@ type MessageActionSection = {
type MessageActionMenuProps = {
onChangeMenuVisibility: (visible: boolean) => void;
options: MessageActionConfigOption[];
context: MessageActionConditionProps;
isMessageEncrypted: boolean;
};

const MessageActionMenu = ({ options, onChangeMenuVisibility }: MessageActionMenuProps): ReactElement => {
const MessageActionMenu = ({ options, onChangeMenuVisibility, context, isMessageEncrypted }: MessageActionMenuProps): ReactElement => {
const t = useTranslation();

const id = useUniqueId();
const groupOptions = options
.map((option) => ({
variant: option.color === 'alert' ? 'danger' : '',
Expand All @@ -32,6 +35,9 @@ const MessageActionMenu = ({ options, onChangeMenuVisibility }: MessageActionMen
content: t(option.label),
onClick: option.action,
type: option.type,
...(option.disabled && { disabled: option?.disabled?.(context) }),
...(option.disabled &&
option?.disabled?.(context) && { tooltip: t('Action_not_available_encrypted_content', { action: t(option.label) }) }),
}))
.reduce((acc, option) => {
const group = option.type ? option.type : '';
Expand All @@ -44,7 +50,31 @@ const MessageActionMenu = ({ options, onChangeMenuVisibility }: MessageActionMen
acc.push(newSection);

return acc;
}, [] as unknown as MessageActionSection[]);
}, [] as unknown as MessageActionSection[])
.map((section) => {
if (section.id !== 'apps') {
return section;
}

if (!isMessageEncrypted) {
return section;
}

return {
id: 'apps',
title: t('Apps'),
items: [
{
content: t('Unavailable'),
type: 'apps',
id,
disabled: true,
gap: false,
tooltip: t('Action_not_available_encrypted_content', { action: t('Apps') }),
},
],
};
});

return (
<GenericMenu
Expand Down
11 changes: 9 additions & 2 deletions apps/meteor/client/components/message/toolbar/MessageToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useToolbar } from '@react-aria/toolbar';
import type { IMessage, IRoom, ISubscription, ITranslatedMessage } from '@rocket.chat/core-typings';
import { isThreadMessage, isRoomFederated, isVideoConfMessage } from '@rocket.chat/core-typings';
import { isThreadMessage, isRoomFederated, isVideoConfMessage, isE2EEMessage } from '@rocket.chat/core-typings';
import { MessageToolbar as FuselageMessageToolbar, MessageToolbarItem } from '@rocket.chat/fuselage';
import { useFeaturePreview } from '@rocket.chat/ui-client';
import { useUser, useSettings, useTranslation, useMethod, useLayoutHiddenActions } from '@rocket.chat/ui-contexts';
Expand Down Expand Up @@ -125,9 +125,14 @@ const MessageToolbar = ({
onClick={(e): void => action.action(e, { message, tabbar: toolbox, room, chat, autoTranslateOptions })}
key={action.id}
icon={action.icon}
title={t(action.label)}
title={
action?.disabled?.({ message, room, user, subscription, settings: mapSettings, chat, context })
? t('Action_not_available_encrypted_content', { action: t(action.label) })
: t(action.label)
}
data-qa-id={action.label}
data-qa-type='message-action-menu'
disabled={action?.disabled?.({ message, room, user, subscription, settings: mapSettings, chat, context })}
/>
))}
{actionsQueryResult.isSuccess && actionsQueryResult.data.menu.length > 0 && (
Expand All @@ -138,6 +143,8 @@ const MessageToolbar = ({
}))}
onChangeMenuVisibility={onChangeMenuVisibility}
data-qa-type='message-action-menu-options'
context={{ message, room, user, subscription, settings: mapSettings, chat, context }}
isMessageEncrypted={isE2EEMessage(message)}
/>
)}
</FuselageMessageToolbar>
Expand Down
10 changes: 9 additions & 1 deletion apps/meteor/client/lib/chats/ChatAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,15 @@ export type ChatAPI = {

readonly flows: {
readonly uploadFiles: (files: readonly File[], resetFileInput?: () => void) => Promise<void>;
readonly sendMessage: ({ text, tshow }: { text: string; tshow?: boolean; previewUrls?: string[] }) => Promise<boolean>;
readonly sendMessage: ({
text,
tshow,
}: {
text: string;
tshow?: boolean;
previewUrls?: string[];
isSlashCommandAllowed?: boolean;
}) => Promise<boolean>;
readonly processSlashCommand: (message: IMessage, userId: string | null) => Promise<boolean>;
readonly processTooLongMessage: (message: IMessage) => Promise<boolean>;
readonly processMessageEditing: (
Expand Down
13 changes: 9 additions & 4 deletions apps/meteor/client/lib/chats/flows/sendMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { processSetReaction } from './processSetReaction';
import { processSlashCommand } from './processSlashCommand';
import { processTooLongMessage } from './processTooLongMessage';

const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[]): Promise<void> => {
const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[], isSlashCommandAllowed?: boolean): Promise<void> => {
KonchatNotification.removeRoomNotification(message.rid);

if (await processSetReaction(chat, message)) {
Expand All @@ -25,7 +25,7 @@ const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[])
return;
}

if (await processSlashCommand(chat, message)) {
if (isSlashCommandAllowed && (await processSlashCommand(chat, message))) {
return;
}

Expand All @@ -34,7 +34,12 @@ const process = async (chat: ChatAPI, message: IMessage, previewUrls?: string[])

export const sendMessage = async (
chat: ChatAPI,
{ text, tshow, previewUrls }: { text: string; tshow?: boolean; previewUrls?: string[] },
{
text,
tshow,
previewUrls,
isSlashCommandAllowed,
}: { text: string; tshow?: boolean; previewUrls?: string[]; isSlashCommandAllowed?: boolean },
): Promise<boolean> => {
if (!(await chat.data.isSubscribedToRoom())) {
try {
Expand Down Expand Up @@ -63,7 +68,7 @@ export const sendMessage = async (
});

try {
await process(chat, message, previewUrls);
await process(chat, message, previewUrls, isSlashCommandAllowed);
chat.composer?.dismissAllQuotedMessages();
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const CreateChannelModal = ({ teamId = '', onClose, reload }: CreateChannelModal
const namesValidation = useSetting('UTF8_Channel_Names_Validation');
const allowSpecialNames = useSetting('UI_Allow_room_names_with_special_chars');
const federationEnabled = useSetting<boolean>('Federation_Matrix_enabled') || false;
const e2eEnabledForPrivateByDefault = useSetting('E2E_Enabled_Default_PrivateRooms');
const e2eEnabledForPrivateByDefault = useSetting('E2E_Enabled_Default_PrivateRooms') && e2eEnabled;

const canCreateChannel = usePermission('create-c');
const canCreatePrivateChannel = usePermission('create-p');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function AssetSettingInput({ _id, label, value, asset, required, disabled, fileC
dispatchToastMessage({ type: 'info', message: t('Uploading_file') });

const fileData = new FormData();
fileData.append('asset', blob, asset);
fileData.append('asset', blob, blob.name);
fileData.append('assetName', asset);

try {
Expand Down
11 changes: 10 additions & 1 deletion apps/meteor/client/views/room/composer/ComposerBoxPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type ComposerBoxPopupProps<
T extends {
_id: string;
sort?: number;
disabled?: boolean;
},
> = {
title?: string;
Expand All @@ -22,6 +23,7 @@ function ComposerBoxPopup<
T extends {
_id: string;
sort?: number;
disabled?: boolean;
},
>({
title,
Expand All @@ -37,7 +39,9 @@ function ComposerBoxPopup<

const variant = popupSizes && popupSizes.inlineSize < 480 ? 'small' : 'large';

const getOptionTitle = <T extends { _id: string; sort?: number; outside?: boolean; suggestion?: boolean }>(item: T) => {
const getOptionTitle = <T extends { _id: string; sort?: number; outside?: boolean; suggestion?: boolean; disabled?: boolean }>(
item: T,
) => {
if (variant !== 'small') {
return undefined;
}
Expand All @@ -49,6 +53,10 @@ function ComposerBoxPopup<
if (item.suggestion) {
return t('Suggestion_from_recent_messages');
}

if (item.disabled) {
return t('Unavailable_in_encrypted_channels');
}
};

const itemsFlat = useMemo(
Expand Down Expand Up @@ -96,6 +104,7 @@ function ComposerBoxPopup<
id={`popup-item-${item._id}`}
tabIndex={item === focused ? 0 : -1}
aria-selected={item === focused}
disabled={item.disabled}
>
{renderItem({ item: { ...item, variant } })}
</Option>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { OptionColumn, OptionContent, OptionDescription, OptionInput } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';

export type ComposerBoxPopupSlashCommandProps = {
_id: string;
description?: string;
params?: string;
disabled?: boolean;
};

function ComposerBoxPopupSlashCommand({ _id, description, params }: ComposerBoxPopupSlashCommandProps) {
function ComposerBoxPopupSlashCommand({ _id, description, params, disabled }: ComposerBoxPopupSlashCommandProps) {
const t = useTranslation();

return (
<>
<OptionContent>
{_id} <OptionDescription>{params}</OptionDescription>
</OptionContent>
<OptionColumn>
<OptionInput>{description}</OptionInput>
<OptionInput>{disabled ? t('Unavailable_in_encrypted_channels') : description}</OptionInput>
</OptionColumn>
</>
);
Expand Down
Loading

0 comments on commit 1dc145d

Please sign in to comment.