From 72b8a9d12fe43213b1cfd78c3e2fe9ca920048c0 Mon Sep 17 00:00:00 2001 From: juancarmore Date: Thu, 27 Mar 2025 19:22:53 +0100 Subject: [PATCH] frontend: Add run-serially.guard to execute multiple guards in sequence --- .../src/lib/guards/index.ts | 1 + .../src/lib/guards/run-serially.guard.ts | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 frontend/projects/shared-meet-components/src/lib/guards/run-serially.guard.ts diff --git a/frontend/projects/shared-meet-components/src/lib/guards/index.ts b/frontend/projects/shared-meet-components/src/lib/guards/index.ts index 2d5f3e5..eb8bf25 100644 --- a/frontend/projects/shared-meet-components/src/lib/guards/index.ts +++ b/frontend/projects/shared-meet-components/src/lib/guards/index.ts @@ -5,3 +5,4 @@ export * from './application-mode.guard'; export * from './participant-name.guard'; export * from './replace-moderator-secret.guard'; export * from './room-creator.guard'; +export * from './run-serially.guard'; diff --git a/frontend/projects/shared-meet-components/src/lib/guards/run-serially.guard.ts b/frontend/projects/shared-meet-components/src/lib/guards/run-serially.guard.ts new file mode 100644 index 0000000..645814e --- /dev/null +++ b/frontend/projects/shared-meet-components/src/lib/guards/run-serially.guard.ts @@ -0,0 +1,36 @@ +import { EnvironmentInjector, inject, runInInjectionContext } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivateFn, GuardResult, RouterStateSnapshot } from '@angular/router'; +import { isObservable, lastValueFrom } from 'rxjs'; + +/** + * This guard is used to run multiple guards serially. + * + * @param guards List of guards to run serially. + * @returns A guard that runs the provided guards serially. + */ +export const runGuardsSerially = (...guards: CanActivateFn[]): CanActivateFn => { + return async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const injector = inject(EnvironmentInjector); + + for (const guard of guards) { + const result = runInInjectionContext(injector, () => guard(route, state)); + let resolvedResult: GuardResult; + + if (result instanceof Promise) { + resolvedResult = await result; + } else if (isObservable(result)) { + resolvedResult = await lastValueFrom(result); + } else { + resolvedResult = result; + } + + if (typeof resolvedResult === 'boolean' && !resolvedResult) { + return false; + } else if (typeof resolvedResult !== 'boolean') { + return resolvedResult; + } + } + + return true; + }; +};