Compare commits

..

2 Commits

Author SHA1 Message Date
damencho
8cf76b20c7 debug 2025-03-05 07:40:32 -06:00
damencho
44c1633952 feat(tests): Fixes the checks when to use token.
We have few options:
- iframeAPI tests generating tokens via jwtPrivateKeyPath
- tests that just use provided JWT_ACCESS_TOKEN for the first participant to avoid deployments where initial authentication is required
- tests that does not use iframeAPI, but want to use the jwtPrivateKeyPath for a meeting (invite test as JWT_ACCESS_TOKEN does not satisfy some services)
2025-03-04 19:08:04 -06:00
28 changed files with 48 additions and 125 deletions

View File

@@ -82,8 +82,7 @@ public class BroadcastAction {
SHOW_NOTIFICATION("org.jitsi.meet.SHOW_NOTIFICATION"),
HIDE_NOTIFICATION("org.jitsi.meet.HIDE_NOTIFICATION"),
START_RECORDING("org.jitsi.meet.START_RECORDING"),
STOP_RECORDING("org.jitsi.meet.STOP_RECORDING"),
OVERWRITE_CONFIG("org.jitsi.meet.OVERWRITE_CONFIG");
STOP_RECORDING("org.jitsi.meet.STOP_RECORDING");
private final String action;

View File

@@ -139,11 +139,4 @@ public class BroadcastIntentHelper {
return intent;
}
public static Intent buildOverwriteConfigIntent(String config) {
Intent intent = new Intent(BroadcastAction.Type.OVERWRITE_CONFIG.getAction());
intent.putExtra("config", config);
return intent;
}
}

View File

@@ -101,7 +101,6 @@ class ExternalAPIModule extends ReactContextBaseJavaModule {
constants.put("HIDE_NOTIFICATION", BroadcastAction.Type.HIDE_NOTIFICATION.getAction());
constants.put("START_RECORDING", BroadcastAction.Type.START_RECORDING.getAction());
constants.put("STOP_RECORDING", BroadcastAction.Type.STOP_RECORDING.getAction());
constants.put("OVERWRITE_CONFIG", BroadcastAction.Type.OVERWRITE_CONFIG.getAction());
return constants;
}

View File

@@ -2278,10 +2278,8 @@ export default {
* @param {boolean} [requestFeedback=false] if user feedback should be
* @param {string} [hangupReason] the reason for leaving the meeting
* requested
* @param {boolean} [notifyOnConferenceTermination] whether to notify
* the user on conference termination
*/
hangup(requestFeedback = false, hangupReason, notifyOnConferenceTermination) {
hangup(requestFeedback = false, hangupReason) {
APP.store.dispatch(disableReceiver());
this._stopProxyConnection();
@@ -2300,7 +2298,7 @@ export default {
if (requestFeedback) {
const feedbackDialogClosed = (feedbackResult = {}) => {
if (!feedbackResult.wasDialogShown && hangupReason && notifyOnConferenceTermination) {
if (!feedbackResult.wasDialogShown && hangupReason) {
return APP.store.dispatch(
openLeaveReasonDialog(hangupReason)).then(() => feedbackResult);
}

View File

@@ -755,9 +755,6 @@ var config = {
// and microsoftApiApplicationClientID
// enableCalendarIntegration: false,
// Whether to notify when the conference is terminated because it was destroyed.
// notifyOnConferenceDestruction: true,
// The client id for the google APIs used for the calendar integration, youtube livestreaming, etc.
// googleApiApplicationClientID: '<client_id>',

View File

@@ -111,7 +111,7 @@ form {
height: $watermarkHeight;
background-size: contain;
background-repeat: no-repeat;
z-index: $watermarkZ;
z-index: $zindex2;
}
.leftwatermark {
@@ -142,7 +142,7 @@ form {
font-size: 11pt;
color: rgba(255,255,255,.50);
text-decoration: none;
z-index: $watermarkZ;
z-index: 100;
}
/**

View File

@@ -174,12 +174,4 @@
}
}
}
@media (max-width: 1024px) { /* Targets iPads and smaller devices */
.item {
.delete-meeting {
display: block !important;
}
}
}
}

View File

@@ -38,8 +38,6 @@ $zindex1: 1;
$zindex2: 2;
$zindex3: 3;
$toolbarZ: 250;
$watermarkZ: 253;
// Place filmstrip videos over toolbar in order
// to make connection info visible.
$filmstripVideosZ: $toolbarZ + 1;

View File

@@ -35,6 +35,5 @@ static NSString * const sendEventNotificationName = @"org.jitsi.meet.SendEvent";
- (void)hideNotification:(NSString*)uid;
- (void)startRecording:(NSString*)mode :(NSString*)dropboxToken :(BOOL)shouldShare :(NSString*)rtmpStreamKey :(NSString*)rtmpBroadcastID :(NSString*)youtubeStreamKey :(NSString*)youtubeBroadcastID :(NSDictionary*)extraMetadata :(BOOL)transcription;
- (void)stopRecording:(NSString*)mode :(BOOL)transcription;
- (void)overwriteConfig:(NSDictionary*)config;
@end

View File

@@ -32,7 +32,7 @@ static NSString * const showNotificationAction = @"org.jitsi.meet.SHOW_NOTIFICAT
static NSString * const hideNotificationAction = @"org.jitsi.meet.HIDE_NOTIFICATION";
static NSString * const startRecordingAction = @"org.jitsi.meet.START_RECORDING";
static NSString * const stopRecordingAction = @"org.jitsi.meet.STOP_RECORDING";
static NSString * const overwriteConfigAction = @"org.jitsi.meet.OVERWRITE_CONFIG";
@implementation ExternalAPI
static NSMapTable<NSString*, void (^)(NSArray* participantsInfo)> *participantInfoCompletionHandlers;
@@ -60,8 +60,7 @@ RCT_EXPORT_MODULE();
@"SHOW_NOTIFICATION": showNotificationAction,
@"HIDE_NOTIFICATION": hideNotificationAction,
@"START_RECORDING": startRecordingAction,
@"STOP_RECORDING": stopRecordingAction,
@"OVERWRITE_CONFIG": overwriteConfigAction
@"STOP_RECORDING": stopRecordingAction
};
};
@@ -91,8 +90,7 @@ RCT_EXPORT_MODULE();
showNotificationAction,
hideNotificationAction,
startRecordingAction,
stopRecordingAction,
overwriteConfigAction
stopRecordingAction
];
}
@@ -236,8 +234,4 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:stopRecordingAction body:data];
}
- (void)overwriteConfig:(NSDictionary*)config {
[self sendEventWithName:overwriteConfigAction body:config];
}
@end

View File

@@ -56,5 +56,5 @@ typedef NS_ENUM(NSInteger, RecordingMode) {
- (void)hideNotification:(NSString * _Nullable)uid;
- (void)startRecording:(RecordingMode)mode :(NSString * _Nullable)dropboxToken :(BOOL)shouldShare :(NSString * _Nullable)rtmpStreamKey :(NSString * _Nullable)rtmpBroadcastID :(NSString * _Nullable)youtubeStreamKey :(NSString * _Nullable)youtubeBroadcastID :(NSString * _Nullable)extraMetadata :(BOOL)transcription;
- (void)stopRecording:(RecordingMode)mode :(BOOL)transcription;
- (void)overwriteConfig:(NSDictionary * _Nonnull)config;
@end

View File

@@ -168,11 +168,6 @@ static NSString *recordingModeToString(RecordingMode mode);
[externalAPI stopRecording:recordingModeToString(mode) :transcription];
}
- (void)overwriteConfig:(NSDictionary *)config {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI overwriteConfig:config];
}
#pragma mark Private methods
- (void)registerObservers {

View File

@@ -4,7 +4,7 @@ import { JitsiConferenceErrors } from '../lib-jitsi-meet';
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
import { CONFERENCE_FAILED } from './actionTypes';
import { conferenceLeft } from './actions.native';
import { conferenceLeft } from './actions';
import { TRIGGER_READY_TO_CLOSE_REASONS } from './constants';
import './middleware.any';
@@ -15,20 +15,10 @@ MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CONFERENCE_FAILED: {
const { getState } = store;
const state = getState();
const { notifyOnConferenceDestruction = true } = state['features/base/config'];
if (error?.name !== JitsiConferenceErrors.CONFERENCE_DESTROYED) {
break;
}
if (!notifyOnConferenceDestruction) {
dispatch(conferenceLeft(action.conference));
dispatch(appNavigate(undefined));
break;
}
const [ reason ] = error.params;
const reasonKey = Object.keys(TRIGGER_READY_TO_CLOSE_REASONS)[

View File

@@ -122,14 +122,12 @@ MiddlewareRegistry.register(store => next => action => {
}
if (errorName === JitsiConferenceErrors.CONFERENCE_DESTROYED) {
const state = getState();
const { notifyOnConferenceDestruction = true } = state['features/base/config'];
const [ reason ] = action.error.params;
const titlekey = Object.keys(TRIGGER_READY_TO_CLOSE_REASONS)[
Object.values(TRIGGER_READY_TO_CLOSE_REASONS).indexOf(reason)
];
dispatch(hangup(true, i18next.t(titlekey) || reason, notifyOnConferenceDestruction));
dispatch(hangup(true, i18next.t(titlekey) || reason));
}
releaseScreenLock();

View File

@@ -486,7 +486,6 @@ export interface IConfig {
short?: number;
};
notifications?: Array<string>;
notifyOnConferenceDestruction?: boolean;
openSharedDocumentOnJoin?: boolean;
opusMaxAverageBitrate?: number;
p2p?: {

View File

@@ -182,7 +182,6 @@ export default [
'mouseMoveCallbackInterval',
'notifications',
'notificationTimeouts',
'notifyOnConferenceDestruction',
'openSharedDocumentOnJoin',
'opusMaxAverageBitrate',
'p2p.backToP2PDelay',

View File

@@ -62,11 +62,9 @@ export function connect(id?: string, password?: string) {
* @param {boolean} [requestFeedback] - Whether to attempt showing a
* request for call feedback.
* @param {string} [feedbackTitle] - The feedback title.
* @param {boolean} [notifyOnConferenceTermination] - Whether to notify
* the user on conference termination.
* @returns {Function}
*/
export function hangup(requestFeedback = false, feedbackTitle?: string, notifyOnConferenceTermination?: boolean) {
export function hangup(requestFeedback = false, feedbackTitle?: string) {
// XXX For web based version we use conference hanging up logic from the old app.
return async (dispatch: IStore['dispatch']) => {
if (LocalRecordingManager.isRecordingLocally()) {
@@ -82,6 +80,6 @@ export function hangup(requestFeedback = false, feedbackTitle?: string, notifyOn
});
}
return APP.conference.hangup(requestFeedback, feedbackTitle, notifyOnConferenceTermination);
return APP.conference.hangup(requestFeedback, feedbackTitle);
};
}

View File

@@ -15,11 +15,6 @@ interface IProps {
*/
gifEnabled: boolean;
/**
* Message decoration for screen reader.
*/
screenReaderHelpText?: string;
/**
* The body of the message.
*/
@@ -96,18 +91,10 @@ class Message extends Component<IProps> {
* @returns {ReactElement}
*/
render() {
const { screenReaderHelpText } = this.props;
return (
<p>
{ screenReaderHelpText && (
<span className = 'sr-only'>
{screenReaderHelpText}
</span>
) }
<>
{ this._processMessage() }
</p>
</>
);
}
}

View File

@@ -254,9 +254,7 @@ const ChatMessage = ({
function _renderTimestamp() {
return (
<div className = { cx('timestamp', classes.timestamp) }>
<p>
{getFormattedTimestamp(message)}
</p>
{getFormattedTimestamp(message)}
</div>
);
}
@@ -287,17 +285,15 @@ const ChatMessage = ({
<div
className = { classes.reactionItem }
key = { reaction }>
<p>
<span>{reaction}</span>
<span>{participants.size}</span>
</p>
<span>{reaction}</span>
<span>{participants.size}</span>
<div className = { classes.participantList }>
{Array.from(participants).map(participantId => (
<p
<div
className = { classes.participant }
key = { participantId }>
{state && getParticipantDisplayName(state, participantId)}
</p>
</div>
))}
</div>
</div>
@@ -315,12 +311,12 @@ const ChatMessage = ({
visible = { isReactionsOpen }>
<div className = { classes.reactionBox }>
{reactionsArray.slice(0, numReactionsDisplayed).map(({ reaction }, index) =>
<p key = { index }>{reaction}</p>
<span key = { index }>{reaction}</span>
)}
{reactionsArray.length > numReactionsDisplayed && (
<p className = { classes.reactionCount }>
<span className = { classes.reactionCount }>
+{totalReactions - numReactionsDisplayed}
</p>
</span>
)}
</div>
</Popover>
@@ -356,13 +352,14 @@ const ChatMessage = ({
<div className = { cx('messagecontent', classes.messageContent) }>
{showDisplayName && _renderDisplayName()}
<div className = { cx('usermessage', classes.userMessage) }>
<Message
screenReaderHelpText = { message.displayName === message.recipient
? t<string>('chat.messageAccessibleTitleMe')
: t<string>('chat.messageAccessibleTitle', {
<span className = 'sr-only'>
{message.displayName === message.recipient
? t('chat.messageAccessibleTitleMe')
: t('chat.messageAccessibleTitle', {
user: message.displayName
}) }
text = { getMessageText(message) } />
})}
</span>
<Message text = { getMessageText(message) } />
{(message.privateMessage || (message.lobbyChat && !knocking))
&& _renderPrivateNotice()}
<div className = { classes.chatMessageFooter }>

View File

@@ -1,6 +1,6 @@
import { appNavigate } from '../app/actions.native';
import { KICKED_OUT } from '../base/conference/actionTypes';
import { conferenceLeft } from '../base/conference/actions.native';
import { conferenceLeft } from '../base/conference/actions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { notifyKickedOut } from './actions.native';

View File

@@ -35,8 +35,7 @@ MiddlewareRegistry.register(store => next => action => {
dispatch(hangup(true,
participantDisplayName ? i18next.t('dialog.kickTitle', { participantDisplayName })
: i18next.t('dialog.kickSystemTitle'),
true));
: i18next.t('dialog.kickSystemTitle')));
return result;
}

View File

@@ -26,8 +26,6 @@ import {
isRoomValid
} from '../../base/conference/functions';
import { IJitsiConference } from '../../base/conference/reducer';
import { overwriteConfig } from '../../base/config/actions';
import { getWhitelistedJSON } from '../../base/config/functions.native';
import { CONNECTION_DISCONNECTED } from '../../base/connection/actionTypes';
import {
JITSI_CONNECTION_CONFERENCE_KEY,
@@ -577,14 +575,6 @@ function _registerForNativeEvents(store: IStore) {
conference.stopRecording(activeSession.id);
});
eventEmitter.addListener(ExternalAPI.OVERWRITE_CONFIG, ({ config }: any) => {
const whitelistedConfig = getWhitelistedJSON('config', config);
logger.info(`Overwriting config with: ${JSON.stringify(whitelistedConfig)}`);
dispatch(overwriteConfig(config));
});
}
/**
@@ -609,7 +599,6 @@ function _unregisterForNativeEvents() {
eventEmitter.removeAllListeners(ExternalAPI.HIDE_NOTIFICATION);
eventEmitter.removeAllListeners(ExternalAPI.START_RECORDING);
eventEmitter.removeAllListeners(ExternalAPI.STOP_RECORDING);
eventEmitter.removeAllListeners(ExternalAPI.OVERWRITE_CONFIG);
}
/**

View File

@@ -15,8 +15,6 @@ export default function RecordingConsentDialog() {
const consent = useCallback(() => {
dispatch(setAudioUnmutePermissions(false, true));
dispatch(setVideoUnmutePermissions(false, true));
return true;
}, []);
return (

View File

@@ -453,10 +453,10 @@ export function shouldRequireRecordingConsent(recorderSession: any, state: IRedu
return false;
}
if (!recorderSession.getInitiator()
|| recorderSession.getStatus() === JitsiRecordingConstants.status.OFF) {
if (!recorderSession._initiator
|| recorderSession._statusFromJicofo === JitsiRecordingConstants.status.OFF) {
return false;
}
return recorderSession.getInitiator() !== getLocalParticipant(state)?.id;
return recorderSession._initiator !== getLocalParticipant(state)?.id;
}

View File

@@ -234,7 +234,7 @@ export class Participant {
let urlToLoad = url.startsWith('/') ? url.substring(1) : url;
if (options.preferGenerateToken && !ctx.iframeAPI && ctx.isJaasAvailable() && process.env.IFRAME_TENANT) {
if (options.forceGenerateToken && !ctx.iframeAPI && ctx.isJaasAvailable() && process.env.IFRAME_TENANT) {
// This to enables tests like invite, which can force using the jaas auth instead of the provided token
urlToLoad = `/${process.env.IFRAME_TENANT}/${urlToLoad}`;
}
@@ -617,10 +617,16 @@ export class Participant {
// let's give it some time to leave the muc, we redirect after hangup so we should wait for the
// change of url
await this.driver.waitUntil(
async () => current !== await this.driver.getUrl(),
async () => {
const u = await this.driver.getUrl();
console.log('url:', current, u);
return current !== u;
},
{
timeout: 8000,
timeoutMsg: `${this.name} did not leave the muc in 8s`
timeout: 5000,
timeoutMsg: `${this.name} did not leave the muc in 5s`
}
);

View File

@@ -169,8 +169,7 @@ async function joinTheModeratorAsP1(ctx: IContext, options?: IJoinOptions) {
// we prioritize the access token when iframe is not used and private key is set,
// otherwise if private key is not specified we use the access token if set
if (process.env.JWT_ACCESS_TOKEN
&& ((ctx.jwtPrivateKeyPath && !ctx.iframeAPI && !options?.preferGenerateToken)
|| !ctx.jwtPrivateKeyPath)) {
&& (ctx.jwtPrivateKeyPath && !ctx.iframeAPI && !options?.forceGenerateToken)) {
token = process.env.JWT_ACCESS_TOKEN;
} else if (ctx.jwtPrivateKeyPath) {
token = getModeratorToken(p1DisplayName);

View File

@@ -38,7 +38,7 @@ export type IJoinOptions = {
* When joining the first participant and jwt singing material is available and a provided token
* is available, prefer generating a new token for the first participant.
*/
preferGenerateToken?: boolean;
forceGenerateToken?: boolean;
/**
* Whether to skip setting display name.

View File

@@ -2,7 +2,7 @@ import { ensureOneParticipant } from '../../helpers/participants';
import { isDialInEnabled } from '../helpers/DialIn';
describe('Invite', () => {
it('join participant', () => ensureOneParticipant(ctx, { preferGenerateToken: true }));
it('join participant', () => ensureOneParticipant(ctx, { forceGenerateToken: true }));
it('url displayed', async () => {
const { p1 } = ctx;