Sfoglia il codice sorgente

feat(e2ee) disable e2ee when large number of participants

master
tmoldovan8x8 4 anni fa
parent
commit
5ad98d193a
Nessun account collegato all'indirizzo email del committer

+ 2
- 0
lang/main.json Vedi File

213
         "done": "Done",
213
         "done": "Done",
214
         "e2eeDescription": "End-to-End Encryption is currently EXPERIMENTAL. Please keep in mind that turning on end-to-end encryption will effectively disable server-side provided services such as: phone participation. Also keep in mind that the meeting will only work for people joining from browsers with support for insertable streams.",
214
         "e2eeDescription": "End-to-End Encryption is currently EXPERIMENTAL. Please keep in mind that turning on end-to-end encryption will effectively disable server-side provided services such as: phone participation. Also keep in mind that the meeting will only work for people joining from browsers with support for insertable streams.",
215
         "e2eeLabel": "Enable End-to-End Encryption",
215
         "e2eeLabel": "Enable End-to-End Encryption",
216
+        "e2eeDisabledDueToMaxModeDescription": "Cannot enable End-to-End Encryption due to large number of participants in the conference.",
216
         "e2eeWarning": "WARNING: Not all participants in this meeting seem to have support for End-to-End encryption. If you enable it they won't be able to see nor hear you.",
217
         "e2eeWarning": "WARNING: Not all participants in this meeting seem to have support for End-to-End encryption. If you enable it they won't be able to see nor hear you.",
218
+        "e2eeWillDisableDueToMaxModeDescription": "WARNING: End-to-End Encryption will be automatically disabled if more participants join the conference.",
217
         "enterDisplayName": "Enter your name here",
219
         "enterDisplayName": "Enter your name here",
218
         "embedMeeting": "Embed meeting",
220
         "embedMeeting": "Embed meeting",
219
         "error": "Error",
221
         "error": "Error",

+ 8
- 3
react/features/base/participants/middleware.js Vedi File

5
 import UIEvents from '../../../../service/UI/UIEvents';
5
 import UIEvents from '../../../../service/UI/UIEvents';
6
 import { approveParticipant } from '../../av-moderation/actions';
6
 import { approveParticipant } from '../../av-moderation/actions';
7
 import { toggleE2EE } from '../../e2ee/actions';
7
 import { toggleE2EE } from '../../e2ee/actions';
8
+import { MAX_MODE } from '../../e2ee/constants';
8
 import { NOTIFICATION_TIMEOUT, showNotification } from '../../notifications';
9
 import { NOTIFICATION_TIMEOUT, showNotification } from '../../notifications';
9
 import { isForceMuted } from '../../participants-pane/functions';
10
 import { isForceMuted } from '../../participants-pane/functions';
10
 import { CALLING, INVITED } from '../../presence-status';
11
 import { CALLING, INVITED } from '../../presence-status';
327
 /**
328
 /**
328
  * Handles a E2EE enabled status update.
329
  * Handles a E2EE enabled status update.
329
  *
330
  *
330
- * @param {Function} dispatch - The Redux dispatch function.
331
+ * @param {Store} store - The redux store.
331
  * @param {Object} conference - The conference for which we got an update.
332
  * @param {Object} conference - The conference for which we got an update.
332
  * @param {string} participantId - The ID of the participant from which we got an update.
333
  * @param {string} participantId - The ID of the participant from which we got an update.
333
  * @param {boolean} newValue - The new value of the E2EE enabled status.
334
  * @param {boolean} newValue - The new value of the E2EE enabled status.
334
  * @returns {void}
335
  * @returns {void}
335
  */
336
  */
336
-function _e2eeUpdated({ dispatch }, conference, participantId, newValue) {
337
+function _e2eeUpdated({ getState, dispatch }, conference, participantId, newValue) {
337
     const e2eeEnabled = newValue === 'true';
338
     const e2eeEnabled = newValue === 'true';
338
 
339
 
339
-    dispatch(toggleE2EE(e2eeEnabled));
340
+    const { maxMode } = getState()['features/e2ee'];
341
+
342
+    if (maxMode !== MAX_MODE.THRESHOLD_EXCEEDED || !e2eeEnabled) {
343
+        dispatch(toggleE2EE(e2eeEnabled));
344
+    }
340
 
345
 
341
     dispatch(participantUpdated({
346
     dispatch(participantUpdated({
342
         conference,
347
         conference,

+ 9
- 0
react/features/e2ee/actionTypes.js Vedi File

25
  * }
25
  * }
26
  */
26
  */
27
 export const SET_EVERYONE_SUPPORT_E2EE = 'SET_EVERYONE_SUPPORT_E2EE';
27
 export const SET_EVERYONE_SUPPORT_E2EE = 'SET_EVERYONE_SUPPORT_E2EE';
28
+
29
+/**
30
+ * The type of the action which signals to set new value E2EE maxMode.
31
+ *
32
+ * {
33
+ *     type: SET_MAX_MODE
34
+ * }
35
+ */
36
+export const SET_MAX_MODE = 'SET_MAX_MODE';

+ 14
- 1
react/features/e2ee/actions.js Vedi File

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { SET_EVERYONE_ENABLED_E2EE, SET_EVERYONE_SUPPORT_E2EE, TOGGLE_E2EE } from './actionTypes';
3
+import { SET_EVERYONE_ENABLED_E2EE, SET_EVERYONE_SUPPORT_E2EE, SET_MAX_MODE, TOGGLE_E2EE } from './actionTypes';
4
 
4
 
5
 /**
5
 /**
6
  * Dispatches an action to enable / disable E2EE.
6
  * Dispatches an action to enable / disable E2EE.
46
         everyoneSupportE2EE
46
         everyoneSupportE2EE
47
     };
47
     };
48
 }
48
 }
49
+
50
+/**
51
+ * Dispatches an action to set E2EE maxMode.
52
+ *
53
+ * @param {string} maxMode - The new value.
54
+ * @returns {Object}
55
+ */
56
+export function setE2EEMaxMode(maxMode: string) {
57
+    return {
58
+        type: SET_MAX_MODE,
59
+        maxMode
60
+    };
61
+}

+ 41
- 13
react/features/e2ee/components/E2EESection.js Vedi File

8
 import { Switch } from '../../base/react';
8
 import { Switch } from '../../base/react';
9
 import { connect } from '../../base/redux';
9
 import { connect } from '../../base/redux';
10
 import { toggleE2EE } from '../actions';
10
 import { toggleE2EE } from '../actions';
11
+import { MAX_MODE } from '../constants';
11
 import { doesEveryoneSupportE2EE } from '../functions';
12
 import { doesEveryoneSupportE2EE } from '../functions';
12
 
13
 
13
 type Props = {
14
 type Props = {
14
 
15
 
16
+    /**
17
+     * The resource for the description, computed based on the maxMode and whether the switch is toggled or not.
18
+     */
19
+    _descriptionResource: string,
20
+
15
     /**
21
     /**
16
      * Custom e2ee labels.
22
      * Custom e2ee labels.
17
      */
23
      */
18
     _e2eeLabels: Object,
24
     _e2eeLabels: Object,
19
 
25
 
20
     /**
26
     /**
21
-     * Whether E2EE is currently enabled or not.
27
+     * Whether the switch is currently enabled or not.
22
      */
28
      */
23
     _enabled: boolean,
29
     _enabled: boolean,
24
 
30
 
27
      */
33
      */
28
     _everyoneSupportE2EE: boolean,
34
     _everyoneSupportE2EE: boolean,
29
 
35
 
36
+    /**
37
+     * Whether E2EE is currently enabled or not.
38
+     */
39
+    _toggled: boolean,
40
+
30
     /**
41
     /**
31
      * The redux {@code dispatch} function.
42
      * The redux {@code dispatch} function.
32
      */
43
      */
43
     /**
54
     /**
44
      * True if the switch is toggled on.
55
      * True if the switch is toggled on.
45
      */
56
      */
46
-    enabled: boolean
57
+    toggled: boolean
47
 };
58
 };
48
 
59
 
49
 /**
60
 /**
59
      * @inheritdoc
70
      * @inheritdoc
60
      */
71
      */
61
     static getDerivedStateFromProps(props: Props, state: Object) {
72
     static getDerivedStateFromProps(props: Props, state: Object) {
62
-        if (props._enabled !== state.enabled) {
73
+        if (props._toggled !== state.toggled) {
63
 
74
 
64
             return {
75
             return {
65
-                enabled: props._enabled
76
+                toggled: props._toggled
66
             };
77
             };
67
         }
78
         }
68
 
79
 
78
         super(props);
89
         super(props);
79
 
90
 
80
         this.state = {
91
         this.state = {
81
-            enabled: false
92
+            toggled: false
82
         };
93
         };
83
 
94
 
84
         // Bind event handlers so they are only bound once for every instance.
95
         // Bind event handlers so they are only bound once for every instance.
92
      * @returns {ReactElement}
103
      * @returns {ReactElement}
93
      */
104
      */
94
     render() {
105
     render() {
95
-        const { _e2eeLabels, _everyoneSupportE2EE, t } = this.props;
96
-        const { enabled } = this.state;
97
-        const description = _e2eeLabels?.description || t('dialog.e2eeDescription');
106
+        const { _descriptionResource, _enabled, _e2eeLabels, _everyoneSupportE2EE, t } = this.props;
107
+        const { toggled } = this.state;
108
+        const description = _e2eeLabels?.description || t(_descriptionResource);
98
         const label = _e2eeLabels?.label || t('dialog.e2eeLabel');
109
         const label = _e2eeLabels?.label || t('dialog.e2eeLabel');
99
         const warning = _e2eeLabels?.warning || t('dialog.e2eeWarning');
110
         const warning = _e2eeLabels?.warning || t('dialog.e2eeWarning');
100
 
111
 
113
                         { label }
124
                         { label }
114
                     </label>
125
                     </label>
115
                     <Switch
126
                     <Switch
127
+                        disabled = { !_enabled }
116
                         id = 'e2ee-section-switch'
128
                         id = 'e2ee-section-switch'
117
                         onValueChange = { this._onToggle }
129
                         onValueChange = { this._onToggle }
118
-                        value = { enabled } />
130
+                        value = { toggled } />
119
                 </div>
131
                 </div>
120
             </div>
132
             </div>
121
         );
133
         );
130
      * @returns {void}
142
      * @returns {void}
131
      */
143
      */
132
     _onToggle() {
144
     _onToggle() {
133
-        const newValue = !this.state.enabled;
145
+        const newValue = !this.state.toggled;
134
 
146
 
135
         this.setState({
147
         this.setState({
136
-            enabled: newValue
148
+            toggled: newValue
137
         });
149
         });
138
 
150
 
139
         sendAnalytics(createE2EEEvent(`enabled.${String(newValue)}`));
151
         sendAnalytics(createE2EEEvent(`enabled.${String(newValue)}`));
149
  * @returns {Props}
161
  * @returns {Props}
150
  */
162
  */
151
 function mapStateToProps(state) {
163
 function mapStateToProps(state) {
152
-    const { enabled } = state['features/e2ee'];
164
+    const { enabled: e2eeEnabled, maxMode } = state['features/e2ee'];
153
     const { e2eeLabels } = state['features/base/config'];
165
     const { e2eeLabels } = state['features/base/config'];
154
 
166
 
167
+    let descriptionResource = '';
168
+
169
+    if (e2eeLabels) {
170
+        // When e2eeLabels are present, the descriptionResouse is ignored.
171
+        descriptionResource = undefined;
172
+    } else if (maxMode === MAX_MODE.THRESHOLD_EXCEEDED) {
173
+        descriptionResource = 'dialog.e2eeDisabledDueToMaxModeDescription';
174
+    } else if (maxMode === MAX_MODE.ENABLED) {
175
+        descriptionResource = e2eeEnabled
176
+            ? 'dialog.e2eeWillDisableDueToMaxModeDescription' : 'dialog.e2eeDisabledDueToMaxModeDescription';
177
+    } else {
178
+        descriptionResource = 'dialog.e2eeDescription';
179
+    }
180
+
155
     return {
181
     return {
182
+        _descriptionResource: descriptionResource,
156
         _e2eeLabels: e2eeLabels,
183
         _e2eeLabels: e2eeLabels,
157
-        _enabled: enabled,
184
+        _enabled: maxMode === MAX_MODE.DISABLED || e2eeEnabled,
185
+        _toggled: e2eeEnabled,
158
         _everyoneSupportE2EE: doesEveryoneSupportE2EE(state)
186
         _everyoneSupportE2EE: doesEveryoneSupportE2EE(state)
159
     };
187
     };
160
 }
188
 }

+ 40
- 0
react/features/e2ee/constants.js Vedi File

13
  * @type {string}
13
  * @type {string}
14
  */
14
  */
15
 export const E2EE_ON_SOUND_ID = 'E2EE_ON_SOUND';
15
 export const E2EE_ON_SOUND_ID = 'E2EE_ON_SOUND';
16
+
17
+/**
18
+ * The number of participants after which e2ee maxMode is set to MAX_MODE.ENABLED.
19
+ *
20
+ * @type {integer}
21
+ */
22
+export const MAX_MODE_LIMIT = 20;
23
+
24
+/**
25
+ * If the number of participants is greater then MAX_MODE_LIMIT + MAX_MODE_THRESHOLD
26
+ * e2ee maxMode is set to MAX_MODE.THRESHOLD_EXCEEDED.
27
+ *
28
+ * @type {integer}
29
+ */
30
+export const MAX_MODE_THRESHOLD = 5;
31
+
32
+export const MAX_MODE = {
33
+    /**
34
+     * Mode for which the e2ee can be enabled or disabled.
35
+     * If e2ee is enabled, e2ee section is enabled with a warning text.
36
+     * If e2ee is disabled, e2ee section is disabled with a warning text.
37
+     *
38
+     * @type {string}
39
+     */
40
+    ENABLED: 'max-mode-enabled',
41
+
42
+    /**
43
+     * Mode for which the e2ee and the e2ee section are automatically disabled.
44
+     *
45
+     * @type {string}
46
+     */
47
+    THRESHOLD_EXCEEDED: 'max-mode-threshold-exceeded',
48
+
49
+    /**
50
+     * The default e2ee maxMode, e2ee can be enabled/disabled, e2ee section is enabled.
51
+     *
52
+     * @type {string}
53
+     */
54
+    DISABLED: 'max-mode-disabled'
55
+};

+ 28
- 0
react/features/e2ee/functions.js Vedi File

2
 import { getParticipantCount } from '../base/participants/functions';
2
 import { getParticipantCount } from '../base/participants/functions';
3
 import { toState } from '../base/redux';
3
 import { toState } from '../base/redux';
4
 
4
 
5
+import { MAX_MODE_LIMIT, MAX_MODE_THRESHOLD } from './constants';
6
+
5
 /**
7
 /**
6
  * Gets the value of a specific React {@code Component} prop of the currently
8
  * Gets the value of a specific React {@code Component} prop of the currently
7
  * mounted {@link App}.
9
  * mounted {@link App}.
27
 
29
 
28
     return everyoneSupportE2EE;
30
     return everyoneSupportE2EE;
29
 }
31
 }
32
+
33
+/**
34
+ * Returns true is the number of participants is larger than {@code MAX_MODE_LIMIT}.
35
+ *
36
+ * @param {Function|Object} stateful - The redux store or {@code getState}
37
+ * function.
38
+ * @returns {boolean}.
39
+ */
40
+export function isMaxModeReached(stateful) {
41
+    const participantCount = getParticipantCount(toState(stateful));
42
+
43
+    return participantCount >= MAX_MODE_LIMIT;
44
+}
45
+
46
+/**
47
+ * Returns true is the number of participants is larger than {@code MAX_MODE_LIMIT + MAX_MODE_THREHOLD}.
48
+ *
49
+ * @param {Function|Object} stateful - The redux store or {@code getState}
50
+ * function.
51
+ * @returns {boolean}.
52
+ */
53
+export function isMaxModeThresholdReached(stateful) {
54
+    const participantCount = getParticipantCount(toState(stateful));
55
+
56
+    return participantCount >= MAX_MODE_LIMIT + MAX_MODE_THRESHOLD;
57
+}

+ 35
- 4
react/features/e2ee/middleware.js Vedi File

3
 import { batch } from 'react-redux';
3
 import { batch } from 'react-redux';
4
 
4
 
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
5
 import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
6
-import { getCurrentConference } from '../base/conference';
6
+import { CONFERENCE_JOINED, getCurrentConference } from '../base/conference';
7
 import {
7
 import {
8
     getLocalParticipant,
8
     getLocalParticipant,
9
     getParticipantById,
9
     getParticipantById,
18
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
18
 import { playSound, registerSound, unregisterSound } from '../base/sounds';
19
 
19
 
20
 import { TOGGLE_E2EE } from './actionTypes';
20
 import { TOGGLE_E2EE } from './actionTypes';
21
-import { setEveryoneEnabledE2EE, setEveryoneSupportE2EE, toggleE2EE } from './actions';
22
-import { E2EE_OFF_SOUND_ID, E2EE_ON_SOUND_ID } from './constants';
21
+import { setE2EEMaxMode, setEveryoneEnabledE2EE, setEveryoneSupportE2EE, toggleE2EE } from './actions';
22
+import { E2EE_OFF_SOUND_ID, E2EE_ON_SOUND_ID, MAX_MODE } from './constants';
23
+import { isMaxModeReached, isMaxModeThresholdReached } from './functions';
23
 import logger from './logger';
24
 import logger from './logger';
24
 import { E2EE_OFF_SOUND_FILE, E2EE_ON_SOUND_FILE } from './sounds';
25
 import { E2EE_OFF_SOUND_FILE, E2EE_ON_SOUND_FILE } from './sounds';
25
 
26
 
46
         dispatch(unregisterSound(E2EE_ON_SOUND_ID));
47
         dispatch(unregisterSound(E2EE_ON_SOUND_ID));
47
         break;
48
         break;
48
 
49
 
50
+    case CONFERENCE_JOINED:
51
+        _updateMaxMode(dispatch, getState);
52
+
53
+        break;
54
+
49
     case PARTICIPANT_UPDATED: {
55
     case PARTICIPANT_UPDATED: {
50
         const { id, e2eeEnabled, e2eeSupported } = action.participant;
56
         const { id, e2eeEnabled, e2eeSupported } = action.participant;
51
         const oldParticipant = getParticipantById(getState(), id);
57
         const oldParticipant = getParticipantById(getState(), id);
88
         const result = next(action);
94
         const result = next(action);
89
         const { e2eeEnabled, e2eeSupported, local } = action.participant;
95
         const { e2eeEnabled, e2eeSupported, local } = action.participant;
90
         const { everyoneEnabledE2EE } = getState()['features/e2ee'];
96
         const { everyoneEnabledE2EE } = getState()['features/e2ee'];
91
-        const participantCount = getParticipantCount(getState());
97
+        const participantCount = getParticipantCount(getState);
92
 
98
 
93
         // the initial values
99
         // the initial values
94
         if (participantCount === 1) {
100
         if (participantCount === 1) {
116
             dispatch(setEveryoneSupportE2EE(false));
122
             dispatch(setEveryoneSupportE2EE(false));
117
         }
123
         }
118
 
124
 
125
+        _updateMaxMode(dispatch, getState);
126
+
119
         return result;
127
         return result;
120
     }
128
     }
121
 
129
 
165
             });
173
             });
166
         }
174
         }
167
 
175
 
176
+        _updateMaxMode(dispatch, getState);
177
+
168
         return result;
178
         return result;
169
     }
179
     }
170
 
180
 
207
             dispatch(toggleE2EE(false));
217
             dispatch(toggleE2EE(false));
208
         }
218
         }
209
     });
219
     });
220
+
221
+/**
222
+ * Sets the maxMode based on the number of participants in the conference.
223
+ *
224
+ * @param { Dispatch<any>} dispatch - The redux dispatch function.
225
+ * @param {Function|Object} getState - The {@code getState} function.
226
+ * @private
227
+ * @returns {void}
228
+ */
229
+function _updateMaxMode(dispatch, getState) {
230
+    const state = getState();
231
+
232
+    if (isMaxModeThresholdReached(state)) {
233
+        dispatch(setE2EEMaxMode(MAX_MODE.THRESHOLD_EXCEEDED));
234
+        dispatch(toggleE2EE(false));
235
+    } else if (isMaxModeReached(state)) {
236
+        dispatch(setE2EEMaxMode(MAX_MODE.ENABLED));
237
+    } else {
238
+        dispatch(setE2EEMaxMode(MAX_MODE.DISABLED));
239
+    }
240
+}

+ 11
- 1
react/features/e2ee/reducer.js Vedi File

5
 import {
5
 import {
6
     SET_EVERYONE_ENABLED_E2EE,
6
     SET_EVERYONE_ENABLED_E2EE,
7
     SET_EVERYONE_SUPPORT_E2EE,
7
     SET_EVERYONE_SUPPORT_E2EE,
8
+    SET_MAX_MODE,
8
     TOGGLE_E2EE
9
     TOGGLE_E2EE
9
 } from './actionTypes';
10
 } from './actionTypes';
11
+import { MAX_MODE } from './constants';
10
 
12
 
11
 const DEFAULT_STATE = {
13
 const DEFAULT_STATE = {
12
-    enabled: false
14
+    enabled: false,
15
+    maxMode: MAX_MODE.DISABLED
13
 };
16
 };
14
 
17
 
15
 /**
18
 /**
33
             everyoneSupportE2EE: action.everyoneSupportE2EE
36
             everyoneSupportE2EE: action.everyoneSupportE2EE
34
         };
37
         };
35
 
38
 
39
+    case SET_MAX_MODE: {
40
+        return {
41
+            ...state,
42
+            maxMode: action.maxMode
43
+        };
44
+    }
45
+
36
     default:
46
     default:
37
         return state;
47
         return state;
38
     }
48
     }

Loading…
Annulla
Salva