Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Disabling not supported features in federated channels #27204

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/meteor/app/e2e/client/tabbar.ts
@@ -1,6 +1,7 @@
import { useMemo, useCallback } from 'react';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useSetting, usePermission, useEndpoint } from '@rocket.chat/ui-contexts';
import { isRoomFederated } from '@rocket.chat/core-typings';

import { addAction } from '../../../client/views/room/lib/Toolbox';
import { useReactiveValue } from '../../../client/hooks/useReactiveValue';
Expand All @@ -12,6 +13,7 @@ addAction('e2e', ({ room }) => {
const canToggleE2e = usePermission('toggle-room-e2e-encryption', room._id);
const canEditRoom = usePermission('edit-room', room._id);
const hasPermission = (room.t === 'd' || (canEditRoom && canToggleE2e)) && e2eReady;
const federated = isRoomFederated(room);

const toggleE2E = useEndpoint('POST', '/v1/rooms.saveRoomSettings');

Expand All @@ -31,8 +33,12 @@ addAction('e2e', ({ room }) => {
icon: 'key',
order: 13,
action,
...(federated && {
'data-tooltip': 'E2E_unavailable_for_federation',
'disabled': true,
}),
}
: null,
[action, e2eEnabled, enabledOnRoom, hasPermission],
[action, e2eEnabled, enabledOnRoom, hasPermission, federated],
);
});
12 changes: 10 additions & 2 deletions apps/meteor/app/otr/client/tabBar.ts
@@ -1,12 +1,16 @@
import { useMemo, lazy, useEffect } from 'react';
import { useSetting } from '@rocket.chat/ui-contexts';
import type { IRoom, ISubscription } from '@rocket.chat/core-typings';
import { isRoomFederated } from '@rocket.chat/core-typings';

import OTR from './OTR';
import { addAction } from '../../../client/views/room/lib/Toolbox';

const template = lazy(() => import('../../../client/views/room/contextualBar/OTR'));

addAction('otr', () => {
addAction('otr', (options) => {
const room = options.room as unknown as ISubscription & IRoom;
const federated = isRoomFederated(room);
const enabled = useSetting('OTR_Enable') as boolean;

const shouldAddAction = enabled && Boolean(global.crypto);
Expand All @@ -26,8 +30,12 @@ addAction('otr', () => {
template,
order: 13,
full: true,
...(federated && {
'data-tooltip': 'OTR_unavailable_for_federation',
'disabled': true,
}),
}
: null,
[shouldAddAction],
[shouldAddAction, federated],
);
});
Expand Up @@ -24,7 +24,7 @@ type UserAutoCompleteOptions = {
[k: string]: UserAutoCompleteOptionType;
};

const matrixRegex = new RegExp('(.*:.*)');
const matrixRegex = new RegExp('@(.*:.*)');

const UserAutoCompleteMultipleFederated = ({
onChange,
Expand Down
12 changes: 10 additions & 2 deletions apps/meteor/client/components/avatar/RoomAvatarEditor.tsx
@@ -1,3 +1,4 @@
import { isRoomFederated } from '@rocket.chat/core-typings';
import type { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings';
import { css } from '@rocket.chat/css-in-js';
import { Box, Button, ButtonGroup, Icon } from '@rocket.chat/fuselage';
Expand Down Expand Up @@ -60,12 +61,19 @@ const RoomAvatarEditor = ({ room, roomAvatar, onChangeAvatar }: RoomAvatarEditor
m='x12'
>
<ButtonGroup>
<Button small title={t('Upload_user_avatar')} onClick={clickUpload}>
<Button disabled={isRoomFederated(room)} small title={t('Upload_user_avatar')} onClick={clickUpload}>
<Icon name='upload' size='x16' />
{t('Upload')}
</Button>

<Button primary small danger title={t('Accounts_SetDefaultAvatar')} disabled={roomAvatar === null} onClick={clickReset}>
<Button
primary
small
danger
title={t('Accounts_SetDefaultAvatar')}
disabled={roomAvatar === null || isRoomFederated(room)}
onClick={clickReset}
>
<Icon name='trash' size='x16' />
</Button>
</ButtonGroup>
Expand Down
Expand Up @@ -287,6 +287,8 @@ function EditChannel({ room, onClickClose, onClickBack }) {
handleRetentionMaxAge(Math.max(1, Number(e.currentTarget.value)));
});

const isFederated = useMemo(() => isRoomFederated(room), [room]);

return (
<>
<VerticalBar.Header>
Expand All @@ -309,15 +311,15 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Field>
<Field.Label>{t('Description')}</Field.Label>
<Field.Row>
<TextAreaInput rows={4} value={roomDescription} onChange={handleRoomDescription} flexGrow={1} />
<TextAreaInput disabled={isFederated} rows={4} value={roomDescription} onChange={handleRoomDescription} flexGrow={1} />
</Field.Row>
</Field>
)}
{canViewAnnouncement && (
<Field>
<Field.Label>{t('Announcement')}</Field.Label>
<Field.Row>
<TextAreaInput rows={4} value={roomAnnouncement} onChange={handleRoomAnnouncement} flexGrow={1} />
<TextAreaInput disabled={isFederated} rows={4} value={roomAnnouncement} onChange={handleRoomAnnouncement} flexGrow={1} />
</Field.Row>
</Field>
)}
Expand All @@ -334,7 +336,7 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' flexGrow={1}>
<Field.Label>{t('Private')}</Field.Label>
<Field.Row>
<ToggleSwitch disabled={!canChangeType || isRoomFederated(room)} checked={roomType === 'p'} onChange={changeRoomType} />
<ToggleSwitch disabled={!canChangeType || isFederated} checked={roomType === 'p'} onChange={changeRoomType} />
</Field.Row>
</Box>
<Field.Hint>{t('Teams_New_Private_Description_Enabled')}</Field.Hint>
Expand All @@ -345,7 +347,7 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' flexGrow={1}>
<Field.Label>{t('Read_only')}</Field.Label>
<Field.Row>
<ToggleSwitch disabled={!canSetRo || isRoomFederated(room)} checked={readOnly} onChange={handleReadOnly} />
<ToggleSwitch disabled={!canSetRo || isFederated} checked={readOnly} onChange={handleReadOnly} />
</Field.Row>
</Box>
<Field.Hint>{t('Only_authorized_users_can_write_new_messages')}</Field.Hint>
Expand Down Expand Up @@ -377,7 +379,7 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' flexGrow={1}>
<Field.Label>{t('Password_to_access')}</Field.Label>
<Field.Row>
<ToggleSwitch checked={joinCodeRequired} onChange={handleJoinCodeRequired} />
<ToggleSwitch disabled={isFederated} checked={joinCodeRequired} onChange={handleJoinCodeRequired} />
</Field.Row>
</Box>
<Field.Row>
Expand All @@ -396,14 +398,14 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' flexGrow={1}>
<Field.Label>{t('Hide_System_Messages')}</Field.Label>
<Field.Row>
<ToggleSwitch checked={hideSysMes} onChange={handleHideSysMes} />
<ToggleSwitch checked={hideSysMes} disabled={isFederated} onChange={handleHideSysMes} />
</Field.Row>
</Box>
<Field.Row>
<MultiSelect
maxWidth='100%'
options={sysMesOptions}
disabled={!hideSysMes}
disabled={!hideSysMes || isFederated}
value={systemMessages}
onChange={handleSystemMessages}
placeholder={t('Select_an_option')}
Expand All @@ -417,7 +419,7 @@ function EditChannel({ room, onClickClose, onClickBack }) {
<Box display='flex' flexDirection='row' justifyContent='space-between' flexGrow={1}>
<Field.Label>{t('Encrypted')}</Field.Label>
<Field.Row>
<ToggleSwitch disabled={!canToggleEncryption} checked={encrypted} onChange={handleEncrypted} />
<ToggleSwitch disabled={!canToggleEncryption || isFederated} checked={encrypted} onChange={handleEncrypted} />
</Field.Row>
</Box>
</Field>
Expand Down Expand Up @@ -495,7 +497,7 @@ function EditChannel({ room, onClickClose, onClickBack }) {
</Field>
<Field>
<Field.Row>
<Button flexGrow={1} danger disabled={!canDelete} onClick={handleDelete}>
<Button flexGrow={1} danger disabled={!canDelete || isFederated} onClick={handleDelete}>
<Icon name='trash' size='x16' />
{t('Delete')}
</Button>
Expand Down
@@ -1,3 +1,4 @@
import { isRoomFederated } from '@rocket.chat/core-typings';
import { Box, Callout, Menu, Option } from '@rocket.chat/fuselage';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React, { useMemo } from 'react';
Expand Down Expand Up @@ -25,6 +26,7 @@ const RoomInfo = ({
}) => {
const t = useTranslation();
const { name, fname, description, topic, archived, broadcast, announcement } = room;
const isFederated = isRoomFederated(room);

const { retentionPolicyEnabled, filesOnlyDefault, excludePinnedDefault, maxAgeDefault, retentionEnabledDefault } = retentionPolicy;

Expand All @@ -44,13 +46,14 @@ const RoomInfo = ({
action: onClickEdit,
},
}),
...(onClickDelete && {
delete: {
label: t('Delete'),
icon: 'trash',
action: onClickDelete,
},
}),
...(!isFederated &&
onClickDelete && {
delete: {
label: t('Delete'),
icon: 'trash',
action: onClickDelete,
},
}),
...(onClickMoveToTeam && {
move: {
label: t('Teams_move_channel_to_team'),
Expand Down Expand Up @@ -80,7 +83,7 @@ const RoomInfo = ({
},
}),
}),
[onClickEdit, t, onClickDelete, onClickMoveToTeam, onClickConvertToTeam, onClickHide, onClickLeave, onClickEnterRoom],
[onClickEdit, t, onClickDelete, onClickMoveToTeam, onClickConvertToTeam, onClickHide, onClickLeave, onClickEnterRoom, isFederated],
);

const { actions: actionsDefinition, menu: menuOptions } = useActionSpread(memoizedActions);
Expand Down
Expand Up @@ -17,6 +17,7 @@ type RoomMembersProps = {
rid: IRoom['_id'];
isTeam?: boolean;
isDirect?: boolean;
isFederated?: boolean;
loading: boolean;
text: string;
type: string;
Expand Down Expand Up @@ -52,6 +53,7 @@ const RoomMembers = ({
rid,
isTeam,
isDirect,
isFederated,
reload,
}: RoomMembersProps): ReactElement => {
const t = useTranslation();
Expand Down Expand Up @@ -147,7 +149,7 @@ const RoomMembers = ({
{!isDirect && (onClickInvite || onClickAdd) && (
<VerticalBar.Footer>
<ButtonGroup stretch>
{onClickInvite && (
{!isFederated && onClickInvite && (
<Button onClick={onClickInvite} width='50%'>
<Icon name='link' size='x20' mie='x4' />
{t('Invite_Link')}
Expand Down
Expand Up @@ -33,6 +33,7 @@ const RoomMembersWithData = ({ rid }: { rid: IRoom['_id'] }): ReactElement => {

const isTeam = room && isTeamRoom(room);
const isDirect = room && isDirectMessageRoom(room);
const isFederated = room && isRoomFederated(room);

const canCreateInviteLinks = usePermission('create-invite-links');

Expand All @@ -55,7 +56,7 @@ const RoomMembersWithData = ({ rid }: { rid: IRoom['_id'] }): ReactElement => {
);

const canAddUsers =
room && user && isRoomFederated(room) ? Federation.isEditableByTheUser(user, room) && hasPermissionToAddUsers : hasPermissionToAddUsers;
room && user && isFederated ? Federation.isEditableByTheUser(user, room) && hasPermissionToAddUsers : hasPermissionToAddUsers;

const handleTextChange = useCallback((event) => {
setText(event.currentTarget.value);
Expand Down Expand Up @@ -98,6 +99,7 @@ const RoomMembersWithData = ({ rid }: { rid: IRoom['_id'] }): ReactElement => {
rid={rid}
isTeam={isTeam}
isDirect={isDirect}
isFederated={isFederated}
loading={phase === AsyncStatePhase.LOADING}
type={type}
text={text}
Expand Down
2 changes: 2 additions & 0 deletions apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Expand Up @@ -1692,6 +1692,7 @@
"E2E_Reset_Email_Content": "You've been automatically logged out. When you login again, Rocket.Chat will generate a new key and restore your access to any encrypted room that has one or more members online. Due to the nature of the E2E encryption, Rocket.Chat will not be able to restore access to any encrypted room that has no member online.",
"E2E_Reset_Key_Explanation": "This option will remove your current E2E key and log you out. <BR/>When you login again, Rocket.Chat will generate you a new key and restore your access to any encrypted room that has one or more members online.<BR/>Due to the nature of the E2E encryption, Rocket.Chat will not be able to restore access to any encrypted room that has no member online.",
"E2E_Reset_Other_Key_Warning": "Reset the current E2E key will log out the user. When the user login again, Rocket.Chat will generate a new key and restore the user access to any encrypted room that has one or more members online. Due to the nature of the E2E encryption, Rocket.Chat will not be able to restore access to any encrypted room that has no member online.",
"E2E_unavailable_for_federation": "E2E is unavailable for federated rooms",
"ECDH_Enabled": "Enable second layer encryption for data transport",
"Edit": "Edit",
"Edit_Business_Hour": "Edit Business Hour",
Expand Down Expand Up @@ -3658,6 +3659,7 @@
"others": "others",
"Others": "Others",
"OTR": "OTR",
"OTR_unavailable_for_federation": "OTR is unavailable for federated rooms",
"OTR_Description": "Off-the-record chats are secure, private and disappear once ended.",
"OTR_Chat_Declined_Title": "OTR Chat invite Declined",
"OTR_Chat_Declined_Description": "%s declined OTR chat invite. For privacy protection local cache was deleted, including all related system messages.",
Expand Down