frontend: Implement participant role retrieval and enhance authentication guards and http interceptor
This commit is contained in:
parent
bc33e9c5d9
commit
28b65db651
@ -1,6 +1,6 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AuthService, ContextService } from '../services';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, RedirectCommand, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AuthService, ContextService, HttpService, SessionStorageService } from '../services';
|
||||
import { AuthMode, ParticipantRole } from '@lib/typings/ce';
|
||||
|
||||
export const checkUserAuthenticatedGuard: CanActivateFn = async (
|
||||
@ -47,11 +47,26 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
|
||||
_route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) => {
|
||||
const router = inject(Router);
|
||||
const authService = inject(AuthService);
|
||||
const contextService = inject(ContextService);
|
||||
const router = inject(Router);
|
||||
const sessionStorageService = inject(SessionStorageService);
|
||||
const httpService = inject(HttpService);
|
||||
|
||||
// Get participant role by room secret
|
||||
let participantRole: ParticipantRole;
|
||||
|
||||
try {
|
||||
const roomName = contextService.getRoomName();
|
||||
const secret = contextService.getSecret();
|
||||
const storageSecret = sessionStorageService.getModeratorSecret(roomName);
|
||||
|
||||
participantRole = await httpService.getParticipantRole(roomName, storageSecret || secret);
|
||||
} catch (error) {
|
||||
console.error('Error getting participant role:', error);
|
||||
return router.createUrlTree(['unauthorized'], { queryParams: { reason: 'unauthorized-participant' } });
|
||||
}
|
||||
|
||||
const participantRole = contextService.getParticipantRole();
|
||||
const authMode = await contextService.getAuthModeToEnterRoom();
|
||||
|
||||
// If the user is a moderator and the room requires authentication for moderators only,
|
||||
@ -60,16 +75,18 @@ export const checkParticipantRoleAndAuthGuard: CanActivateFn = async (
|
||||
const isAuthRequiredForModerators =
|
||||
authMode === AuthMode.MODERATORS_ONLY && participantRole === ParticipantRole.MODERATOR;
|
||||
const isAuthRequiredForAllUsers = authMode === AuthMode.ALL_USERS;
|
||||
console.log('Participant role:', participantRole);
|
||||
|
||||
if (isAuthRequiredForModerators || isAuthRequiredForAllUsers) {
|
||||
// Check if user is authenticated
|
||||
const isAuthenticated = await authService.isUserAuthenticated();
|
||||
if (!isAuthenticated) {
|
||||
// Redirect to the login page with query param to redirect back to the room
|
||||
return router.createUrlTree(['login'], {
|
||||
const loginRoute = router.createUrlTree(['login'], {
|
||||
queryParams: { redirectTo: state.url }
|
||||
});
|
||||
return new RedirectCommand(loginRoute, {
|
||||
skipLocationChange: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@ export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, ne
|
||||
const sessionStorageService = inject(SessionStorageService);
|
||||
const httpService: HttpService = inject(HttpService);
|
||||
|
||||
const url = router.getCurrentNavigation()?.finalUrl?.toString() || router.url;
|
||||
const pageUrl = router.getCurrentNavigation()?.finalUrl?.toString() || router.url;
|
||||
const requestUrl = req.url;
|
||||
|
||||
req = req.clone({
|
||||
withCredentials: true
|
||||
@ -26,9 +27,15 @@ export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, ne
|
||||
}),
|
||||
catchError((error: HttpErrorResponse) => {
|
||||
if (error.url?.includes('/auth/refresh')) {
|
||||
console.error('Error refreshing access token. Logging out...');
|
||||
const redirectTo = url.startsWith('/console') ? 'console/login' : 'login';
|
||||
authService.logout(redirectTo);
|
||||
console.error('Error refreshing access token');
|
||||
|
||||
// If the original request was not to the profile endpoint, logout and redirect to the login page
|
||||
if (!requestUrl.includes('/profile')) {
|
||||
console.log('Logging out...');
|
||||
const redirectTo = pageUrl.startsWith('/console') ? 'console/login' : 'login';
|
||||
authService.logout(redirectTo);
|
||||
}
|
||||
|
||||
throw firstError;
|
||||
}
|
||||
|
||||
@ -79,9 +86,12 @@ export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest<unknown>, ne
|
||||
}
|
||||
|
||||
// Expired access/participant token
|
||||
if (url.startsWith('/room')) {
|
||||
if (pageUrl.startsWith('/room') && !requestUrl.includes('/profile')) {
|
||||
// If the error occurred in a room page and the request is not to the profile endpoint,
|
||||
// refresh the participant token
|
||||
return refreshParticipantToken(error);
|
||||
} else if (!url.startsWith('/console/login') && !url.startsWith('/login')) {
|
||||
} else if (!pageUrl.startsWith('/console/login') && !pageUrl.startsWith('/login')) {
|
||||
// If the error occurred in a page that is not the login page, refresh the access token
|
||||
return refreshAccessToken(error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,8 @@ export class LoginComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
this.router.navigate([this.redirectTo]);
|
||||
let urlTree = this.router.parseUrl(this.redirectTo);
|
||||
this.router.navigateByUrl(urlTree);
|
||||
} catch (error) {
|
||||
if ((error as HttpErrorResponse).status === 429) {
|
||||
this.loginErrorMessage = 'Too many login attempts. Please try again later';
|
||||
|
||||
@ -35,12 +35,7 @@ export const baseRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: RoomCreatorComponent,
|
||||
canActivate: [
|
||||
runGuardsSerially(
|
||||
checkRoomCreatorEnabledGuard,
|
||||
checkUserAuthenticatedGuard
|
||||
)
|
||||
],
|
||||
canActivate: [runGuardsSerially(checkRoomCreatorEnabledGuard, checkUserAuthenticatedGuard)],
|
||||
data: {
|
||||
checkSkipAuth: true,
|
||||
expectedRoles: [UserRole.USER],
|
||||
@ -121,9 +116,9 @@ export const baseRoutes: Routes = [
|
||||
runGuardsSerially(
|
||||
applicationModeGuard,
|
||||
extractQueryParamsGuard,
|
||||
checkParticipantRoleAndAuthGuard,
|
||||
checkParticipantNameGuard,
|
||||
validateRoomAccessGuard,
|
||||
checkParticipantRoleAndAuthGuard,
|
||||
replaceModeratorSecretGuard
|
||||
)
|
||||
]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { OpenViduMeetRoom, OpenViduMeetRoomOptions } from 'projects/shared-meet-components/src/lib/typings/ce/room';
|
||||
import { GlobalPreferences, RoomPreferences, TokenOptions, User } from '@lib/typings/ce';
|
||||
import { GlobalPreferences, ParticipantRole, RoomPreferences, TokenOptions, User } from '@lib/typings/ce';
|
||||
import { RecordingInfo, Room } from 'openvidu-components-angular';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
@ -40,12 +40,24 @@ export class HttpService {
|
||||
return this.getRequest(path);
|
||||
}
|
||||
|
||||
getParticipantRole(roomName: string, secret: string): Promise<ParticipantRole> {
|
||||
return this.getRequest(
|
||||
`${this.INTERNAL_API_PATH_PREFIX}/${this.API_V1_VERSION}/rooms/${roomName}/participant-role?secret=${secret}`
|
||||
);
|
||||
}
|
||||
|
||||
generateParticipantToken(tokenOptions: TokenOptions): Promise<{ token: string }> {
|
||||
return this.postRequest(`${this.INTERNAL_API_PATH_PREFIX}/${this.API_V1_VERSION}/participants/token`, tokenOptions);
|
||||
return this.postRequest(
|
||||
`${this.INTERNAL_API_PATH_PREFIX}/${this.API_V1_VERSION}/participants/token`,
|
||||
tokenOptions
|
||||
);
|
||||
}
|
||||
|
||||
refreshParticipantToken(tokenOptions: TokenOptions): Promise<{ token: string }> {
|
||||
return this.postRequest(`${this.INTERNAL_API_PATH_PREFIX}/${this.API_V1_VERSION}/participants/token/refresh`, tokenOptions);
|
||||
return this.postRequest(
|
||||
`${this.INTERNAL_API_PATH_PREFIX}/${this.API_V1_VERSION}/participants/token/refresh`,
|
||||
tokenOptions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user