frontend: include ParticipantNameForm component inside VideoRoom component and remove unused guards

This commit is contained in:
juancarmore 2025-06-06 16:49:11 +02:00
parent dbd38f3c28
commit ec37389d1c
15 changed files with 262 additions and 448 deletions

View File

@ -1,12 +1,5 @@
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivateFn,
RedirectCommand,
Router,
RouterStateSnapshot,
UrlTree
} from '@angular/router';
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { AuthMode, ParticipantRole } from '@lib/typings/ce';
import { AuthService, ContextService, HttpService, SessionStorageService } from '../services';
@ -79,12 +72,9 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
const isAuthenticated = await authService.isUserAuthenticated();
if (!isAuthenticated) {
// Redirect to the login page with query param to redirect back to the room
const loginRoute = router.createUrlTree(['login'], {
return router.createUrlTree(['login'], {
queryParams: { redirectTo: state.url }
});
return new RedirectCommand(loginRoute, {
skipLocationChange: true
});
}
}

View File

@ -2,7 +2,5 @@ export * from './application-mode.guard';
export * from './auth.guard';
export * from './extract-query-params.guard';
export * from './moderator-secret.guard';
export * from './participant-name.guard';
export * from './run-serially.guard';
export * from './validate-room-access.guard';
export * from './validate-recording-access.guard';

View File

@ -5,54 +5,6 @@ import { Router } from '@angular/router';
import { ContextService, HttpService, SessionStorageService } from '../services';
import { filter, take } from 'rxjs';
/**
* Guard that replaces the moderator secret in the URL with the publisher secret.
*
* This guard checks if the current participant is a moderator. If so, it retrieves the moderator and publisher secrets
* for the current room and updates the session storage with the moderator secret. It then replaces the secret in the URL
* with the publisher secret.
*
* @param route - The activated route snapshot.
* @param state - The router state snapshot.
* @returns A promise that resolves to `true` if the operation is successful, otherwise `false`.
*
* @throws Will log an error and return `false` if an error occurs during the process.
*/
export const replaceModeratorSecretGuard: CanActivateFn = (route, _state) => {
const httpService = inject(HttpService);
const contextService = inject(ContextService);
const router = inject(Router);
const location: Location = inject(Location);
const sessionStorageService = inject(SessionStorageService);
try {
router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
take(1)
)
.subscribe(async () => {
if (contextService.isModeratorParticipant()) {
const roomId = contextService.getRoomId();
const { moderatorSecret, publisherSecret } = await getUrlSecret(httpService, roomId);
sessionStorageService.setModeratorSecret(roomId, moderatorSecret);
// Replace secret in URL by the publisher secret
const queryParams = { ...route.queryParams, secret: publisherSecret };
const urlTree = router.createUrlTree([], { queryParams, queryParamsHandling: 'merge' });
const newUrl = router.serializeUrl(urlTree);
location.replaceState(newUrl);
}
});
return true;
} catch (error) {
console.error('error', error);
return false;
}
};
/**
* Guard that intercepts navigation to remove the 'secret' query parameter from the URL
* when a moderator participant is detected. The secret is stored in session storage

View File

@ -1,25 +0,0 @@
import { inject } from '@angular/core';
import { CanActivateFn, RedirectCommand } from '@angular/router';
import { Router } from '@angular/router';
import { ContextService } from '../services';
export const checkParticipantNameGuard: CanActivateFn = (_route, state) => {
const router = inject(Router);
const contextService = inject(ContextService);
const roomId = contextService.getRoomId();
const hasParticipantName = !!contextService.getParticipantName();
// Check if participant name exists in the service
if (!hasParticipantName) {
// Redirect to a page where the participant can input their participant name
const participantNameRoute = router.createUrlTree([`room/${roomId}/participant-name`], {
queryParams: { originUrl: state.url, t: Date.now() }
});
return new RedirectCommand(participantNameRoute, {
skipLocationChange: true
});
}
// Proceed if the name exists
return true;
};

View File

@ -1,64 +0,0 @@
import { inject } from '@angular/core';
import {
ActivatedRouteSnapshot,
Router,
RouterStateSnapshot,
CanActivateFn,
UrlTree,
RedirectCommand
} from '@angular/router';
import { ContextService, HttpService, SessionStorageService } from '../services';
/**
* Guard to validate the access to a room.
*/
export const validateRoomAccessGuard: CanActivateFn = async (
_route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const httpService = inject(HttpService);
const contextService = inject(ContextService);
const router = inject(Router);
const sessionStorageService = inject(SessionStorageService);
const roomId = contextService.getRoomId();
const participantName = contextService.getParticipantName();
const secret = contextService.getSecret();
const storageSecret = sessionStorageService.getModeratorSecret(roomId);
try {
// Generate a participant token
const response = await httpService.generateParticipantToken({
roomId,
participantName,
secret: storageSecret || secret
});
contextService.setParticipantToken(response.token);
return true;
} catch (error: any) {
console.error('Error generating participant token:', error);
switch (error.status) {
case 400:
// Invalid secret
return redirectToErrorPage(router, 'invalid-secret');
case 404:
// Room not found
return redirectToErrorPage(router, 'invalid-room');
case 409:
// Participant already exists.
// Send a timestamp to force update the query params and show the error message in participant name input form
const participantNameRoute = router.createUrlTree([`room/${roomId}/participant-name`], {
queryParams: { originUrl: state.url, accessError: 'participant-exists', t: Date.now() }
});
return new RedirectCommand(participantNameRoute, {
skipLocationChange: true
});
default:
return redirectToErrorPage(router, 'internal-error');
}
}
};
const redirectToErrorPage = (router: Router, reason: string): UrlTree => {
return router.createUrlTree(['error'], { queryParams: { reason } });
};

View File

@ -10,6 +10,5 @@ export * from './console/security-preferences/security-preferences.component';
export * from './disconnected/disconnected.component';
export * from './error/error.component';
export * from './login/login.component';
export * from './participant-name-form/participant-name-form.component';
export * from './room-recordings/room-recordings.component';
export * from './video-room/video-room.component';

View File

@ -1,24 +0,0 @@
<div class="form-container">
<mat-card class="form-card">
<h2 class="form-title">What is your name?</h2>
<form [formGroup]="participantForm" (ngSubmit)="onSubmit()">
<mat-form-field appearance="outline" class="full-width">
<mat-label>Name</mat-label>
<input id="participant-name-input" matInput placeholder="Enter your name" formControlName="name" required />
@if (name?.hasError('minlength')) {
<mat-error> The name must be at least <strong>4 characters</strong> </mat-error>
}
@if (name?.hasError('required')) {
<mat-error> The name is <strong>required</strong> </mat-error>
}
@if (name?.hasError('participantExists')) {
<mat-error> The name is already taken. <strong> Please choose another name </strong> </mat-error>
}
</mat-form-field>
<button mat-raised-button color="primary" id="participant-name-submit" class="full-width" [disabled]="participantForm.invalid">
Continue
</button>
</form>
</mat-card>
</div>

View File

@ -1,36 +0,0 @@
.form-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--ov-background-color);
}
.form-card {
width: 400px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
border-radius: var(--ov-surface-radius);
background-color: var(--ov-surface-color);
}
.form-title {
text-align: center;
margin-bottom: 20px;
color: var(--ov-text-surface-color);
}
.full-width {
width: 100%;
margin-bottom: 20px;
}
button {
height: 56px;
border-radius: var(--ov-surface-radius);
}
button:not([disabled]) {
background-color: var(--ov-accent-action-color);
color: var(--ov-text-primary-color);
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParticipantNameFormComponent } from './participant-name-form.component';
describe('ParticipantNameFormComponent', () => {
let component: ParticipantNameFormComponent;
let fixture: ComponentFixture<ParticipantNameFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ParticipantNameFormComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ParticipantNameFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,74 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { AuthService } from 'shared-meet-components';
@Component({
selector: 'ov-participant-name-form',
standalone: true,
imports: [
MatFormFieldModule,
MatInputModule,
FormsModule,
ReactiveFormsModule,
MatCardModule,
MatButtonModule
// MatIconModule
],
templateUrl: './participant-name-form.component.html',
styleUrl: './participant-name-form.component.scss'
})
export class ParticipantNameFormComponent implements OnInit {
participantForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(4)])
});
protected originUrl: string = '';
protected error = '';
constructor(
protected router: Router,
protected route: ActivatedRoute,
protected authService: AuthService
) {}
async ngOnInit() {
this.route.queryParams.subscribe((params) => {
if (params['originUrl']) {
this.originUrl = params['originUrl'];
this.error = params['accessError'];
this.applyErrorToForm();
}
});
// Set the username if authenticated as default value
const username = await this.authService.getUsername();
if (username) {
this.participantForm.get('name')?.setValue(username);
}
}
get name() {
return this.participantForm.get('name');
}
async onSubmit() {
if (this.participantForm.valid) {
const participantName = this.participantForm.value.name;
let urlTree = this.router.parseUrl(this.originUrl);
urlTree.queryParams = { ...urlTree.queryParams, 'participant-name': participantName };
await this.router.navigateByUrl(urlTree);
}
}
private applyErrorToForm() {
if (this.error === 'participant-exists') {
this.participantForm.get('name')?.setErrors({ participantExists: true });
}
}
}

View File

@ -1,7 +1,45 @@
@if (!serverError && !loading) {
@if (!showRoom) {
<div class="form-container">
<mat-card class="form-card">
<h2 class="form-title">What is your name?</h2>
<form [formGroup]="participantForm" (ngSubmit)="accessRoom()">
<mat-form-field appearance="outline" class="full-width">
<mat-label>Name</mat-label>
<input
id="participant-name-input"
matInput
placeholder="Enter your name"
formControlName="name"
required
/>
@if (participantForm.get('name')?.hasError('minlength')) {
<mat-error> The name must be at least <strong>4 characters</strong> </mat-error>
}
@if (participantForm.get('name')?.hasError('required')) {
<mat-error> The name is <strong>required</strong> </mat-error>
}
@if (participantForm.get('name')?.hasError('participantExists')) {
<mat-error>
The name is already taken. <strong> Please choose another name </strong>
</mat-error>
}
</mat-form-field>
<button
mat-raised-button
color="primary"
id="participant-name-submit"
class="full-width"
[disabled]="participantForm.invalid"
>
Continue
</button>
</form>
</mat-card>
</div>
} @else {
<ov-videoconference
[token]="token"
[tokenError]="serverError"
[token]="participantToken"
[participantName]="participantName"
[prejoin]="featureFlags.showPrejoin"
[prejoinDisplayParticipantName]="false"
@ -17,21 +55,11 @@
[toolbarActivitiesPanelButton]="true"
[activitiesPanelRecordingActivity]="true"
[activitiesPanelBroadcastingActivity]="false"
(onTokenRequested)="onTokenRequested($event)"
(onTokenRequested)="onTokenRequested()"
(onParticipantConnected)="onParticipantConnected($event)"
(onParticipantLeft)="onParticipantLeft($event)"
(onRecordingStartRequested)="onRecordingStartRequested($event)"
(onRecordingStopRequested)="onRecordingStopRequested($event)"
(onRecordingDeleteRequested)="onRecordingDeleteRequested($event)"
>
</ov-videoconference>
}
@if (!loading && serverError) {
<div class="error">
<mat-icon>error</mat-icon>
<span>
{{ serverError }}
</span>
</div>
}

View File

@ -1,9 +1,36 @@
.error {
height: 100%;
width: 100%;
text-align: center;
margin-top: 20px;
mat-icon {
vertical-align: bottom;
}
.form-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--ov-background-color);
}
.form-card {
width: 400px;
padding: 20px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
border-radius: var(--ov-surface-radius);
background-color: var(--ov-surface-color);
}
.form-title {
text-align: center;
margin-bottom: 20px;
color: var(--ov-text-surface-color);
}
.full-width {
width: 100%;
margin-bottom: 20px;
}
button {
height: 56px;
border-radius: var(--ov-surface-radius);
}
button:not([disabled]) {
background-color: var(--ov-accent-action-color);
color: var(--ov-text-primary-color);
}

View File

@ -1,53 +1,74 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MatIcon } from '@angular/material/icon';
import { Location } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { ActivatedRoute, Router } from '@angular/router';
import { MeetRecordingAccess, MeetRoomPreferences, OpenViduMeetPermissions, ParticipantRole } from '@lib/typings/ce';
import {
RecordingDeleteRequestedEvent,
RecordingStartRequestedEvent,
RecordingStopRequestedEvent,
ApiDirectiveModule,
ParticipantLeftEvent,
ParticipantModel,
OpenViduComponentsUiModule,
ParticipantLeftReason
ParticipantLeftEvent,
ParticipantLeftReason,
ParticipantModel,
RecordingStartRequestedEvent,
RecordingStopRequestedEvent
} from 'openvidu-components-angular';
import {
MeetChatPreferences,
MeetRecordingAccess,
MeetRecordingPreferences,
MeetVirtualBackgroundPreferences
} from '@lib/typings/ce';
import {
HttpService,
WebComponentManagerService,
ContextService,
RoomService,
SessionStorageService
} from '../../services';
import { OutboundEventMessage } from 'webcomponent/src/models/message.type';
import { WebComponentEvent } from 'webcomponent/src/models/event.model';
import { OutboundEventMessage } from 'webcomponent/src/models/message.type';
import {
AuthService,
ContextService,
HttpService,
RoomService,
SessionStorageService,
WebComponentManagerService
} from '../../services';
@Component({
selector: 'app-video-room',
templateUrl: './video-room.component.html',
styleUrls: ['./video-room.component.scss'],
standalone: true,
imports: [OpenViduComponentsUiModule, ApiDirectiveModule, MatIcon]
imports: [
OpenViduComponentsUiModule,
ApiDirectiveModule,
MatFormFieldModule,
MatInputModule,
FormsModule,
ReactiveFormsModule,
MatCardModule,
MatButtonModule
]
})
export class VideoRoomComponent implements OnInit, OnDestroy {
participantForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(4)])
});
showRoom = false;
roomId = '';
roomSecret = '';
participantName = '';
token = '';
serverError = '';
loading = true;
chatPreferences: MeetChatPreferences = { enabled: true };
recordingPreferences: MeetRecordingPreferences = {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER
participantToken = '';
participantRole: ParticipantRole = ParticipantRole.PUBLISHER;
participantPermissions: OpenViduMeetPermissions = {
canRecord: false,
canChat: false,
canChangeVirtualBackground: false,
canPublishScreen: false
};
roomPreferences: MeetRoomPreferences = {
recordingPreferences: {
enabled: true,
allowAccessTo: MeetRecordingAccess.ADMIN_MODERATOR_PUBLISHER
},
chatPreferences: { enabled: true },
virtualBackgroundPreferences: { enabled: true }
};
virtualBackgroundPreferences: MeetVirtualBackgroundPreferences = { enabled: true };
featureFlags = {
videoEnabled: true,
audioEnabled: true,
@ -63,56 +84,132 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
constructor(
protected httpService: HttpService,
protected router: Router,
protected route: ActivatedRoute,
protected location: Location,
protected authService: AuthService,
protected ctxService: ContextService,
protected roomService: RoomService,
protected wcManagerService: WebComponentManagerService,
protected sessionStorageService: SessionStorageService,
protected cdr: ChangeDetectorRef
protected sessionStorageService: SessionStorageService
) {}
async ngOnInit() {
try {
this.roomId = this.ctxService.getRoomId();
this.participantName = this.ctxService.getParticipantName();
this.roomId = this.ctxService.getRoomId();
const secret = this.ctxService.getSecret();
const storageSecret = this.sessionStorageService.getModeratorSecret(this.roomId);
this.roomSecret = storageSecret || secret;
if (this.ctxService.isEmbeddedMode()) {
this.featureFlags.showPrejoin = false;
}
// Apply participant name from context if set, otherwise use authenticated username
const contextParticipantName = this.ctxService.getParticipantName();
const username = await this.authService.getUsername();
const participantName = contextParticipantName || username;
// TODO: Apply room preferences from saved room using context service
// await this.loadRoomPreferences();
// TODO: Extract permissions from token and apply them to the component
this.applyParticipantPermissions();
} catch (error: any) {
console.error('Error fetching room preferences', error);
this.serverError = error.error.message || error.message || error.error;
if (participantName) {
this.participantForm.get('name')?.setValue(participantName);
}
this.loading = false;
}
ngOnDestroy(): void {
// Clean up the context service
// this.contextService.clearContext();
this.wcManagerService.stopCommandsListener();
}
async onTokenRequested(participantName: string) {
try {
if (this.ctxService.isStandaloneMode()) {
// As token is not provided, we need to set the participant name from
// ov-videoconference event
this.ctxService.setParticipantName(participantName);
}
this.token = this.ctxService.getParticipantToken();
} catch (error: any) {
console.error(error);
this.serverError = error.error;
async accessRoom() {
if (!this.participantForm.valid) {
return;
}
this.loading = false;
this.cdr.detectChanges();
this.participantName = this.participantForm.value.name!;
try {
await this.generateParticipantToken();
await this.replaceUrlQueryParams();
// await this.loadRoomPreferences();
this.applyParticipantPermissions();
this.showRoom = true;
} catch (error) {
console.error('Error accessing room:', error);
}
}
async onTokenRequested() {
// Participant token must be set only when requested
this.participantToken = this.ctxService.getParticipantToken();
}
private async generateParticipantToken() {
try {
const response = await this.httpService.generateParticipantToken({
roomId: this.roomId,
participantName: this.participantName,
secret: this.roomSecret
});
this.setParticipantToken(response.token);
} catch (error: any) {
console.error('Error generating participant token:', error);
switch (error.status) {
case 400:
// Invalid secret
this.redirectToErrorPage('invalid-secret');
break;
case 404:
// Room not found
this.redirectToErrorPage('invalid-room');
break;
case 409:
// Participant already exists.
// Show the error message in participant name input form
this.participantForm.get('name')?.setErrors({ participantExists: true });
throw new Error('Participant already exists in the room');
default:
this.redirectToErrorPage('internal-error');
}
}
}
private setParticipantToken(token: string): void {
try {
this.ctxService.setParticipantToken(token);
this.participantRole = this.ctxService.getParticipantRole();
this.participantPermissions = this.ctxService.getParticipantPermissions();
} catch (error: any) {
console.error('Error setting token in context', error);
}
}
private async replaceUrlQueryParams() {
let secretQueryParam = this.roomSecret;
// If participant is moderator, store the moderator secret in session storage
// and replace the secret in the URL with the publisher secret
if (this.participantRole === ParticipantRole.MODERATOR) {
try {
const { moderatorSecret, publisherSecret } = await this.getRoomSecrets();
this.sessionStorageService.setModeratorSecret(this.roomId, moderatorSecret);
secretQueryParam = publisherSecret;
} catch (error) {
console.error('error', error);
}
}
// Replace secret and participant name in the URL query parameters
const queryParams = {
...this.route.snapshot.queryParams,
secret: secretQueryParam,
'participant-name': this.participantName
};
const urlTree = this.router.createUrlTree([], { queryParams, queryParamsHandling: 'merge' });
const newUrl = this.router.serializeUrl(urlTree);
this.location.replaceState(newUrl);
}
private async getRoomSecrets(): Promise<{ moderatorSecret: string; publisherSecret: string }> {
const { moderatorRoomUrl, publisherRoomUrl } = await this.httpService.getRoom(this.roomId);
const publisherUrl = new URL(publisherRoomUrl);
const publisherSecret = publisherUrl.searchParams.get('secret') || '';
const moderatorUrl = new URL(moderatorRoomUrl);
const moderatorSecret = moderatorUrl.searchParams.get('secret') || '';
return { publisherSecret, moderatorSecret };
}
onParticipantConnected(event: ParticipantModel) {
@ -158,11 +255,7 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
this.sessionStorageService.removeModeratorSecret(event.roomName);
}
//if (this.contextService.isEmbeddedMode()) this.sendMessageToParent(event);
this.redirectTo(redirectURL, isExternalURL);
// Stop listening to commands from the parent
this.wcManagerService.stopCommandsListener();
}
async onRecordingStartRequested(event: RecordingStartRequestedEvent) {
@ -186,18 +279,6 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
}
}
async onRecordingDeleteRequested(event: RecordingDeleteRequestedEvent) {
try {
const { recordingId } = event;
if (!recordingId) throw new Error('Recording ID not found when deleting recording');
await this.httpService.deleteRecording(recordingId);
} catch (error) {
console.error(error);
}
}
/**
* Loads the room preferences from the global preferences service and assigns them to the component.
*
@ -208,26 +289,26 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
* @returns {Promise<void>} A promise that resolves when the room preferences have been loaded and applied.
*/
private async loadRoomPreferences() {
const preferences = await this.roomService.getRoomPreferences();
// Assign the preferences to the component
Object.assign(this, preferences);
try {
this.roomPreferences = await this.roomService.getRoomPreferences();
} catch (error) {
console.error('Error loading room preferences:', error);
}
this.featureFlags.showChat = this.chatPreferences.enabled;
this.featureFlags.showRecording = this.recordingPreferences.enabled;
this.featureFlags.showBackgrounds = this.virtualBackgroundPreferences.enabled;
this.featureFlags.showChat = this.roomPreferences.chatPreferences.enabled;
this.featureFlags.showRecording = this.roomPreferences.recordingPreferences.enabled;
this.featureFlags.showBackgrounds = this.roomPreferences.virtualBackgroundPreferences.enabled;
}
/**
* Configures the feature flags based on the token permissions.
*
* This method checks the token permissions and sets the feature flags accordingly.
* Configures the feature flags based on participant permissions.
*/
private applyParticipantPermissions() {
if (this.featureFlags.showChat) {
this.featureFlags.showChat = this.ctxService.canChat();
this.featureFlags.showChat = this.participantPermissions.canChat;
}
if (this.featureFlags.showRecording) {
this.featureFlags.showRecording = this.ctxService.canRecord();
this.featureFlags.showRecording = this.participantPermissions.canRecord;
}
}
@ -240,4 +321,8 @@ export class VideoRoomComponent implements OnInit, OnDestroy {
this.router.navigate([url], { replaceUrl: true });
}
}
private redirectToErrorPage(reason: string) {
this.router.navigate(['error'], { queryParams: { reason } });
}
}

View File

@ -1,17 +1,14 @@
import { Routes } from '@angular/router';
import {
applicationModeGuard,
checkParticipantNameGuard,
checkParticipantRoleAndAuthGuard,
checkUserAuthenticatedGuard,
checkUserNotAuthenticatedGuard,
extractRecordingQueryParamsGuard,
extractRoomQueryParamsGuard,
removeModeratorSecretGuard,
replaceModeratorSecretGuard,
runGuardsSerially,
validateRecordingAccessGuard,
validateRoomAccessGuard
validateRecordingAccessGuard
} from '../guards';
import {
ConsoleComponent,
@ -19,7 +16,6 @@ import {
ErrorComponent,
LoginComponent,
OverviewComponent,
ParticipantNameFormComponent,
RecordingsComponent,
RoomFormComponent,
RoomRecordingsComponent,
@ -83,20 +79,9 @@ export const baseRoutes: Routes = [
path: 'room/:room-id',
component: VideoRoomComponent,
canActivate: [
runGuardsSerially(
applicationModeGuard,
extractRoomQueryParamsGuard,
checkParticipantRoleAndAuthGuard,
checkParticipantNameGuard,
validateRoomAccessGuard,
replaceModeratorSecretGuard
)
runGuardsSerially(applicationModeGuard, extractRoomQueryParamsGuard, checkParticipantRoleAndAuthGuard)
]
},
{
path: 'room/:room-id/participant-name',
component: ParticipantNameFormComponent
},
{
path: 'room/:room-id/recordings',
component: RoomRecordingsComponent,

View File

@ -150,12 +150,8 @@ export class ContextService {
return this.context.participantRole === ParticipantRole.MODERATOR;
}
canRecord(): boolean {
return this.context.participantPermissions.canRecord;
}
canChat(): boolean {
return this.context.participantPermissions.canChat;
getParticipantPermissions() {
return this.context.participantPermissions;
}
setRecordingPermissionsFromToken(token: string): void {