feat: Backend reports default permissions.

When any of the backend is used 'anonymous', 'jitsi-anonymous', 'internal_hashed', 'internal_plain', 'cyrus' and a participant becomes a moderator, because of external module or because set from jicofo we send to client with the self-presence about becoming moderator a default set of permissions which can be controlled via prosody config.
If using 'token' authentication the above applies only if there is a token and the token does not contain context.features.
This commit is contained in:
damencho
2025-03-26 13:18:30 -05:00
committed by Дамян Минков
parent b97798e1ca
commit 92df4bfbbb
19 changed files with 219 additions and 102 deletions

View File

@@ -1,12 +1,9 @@
import { IStore } from '../app/types';
import { getMeetingRegion, getRecordingSharingUrl } from '../base/config/functions';
import { MEET_FEATURES } from '../base/jwt/constants';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import JitsiMeetJS, { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import {
getLocalParticipant,
getParticipantDisplayName,
isLocalParticipantModerator
} from '../base/participants/functions';
import { getLocalParticipant, getParticipantDisplayName } from '../base/participants/functions';
import { BUTTON_TYPES } from '../base/ui/constants.any';
import { copyText } from '../base/util/copyText';
import { getVpaasTenant, isVpaasMeeting } from '../jaas/functions';
@@ -435,10 +432,9 @@ export function showStartRecordingNotificationWithCallback(openRecordingDialog:
customActionNameKey: [ 'notify.suggestRecordingAction' ],
customActionHandler: [ () => {
state = getState();
const isModerator = isLocalParticipantModerator(state);
const { recordingService } = state['features/base/config'];
const canBypassDialog = recordingService?.enabled
&& isJwtFeatureEnabled(state, 'recording', isModerator, false);
&& isJwtFeatureEnabled(state, MEET_FEATURES.RECORDING, false);
if (canBypassDialog) {
const options = {

View File

@@ -2,7 +2,6 @@ import { IReduxState } from '../../../app/types';
import { IconSites } from '../../../base/icons/svg';
import { MEET_FEATURES } from '../../../base/jwt/constants';
import { isJwtFeatureEnabled } from '../../../base/jwt/functions';
import { isLocalParticipantModerator } from '../../../base/participants/functions';
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions';
@@ -129,11 +128,10 @@ export function _mapStateToProps(state: IReduxState, ownProps: IProps) {
// If the containing component provides the visible prop, that is one
// above all, but if not, the button should be autonomous and decide on
// its own to be visible or not.
const isModerator = isLocalParticipantModerator(state);
const liveStreaming = getLiveStreaming(state);
visible = isLiveStreamingButtonVisible({
liveStreamingAllowed: isJwtFeatureEnabled(state, 'livestreaming', isModerator, false),
liveStreamingAllowed: isJwtFeatureEnabled(state, MEET_FEATURES.LIVESTREAMING, false),
liveStreamingEnabled: liveStreaming?.enabled,
isInBreakoutRoom: isInBreakoutRoom(state)
});

View File

@@ -6,8 +6,8 @@ import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState, IStore } from '../../../app/types';
import ColorSchemeRegistry from '../../../base/color-scheme/ColorSchemeRegistry';
import { _abstractMapStateToProps } from '../../../base/dialog/functions';
import { MEET_FEATURES } from '../../../base/jwt/constants';
import { isJwtFeatureEnabled } from '../../../base/jwt/functions';
import { isLocalParticipantModerator } from '../../../base/participants/functions';
import { authorizeDropbox, updateDropboxToken } from '../../../dropbox/actions';
import { isVpaasMeeting } from '../../../jaas/functions';
import { canAddTranscriber } from '../../../transcribing/functions';
@@ -414,14 +414,13 @@ class AbstractStartRecordingDialogContent extends Component<IProps, IState> {
export function mapStateToProps(state: IReduxState) {
const { localRecording, recordingService } = state['features/base/config'];
const _localRecordingAvailable = !localRecording?.disable && supportsLocalRecording();
const isModerator = isLocalParticipantModerator(state);
return {
..._abstractMapStateToProps(state),
isVpaas: isVpaasMeeting(state),
_canStartTranscribing: canAddTranscriber(state),
_hideStorageWarning: Boolean(recordingService?.hideStorageWarning),
_renderRecording: isJwtFeatureEnabled(state, 'recording', isModerator, false),
_renderRecording: isJwtFeatureEnabled(state, MEET_FEATURES.RECORDING, false),
_localRecordingAvailable,
_localRecordingEnabled: !localRecording?.disable,
_localRecordingSelfEnabled: !localRecording?.disableSelfRecording,

View File

@@ -2,14 +2,11 @@ import i18next from 'i18next';
import { IReduxState, IStore } from '../app/types';
import { isMobileBrowser } from '../base/environment/utils';
import { MEET_FEATURES } from '../base/jwt/constants';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { JitsiRecordingConstants, browser } from '../base/lib-jitsi-meet';
import { getSoundFileSrc } from '../base/media/functions';
import {
getLocalParticipant,
getRemoteParticipants,
isLocalParticipantModerator
} from '../base/participants/functions';
import { getLocalParticipant, getRemoteParticipants } from '../base/participants/functions';
import { registerSound, unregisterSound } from '../base/sounds/actions';
import { isInBreakoutRoom as isInBreakoutRoomF } from '../breakout-rooms/functions';
import { isEnabled as isDropboxEnabled } from '../dropbox/functions';
@@ -203,9 +200,7 @@ export function canStopRecording(state: IReduxState) {
}
if (isCloudRecordingRunning(state) || isRecorderTranscriptionsRunning(state)) {
const isModerator = isLocalParticipantModerator(state);
return isJwtFeatureEnabled(state, 'recording', isModerator, false);
return isJwtFeatureEnabled(state, MEET_FEATURES.RECORDING, false);
}
return false;
@@ -257,7 +252,6 @@ export function getRecordButtonProps(state: IReduxState) {
// If the containing component provides the visible prop, that is one
// above all, but if not, the button should be autonomus and decide on
// its own to be visible or not.
const isModerator = isLocalParticipantModerator(state);
const {
recordingService,
localRecording
@@ -269,7 +263,7 @@ export function getRecordButtonProps(state: IReduxState) {
if (localRecordingEnabled) {
visible = true;
} else if (isJwtFeatureEnabled(state, 'recording', isModerator, false)) {
} else if (isJwtFeatureEnabled(state, MEET_FEATURES.RECORDING, false)) {
visible = recordingEnabled;
}

View File

@@ -1,8 +1,8 @@
import { useSelector } from 'react-redux';
import { IReduxState } from '../app/types';
import { MEET_FEATURES } from '../base/jwt/constants';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { isLocalParticipantModerator } from '../base/participants/functions';
import { isInBreakoutRoom } from '../breakout-rooms/functions';
import { getLiveStreaming } from './components/LiveStream/functions';
@@ -45,10 +45,9 @@ export function useRecordingButton() {
*/
export function useLiveStreamingButton() {
const toolbarButtons = useSelector((state: IReduxState) => state['features/toolbox'].toolbarButtons);
const localParticipantIsModerator = useSelector(isLocalParticipantModerator);
const liveStreaming = useSelector(getLiveStreaming);
const liveStreamingAllowed = useSelector((state: IReduxState) =>
isJwtFeatureEnabled(state, 'livestreaming', localParticipantIsModerator, false));
isJwtFeatureEnabled(state, MEET_FEATURES.LIVESTREAMING, false));
const _isInBreakoutRoom = useSelector(isInBreakoutRoom);
if (toolbarButtons?.includes('recording')