Refactor the logic on RoomView and apply filters on ShareListView and forward message

This commit is contained in:
Diego Mello 2024-04-19 16:07:46 -03:00
parent 15766e2f64
commit 24464a8859
4 changed files with 99 additions and 46 deletions

View File

@ -501,6 +501,26 @@ class Encryption {
// Decrypt multiple subscriptions
decryptSubscriptions = (subscriptions: ISubscription[]) => Promise.all(subscriptions.map(s => this.decryptSubscription(s)));
// Missing room encryption key
isMissingRoomE2EEKey = ({
encryptionEnabled,
roomEncrypted,
E2EKey
}: {
encryptionEnabled: boolean;
roomEncrypted: TSubscriptionModel['encrypted'];
E2EKey: TSubscriptionModel['E2EKey'];
}) => (encryptionEnabled && roomEncrypted && !E2EKey) ?? false;
// Encrypted room, but user session is not encrypted
isE2EEDisabledEncryptedRoom = ({
encryptionEnabled,
roomEncrypted
}: {
encryptionEnabled: boolean;
roomEncrypted: TSubscriptionModel['encrypted'];
}) => (!encryptionEnabled && roomEncrypted) ?? false;
}
const encryption = new Encryption();

View File

@ -6,6 +6,7 @@ import { store as reduxStore } from '../store/auxStore';
import { spotlight } from '../services/restApi';
import { ISearch, ISearchLocal, IUserMessage, SubscriptionType, TSubscriptionModel } from '../../definitions';
import { isGroupChat, isReadOnly } from './helpers';
import { Encryption } from '../encryption';
export type TSearch = ISearchLocal | IUserMessage | ISearch;
@ -46,10 +47,21 @@ export const localSearchSubscription = async ({
if (filterMessagingAllowed) {
const username = reduxStore.getState().login.user.username as string;
const encryptionEnabled = reduxStore.getState().encryption.enabled as boolean;
const filteredSubscriptions = await Promise.all(
subscriptions.map(async item => {
const isItemReadOnly = await isReadOnly(item, username);
return isItemReadOnly ? null : item;
if (await isReadOnly(item, username)) {
return null;
}
if (Encryption.isMissingRoomE2EEKey({ encryptionEnabled, roomEncrypted: item.encrypted, E2EKey: item.E2EKey })) {
return null;
}
if (Encryption.isE2EEDisabledEncryptedRoom({ encryptionEnabled, roomEncrypted: item.encrypted })) {
return null;
}
return item;
})
);
subscriptions = filteredSubscriptions.filter(item => item !== null) as TSubscriptionModel[];

View File

@ -98,6 +98,7 @@ import AudioManager from '../../lib/methods/AudioManager';
import { IListContainerRef, TListRef } from './List/definitions';
import { getMessageById } from '../../lib/database/services/Message';
import { getThreadById } from '../../lib/database/services/Thread';
import { Encryption } from '../../lib/encryption';
import { clearInAppFeedback, removeInAppFeedback } from '../../actions/inAppFeedback';
import UserPreferences from '../../lib/methods/userPreferences';
import { IRoomViewProps, IRoomViewState } from './definitions';
@ -414,17 +415,19 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
return hideSystemMessages ?? [];
}
get missingRoomE2EEKey() {
hasE2EEWarning = () => {
const { room } = this.state;
const { encryptionEnabled } = this.props;
return (encryptionEnabled && 'encrypted' in room && room.encrypted && 'E2EKey' in room && !room.E2EKey) ?? false;
}
get e2eeDisabledEncryptedRoom() {
const { room } = this.state;
const { encryptionEnabled } = this.props;
return (!encryptionEnabled && 'encrypted' in room && room.encrypted) ?? false;
}
if ('encrypted' in room) {
if (Encryption.isMissingRoomE2EEKey({ encryptionEnabled, roomEncrypted: room.encrypted, E2EKey: room.E2EKey })) {
return true;
}
if (Encryption.isE2EEDisabledEncryptedRoom({ encryptionEnabled, roomEncrypted: room.encrypted })) {
return true;
}
}
return false;
};
setHeader = () => {
const { room, unreadsCount, roomUserId, joined, canForwardGuest, canReturnQueue, canPlaceLivechatOnHold } = this.state;
@ -513,7 +516,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
onPress={this.goRoomActionsView}
testID={`room-view-title-${title}`}
sourceType={sourceType}
disabled={this.missingRoomE2EEKey || this.e2eeDisabledEncryptedRoom || !!tmid}
disabled={this.hasE2EEWarning() || !!tmid}
/>
),
headerRight: () => (
@ -531,7 +534,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
showActionSheet={this.showActionSheet}
departmentId={departmentId}
notificationsDisabled={iSubRoom?.disableNotifications}
disabled={this.missingRoomE2EEKey || this.e2eeDisabledEncryptedRoom}
disabled={this.hasE2EEWarning()}
/>
)
});
@ -1389,8 +1392,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
<Touch
onPress={this.resumeRoom}
style={[styles.joinRoomButton, { backgroundColor: themes[theme].actionTintColor }]}
enabled={!loading}
>
enabled={!loading}>
<Text style={[styles.joinRoomText, { color: themes[theme].buttonText }]} testID='room-view-chat-on-hold-button'>
{I18n.t('Resume')}
</Text>
@ -1405,8 +1407,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
<Touch
onPress={this.joinRoom}
style={[styles.joinRoomButton, { backgroundColor: themes[theme].actionTintColor }]}
enabled={!loading}
>
enabled={!loading}>
<Text style={[styles.joinRoomText, { color: themes[theme].buttonText }]} testID='room-view-join-button'>
{I18n.t(this.isOmnichannel ? 'Take_it' : 'Join')}
</Text>
@ -1460,7 +1461,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
render() {
console.count(`${this.constructor.name}.render calls`);
const { room, loading, action, selectedMessages } = this.state;
const { user, baseUrl, theme, width, serverVersion, navigation } = this.props;
const { user, baseUrl, theme, width, serverVersion, navigation, encryptionEnabled } = this.props;
const { rid, t } = room;
let bannerClosed;
let announcement;
@ -1468,14 +1469,16 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
({ bannerClosed, announcement } = room);
}
// Missing room encryption key
if (this.missingRoomE2EEKey) {
return <MissingRoomE2EEKey />;
}
if ('encrypted' in room) {
// Missing room encryption key
if (Encryption.isMissingRoomE2EEKey({ encryptionEnabled, roomEncrypted: room.encrypted, E2EKey: room.E2EKey })) {
return <MissingRoomE2EEKey />;
}
// Encrypted room, but user session is not encrypted
if (this.e2eeDisabledEncryptedRoom) {
return <EncryptedRoom navigation={navigation} roomName={getRoomTitle(room)} />;
// Encrypted room, but user session is not encrypted
if (Encryption.isE2EEDisabledEncryptedRoom({ encryptionEnabled, roomEncrypted: room.encrypted })) {
return <EncryptedRoom navigation={navigation} roomName={getRoomTitle(room)} />;
}
}
return (
@ -1493,8 +1496,7 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
onSendMessage: this.handleSendMessage,
setQuotesAndText: this.setQuotesAndText,
getText: this.getText
}}
>
}}>
<SafeAreaView style={{ backgroundColor: themes[theme].backgroundColor }} testID='room-view'>
<StatusBar />
<Banner title={I18n.t('Announcement')} text={announcement} bannerClosed={bannerClosed} closeBanner={this.closeBanner} />

View File

@ -1,4 +1,5 @@
import React from 'react';
import { Dispatch } from 'redux';
import { StackNavigationProp } from '@react-navigation/stack';
import { BackHandler, FlatList, Keyboard, ScrollView, Text, View } from 'react-native';
import ShareExtension from 'rn-extensions-share';
@ -20,11 +21,13 @@ import { animateNextTransition } from '../../lib/methods/helpers/layoutAnimation
import { TSupportedThemes, withTheme } from '../../theme';
import SafeAreaView from '../../containers/SafeAreaView';
import { sanitizeLikeString } from '../../lib/database/utils';
import { Encryption } from '../../lib/encryption';
import styles from './styles';
import ShareListHeader from './Header';
import { TServerModel, TSubscriptionModel } from '../../definitions';
import { IApplicationState, TServerModel, TSubscriptionModel } from '../../definitions';
import { ShareInsideStackParamList } from '../../definitions/navigationTypes';
import { getRoomAvatar, isAndroid, isIOS, askAndroidMediaPermissions } from '../../lib/methods/helpers';
import { encryptionInit } from '../../actions/encryption';
interface IDataFromShare {
value: string;
@ -61,6 +64,8 @@ interface IShareListViewProps extends INavigationOption {
token: string;
userId: string;
theme: TSupportedThemes;
encryptionEnabled: boolean;
dispatch: Dispatch;
}
const getItemLayout = (data: any, index: number) => ({ length: data.length, offset: ROW_HEIGHT * index, index });
@ -97,8 +102,9 @@ class ShareListView extends React.Component<IShareListViewProps, IState> {
}
async componentDidMount() {
const { server } = this.props;
const { server, dispatch } = this.props;
try {
dispatch(encryptionInit());
const data = (await ShareExtension.data()) as IDataFromShare[];
if (isAndroid) {
await this.askForPermission(data);
@ -217,6 +223,7 @@ class ShareListView extends React.Component<IShareListViewProps, IState> {
};
query = async (text?: string) => {
const { encryptionEnabled } = this.props;
const db = database.active;
const defaultWhereClause = [
Q.where('archived', false),
@ -234,19 +241,30 @@ class ShareListView extends React.Component<IShareListViewProps, IState> {
.query(...defaultWhereClause)
.fetch()) as TSubscriptionModel[];
return data.map(item => ({
rid: item.rid,
t: item.t,
name: item.name,
fname: item.fname,
blocked: item.blocked,
blocker: item.blocker,
prid: item.prid,
uids: item.uids,
usernames: item.usernames,
topic: item.topic,
teamMain: item.teamMain
}));
return data
.map(item => {
if (Encryption.isMissingRoomE2EEKey({ encryptionEnabled, roomEncrypted: item.encrypted, E2EKey: item.E2EKey })) {
return null;
}
if (Encryption.isE2EEDisabledEncryptedRoom({ encryptionEnabled, roomEncrypted: item.encrypted })) {
return null;
}
return {
rid: item.rid,
t: item.t,
name: item.name,
fname: item.fname,
blocked: item.blocked,
blocker: item.blocker,
prid: item.prid,
uids: item.uids,
usernames: item.usernames,
topic: item.topic,
teamMain: item.teamMain
};
})
.filter(item => !!item);
};
getSubscriptions = async (server: string) => {
@ -465,10 +483,11 @@ class ShareListView extends React.Component<IShareListViewProps, IState> {
};
}
const mapStateToProps = ({ share }: any) => ({
userId: share.user && share.user.id,
token: share.user && share.user.token,
server: share.server.server
const mapStateToProps = ({ share, encryption }: IApplicationState) => ({
userId: share.user && (share.user.id as string),
token: share.user && (share.user.token as string),
server: share.server.server as string,
encryptionEnabled: encryption.enabled
});
export default connect(mapStateToProps)(withTheme(ShareListView));