Skip to content

Commit

Permalink
frontend: Added redirect url feature in standalone mode
Browse files Browse the repository at this point in the history
  • Loading branch information
CSantosM committed Feb 14, 2025
1 parent 410c222 commit 8604704
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 33 deletions.
37 changes: 31 additions & 6 deletions frontend/e2e/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ describe('Testing Standalone Mode', () => {
await utils.removeIframe();
});

it('should redirect to "unauthorized" if external URL and token provided without embedded path', async () => {
const redirectUrl = 'https://openvidu.io';
const token = await utils.getJWTToken();
await utils.buildIframeAndSwitch(`${url}/?token=${token}&redirectUrl=${redirectUrl}`);

await utils.waitForElement('#unauthorized-content');

await utils.waitForElement('#error-reason');

await utils.removeIframe();
});

it('should redirect to home page if no token and room name are provided', async () => {
await browser.get(url);
expect(await browser.getCurrentUrl()).to.include('home');
Expand All @@ -181,21 +193,34 @@ describe('Testing Standalone Mode', () => {
expect(await browser.getCurrentUrl()).to.include('home');
});

it('should NOT redirect to a redirect URL if provided in standalone mode', async () => {
await browser.get(`${url}/room123?redirectUrl=https://openvidu.io`);

it('should redirect to an external URL without token provided', async () => {
const redirectUrl = 'https://openvidu.io';
await browser.get(`${url}/Room123?redirectUrl=${redirectUrl}`);
await utils.checkPrejoinIsPresent();

await utils.joinRoom();
await utils.checkLayoutIsPresent();
await utils.checkToolbarIsPresent();

await utils.leaveRoom();

const currentUrl = await browser.getCurrentUrl();
expect(currentUrl).to.include(redirectUrl);
});

it('should redirect to an external URL with token provided', async () => {
const redirectUrl = 'https://openvidu.io';
const token = await utils.getJWTToken();
await browser.get(`${url}/?token=${token}&redirectUrl=${redirectUrl}`);

await utils.checkLayoutIsPresent();
await utils.checkToolbarIsPresent();

await utils.leaveRoom();

const redirectUrl = await browser.getCurrentUrl();
expect(redirectUrl).to.include(url);
const currentUrl = await browser.getCurrentUrl();
expect(currentUrl).to.include(redirectUrl);
});

});

describe('Testing Console Routes', () => {
Expand Down
6 changes: 5 additions & 1 deletion frontend/e2e/utils.po.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ export class OpenViduCallPO {
await this.browser.executeScript(`document.getElementById('test-iframe')?.remove();`);
}

async getJWTToken(roomName = 'TestRoom', participantName = 'TestParticipant'): Promise<string> {
async getJWTToken(roomName?: string, participantName?: string): Promise<string> {
if(!roomName) roomName = 'TestRoom-'+ Math.random().toString(36).substring(7);

if(!participantName) participantName = 'ParticipantName-' + Math.random().toString(36).substring(7);

const token = await fetch('http://localhost:6080/v1/embedded/api/token', {
method: 'POST',
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { inject } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot } from '@angular/router';
import { ContextService } from '../services';

/**
* Guard that checks for a 'redirectUrl' query parameter in the route.
* If the 'redirectUrl' parameter is valid, it sets the redirect URL in the context service.
*/
export const redirectUrlGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const contextService = inject(ContextService);
const redirectUrlParameter = route.queryParams['redirectUrl'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
[toolbarBackgroundEffectsButton]="featureFlags.showBackgrounds"
[toolbarActivitiesPanelButton]="featureFlags.showActivityPanel"
(onTokenRequested)="onTokenRequested($event)"
(onParticipantLeft)="onParticipantLeft()"
(onParticipantLeft)="onParticipantLeft($event)"
(onRecordingStartRequested)="onRecordingStartRequested($event)"
(onRecordingStopRequested)="onRecordingStopRequested($event)"
(onRecordingDeleteRequested)="onRecordingDeleteRequested($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
RecordingStartRequestedEvent,
RecordingStopRequestedEvent,
OpenViduComponentsModule,
ApiDirectiveModule
ApiDirectiveModule,
ParticipantLeftEvent
} from 'openvidu-components-angular';

import {
Expand Down Expand Up @@ -92,30 +93,12 @@ export class VideoRoomComponent implements OnInit {
this.cdr.detectChanges();
}

onParticipantLeft() {
onParticipantLeft(event: ParticipantLeftEvent) {
console.warn('Participant left the room. Redirecting to:');
const redirectURL = this.contextService.getRedirectURL() || '/';
const isExternalURL = /^https?:\/\//.test(redirectURL);

if (this.contextService.isEmbeddedMode()) {
const redirectURL = this.contextService.getRedirectURL();
if (redirectURL) {
// Check if the redirect URL is an external URL
const isExternalURL = /^https?:\/\//.test(redirectURL);

if (isExternalURL) {
console.log('Redirecting to external URL:', redirectURL);
window.location.href = redirectURL;
} else {
console.log('Participant left the room. Redirecting to internal route:', redirectURL);
this.router.navigate([redirectURL], { replaceUrl: true });
}
} else {
console.warn('Participant left the room. Redirecting to:', `/`);
this.router.navigate([`/`]);
}
return;
}

this.router.navigate([`/`]);
this.redirectTo(redirectURL, isExternalURL);
}

async onRecordingStartRequested(event: RecordingStartRequestedEvent) {
Expand Down Expand Up @@ -207,4 +190,15 @@ export class VideoRoomComponent implements OnInit {

this.featureFlags.showPrejoin = false;
}

private redirectTo(url: string, isExternal: boolean) {
if (isExternal) {
console.log('Redirecting to external URL:', url);
window.location.href = url;
} else {
console.log('Redirecting to internal route:', url);
this.router.navigate([url], { replaceUrl: true });
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const baseRoutes: Routes = [
},
{ path: 'embedded/unauthorized', component: UnauthorizedComponent },

{ path: '', component: VideoRoomComponent, canActivate: [standaloneModeGuard, ensureValidTokenOrRoomNameGuard] },
{ path: '', component: VideoRoomComponent, canActivate: [standaloneModeGuard, ensureValidTokenOrRoomNameGuard, redirectUrlGuard] },
{ path: 'login', component: ConsoleLoginComponent },
{
path: 'console',
Expand All @@ -44,7 +44,7 @@ export const baseRoutes: Routes = [
{
path: ':roomName',
component: VideoRoomComponent,
canActivate: [standaloneModeGuard, ensureValidTokenOrRoomNameGuard]
canActivate: [standaloneModeGuard, ensureValidTokenOrRoomNameGuard, redirectUrlGuard]
},

// Redirect all other routes to home
Expand Down

0 comments on commit 8604704

Please sign in to comment.