@cccteam/ccc-lib 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,3 +47,7 @@ To run the library's tests, use the following command:
47
47
  ```bash
48
48
  ng test ccc-lib
49
49
  ```
50
+
51
+ ### Known Issues
52
+
53
+ - **Contentful Dependency**: The library currently has a hard dependency on `@contentful/rich-text-types` due to the `CustomTypes.ContentfulDocument` type definition in the resource metadata. This means consumers of the library must have this package installed, even if they are not using this custom type.
@@ -1,17 +1,55 @@
1
1
  import { inject } from '@angular/core';
2
+ import { Router } from '@angular/router';
2
3
  import { AuthService } from '@cccteam/ccc-lib/auth-service';
3
- import { BASE_URL } from '@cccteam/ccc-lib/types';
4
+ import { BASE_URL, API_URL } from '@cccteam/ccc-lib/types';
4
5
  import { of } from 'rxjs';
5
6
  import { map, catchError } from 'rxjs/operators';
6
7
 
7
- const AuthenticationGuard = (route, routerState) => {
8
+ /**
9
+ * Route guard that protects routes using OIDC (OpenID Connect) authentication.
10
+ *
11
+ * If the user is not authenticated, they are redirected to the external OIDC
12
+ * login endpoint with the current URL encoded as a return URL parameter.
13
+ *
14
+ */
15
+ const OIDCAuthenticationGuard = (_, routerState) => {
8
16
  const authService = inject(AuthService);
9
17
  const baseUrl = inject(BASE_URL);
18
+ const apiUrl = inject(API_URL);
10
19
  const authenticate = () => {
11
20
  const url = routerState.url;
12
21
  const absoluteUrl = baseUrl + (!url.toString().startsWith('/') ? '/' + url : url);
13
22
  const encodedUrl = encodeURIComponent(absoluteUrl);
14
- window.location.href = `${authService.loginRoute()}?returnUrl=${encodedUrl}`;
23
+ window.location.href = `${apiUrl}/user/login?returnUrl=${encodedUrl}`;
24
+ };
25
+ if (authService.authenticated()) {
26
+ return of(true);
27
+ }
28
+ return authService.checkUserSession().pipe(map((sessionInfo) => {
29
+ if (sessionInfo?.authenticated) {
30
+ return true;
31
+ }
32
+ authenticate();
33
+ return false;
34
+ }), catchError(() => {
35
+ authenticate();
36
+ return of(false);
37
+ }));
38
+ };
39
+ /**
40
+ * Route guard that protects routes using internal login-based authentication.
41
+ *
42
+ * If the user is not authenticated, they are redirected to the application's
43
+ * internal FRONTEND_LOGIN_PATH route. The attempted URL is stored in the AuthService so the
44
+ * user can be redirected back after successful login.
45
+ *
46
+ */
47
+ const LoginAuthenticationGuard = (_, routerState) => {
48
+ const router = inject(Router);
49
+ const authService = inject(AuthService);
50
+ const authenticate = () => {
51
+ authService.redirectUrl.set(routerState.url);
52
+ router.navigate([authService.loginRoute()]);
15
53
  };
16
54
  if (authService.authenticated()) {
17
55
  return of(true);
@@ -32,5 +70,5 @@ const AuthenticationGuard = (route, routerState) => {
32
70
  * Generated bundle index. Do not edit.
33
71
  */
34
72
 
35
- export { AuthenticationGuard };
73
+ export { LoginAuthenticationGuard, OIDCAuthenticationGuard };
36
74
  //# sourceMappingURL=cccteam-ccc-lib-auth-authentication-guard.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-auth-authentication-guard.mjs","sources":["../../../projects/ccc-lib/auth-authentication-guard/authentication.guard.ts","../../../projects/ccc-lib/auth-authentication-guard/cccteam-ccc-lib-auth-authentication-guard.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { BASE_URL } from '@cccteam/ccc-lib/types';\nimport { Observable, of } from 'rxjs';\nimport { catchError, map } from 'rxjs/operators';\n\nexport const AuthenticationGuard = (\n route: ActivatedRouteSnapshot,\n routerState: RouterStateSnapshot,\n): Observable<boolean> => {\n const authService = inject(AuthService);\n const baseUrl = inject(BASE_URL);\n\n const authenticate = (): void => {\n const url = routerState.url;\n const absoluteUrl = baseUrl + (!url.toString().startsWith('/') ? '/' + url : url);\n const encodedUrl = encodeURIComponent(absoluteUrl);\n window.location.href = `${authService.loginRoute()}?returnUrl=${encodedUrl}`;\n };\n\n if (authService.authenticated()) {\n return of(true);\n }\n\n return authService.checkUserSession().pipe(\n map((sessionInfo) => {\n if (sessionInfo?.authenticated) {\n return true;\n }\n\n authenticate();\n return false;\n }),\n catchError(() => {\n authenticate();\n return of(false);\n }),\n );\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAOa,mBAAmB,GAAG,CACjC,KAA6B,EAC7B,WAAgC,KACT;AACvB,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACvC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEhC,MAAM,YAAY,GAAG,MAAW;AAC9B,QAAA,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG;QAC3B,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjF,QAAA,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC;AAClD,QAAA,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAA,EAAG,WAAW,CAAC,UAAU,EAAE,CAAA,WAAA,EAAc,UAAU,EAAE;AAC9E,IAAA,CAAC;AAED,IAAA,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE;AAC/B,QAAA,OAAO,EAAE,CAAC,IAAI,CAAC;IACjB;AAEA,IAAA,OAAO,WAAW,CAAC,gBAAgB,EAAE,CAAC,IAAI,CACxC,GAAG,CAAC,CAAC,WAAW,KAAI;AAClB,QAAA,IAAI,WAAW,EAAE,aAAa,EAAE;AAC9B,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,CAAC,EACF,UAAU,CAAC,MAAK;AACd,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,EAAE,CAAC,KAAK,CAAC;IAClB,CAAC,CAAC,CACH;AACH;;ACvCA;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-auth-authentication-guard.mjs","sources":["../../../projects/ccc-lib/auth-authentication-guard/authentication.guard.ts","../../../projects/ccc-lib/auth-authentication-guard/cccteam-ccc-lib-auth-authentication-guard.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { API_URL, BASE_URL } from '@cccteam/ccc-lib/types';\nimport { Observable, of } from 'rxjs';\nimport { catchError, map } from 'rxjs/operators';\n\n/**\n * Route guard that protects routes using OIDC (OpenID Connect) authentication.\n *\n * If the user is not authenticated, they are redirected to the external OIDC\n * login endpoint with the current URL encoded as a return URL parameter.\n *\n */\nexport const OIDCAuthenticationGuard = (\n _: ActivatedRouteSnapshot,\n routerState: RouterStateSnapshot,\n): Observable<boolean> => {\n const authService = inject(AuthService);\n const baseUrl = inject(BASE_URL);\n const apiUrl = inject(API_URL);\n\n const authenticate = (): void => {\n const url = routerState.url;\n const absoluteUrl = baseUrl + (!url.toString().startsWith('/') ? '/' + url : url);\n const encodedUrl = encodeURIComponent(absoluteUrl);\n window.location.href = `${apiUrl}/user/login?returnUrl=${encodedUrl}`;\n };\n\n if (authService.authenticated()) {\n return of(true);\n }\n\n return authService.checkUserSession().pipe(\n map((sessionInfo) => {\n if (sessionInfo?.authenticated) {\n return true;\n }\n\n authenticate();\n return false;\n }),\n catchError(() => {\n authenticate();\n return of(false);\n }),\n );\n};\n\n/**\n * Route guard that protects routes using internal login-based authentication.\n *\n * If the user is not authenticated, they are redirected to the application's\n * internal FRONTEND_LOGIN_PATH route. The attempted URL is stored in the AuthService so the\n * user can be redirected back after successful login.\n *\n */\nexport const LoginAuthenticationGuard = (\n _: ActivatedRouteSnapshot,\n routerState: RouterStateSnapshot,\n): Observable<boolean> => {\n const router = inject(Router);\n const authService = inject(AuthService);\n\n const authenticate = (): void => {\n authService.redirectUrl.set(routerState.url);\n router.navigate([authService.loginRoute()]);\n };\n\n if (authService.authenticated()) {\n return of(true);\n }\n\n return authService.checkUserSession().pipe(\n map((sessionInfo) => {\n if (sessionInfo?.authenticated) {\n return true;\n }\n\n authenticate();\n return false;\n }),\n catchError(() => {\n authenticate();\n return of(false);\n }),\n );\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;AAOA;;;;;;AAMG;MACU,uBAAuB,GAAG,CACrC,CAAyB,EACzB,WAAgC,KACT;AACvB,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;AACvC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;AAChC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;IAE9B,MAAM,YAAY,GAAG,MAAW;AAC9B,QAAA,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG;QAC3B,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjF,QAAA,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC;QAClD,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,MAAM,CAAA,sBAAA,EAAyB,UAAU,CAAA,CAAE;AACvE,IAAA,CAAC;AAED,IAAA,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE;AAC/B,QAAA,OAAO,EAAE,CAAC,IAAI,CAAC;IACjB;AAEA,IAAA,OAAO,WAAW,CAAC,gBAAgB,EAAE,CAAC,IAAI,CACxC,GAAG,CAAC,CAAC,WAAW,KAAI;AAClB,QAAA,IAAI,WAAW,EAAE,aAAa,EAAE;AAC9B,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,CAAC,EACF,UAAU,CAAC,MAAK;AACd,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,EAAE,CAAC,KAAK,CAAC;IAClB,CAAC,CAAC,CACH;AACH;AAEA;;;;;;;AAOG;MACU,wBAAwB,GAAG,CACtC,CAAyB,EACzB,WAAgC,KACT;AACvB,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IAEvC,MAAM,YAAY,GAAG,MAAW;QAC9B,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC,CAAC;AAC7C,IAAA,CAAC;AAED,IAAA,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE;AAC/B,QAAA,OAAO,EAAE,CAAC,IAAI,CAAC;IACjB;AAEA,IAAA,OAAO,WAAW,CAAC,gBAAgB,EAAE,CAAC,IAAI,CACxC,GAAG,CAAC,CAAC,WAAW,KAAI;AAClB,QAAA,IAAI,WAAW,EAAE,aAAa,EAAE;AAC9B,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,KAAK;AACd,IAAA,CAAC,CAAC,EACF,UAAU,CAAC,MAAK;AACd,QAAA,YAAY,EAAE;AACd,QAAA,OAAO,EAAE,CAAC,KAAK,CAAC;IAClB,CAAC,CAAC,CACH;AACH;;ACvFA;;AAEG;;;;"}
@@ -1,15 +1,15 @@
1
1
  import { inject } from '@angular/core';
2
2
  import { MatDialog } from '@angular/material/dialog';
3
- import { AuthService } from '@cccteam/ccc-lib/auth-service';
4
3
  import { LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource-modals';
5
4
  import { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';
5
+ import { FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';
6
6
  import { tap, firstValueFrom } from 'rxjs';
7
7
 
8
8
  const canDeactivateGuard = async (_, __, ___, nextState) => {
9
- const auth = inject(AuthService);
10
9
  const dialog = inject(MatDialog);
11
10
  const formStateService = inject(FormStateService);
12
- if (nextState?.url.includes(auth.loginRoute())) {
11
+ const loginPath = inject(FRONTEND_LOGIN_PATH);
12
+ if (nextState?.url.includes(loginPath)) {
13
13
  return true;
14
14
  }
15
15
  if (!formStateService.isDirty()) {
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-guards.mjs","sources":["../../../projects/ccc-lib/guards/can-deactivate.guard.ts","../../../projects/ccc-lib/guards/cccteam-ccc-lib-guards.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { CanDeactivateFn, UrlTree } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource-modals';\nimport { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';\nimport { firstValueFrom, Observable, tap } from 'rxjs';\n\nexport type CanDeactivateType = Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => CanDeactivateType;\n}\n\nexport const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = async (_, __, ___, nextState) => {\n const auth = inject(AuthService);\n const dialog = inject(MatDialog);\n const formStateService = inject(FormStateService);\n\n if (nextState?.url.includes(auth.loginRoute())) {\n return true;\n }\n\n if (!formStateService.isDirty()) {\n return true;\n }\n\n const existingDialog = dialog.openDialogs.find(\n (d) => d.componentInstance instanceof LeavePageConfirmationModalComponent,\n );\n\n const dialogRef = existingDialog ?? dialog.open(LeavePageConfirmationModalComponent, { delayFocusTrap: false });\n\n const result = dialogRef.afterClosed().pipe(\n tap((value) => {\n if (value === true) {\n formStateService.resetDirtyForms();\n }\n }),\n );\n\n return firstValueFrom(result);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;AAcO,MAAM,kBAAkB,GAA4C,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,KAAI;AACzG,IAAA,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAChC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;AAChC,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAEjD,IAAA,IAAI,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AAC9C,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE;AAC/B,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5C,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,YAAY,mCAAmC,CAC1E;AAED,IAAA,MAAM,SAAS,GAAG,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAE/G,IAAA,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,CACzC,GAAG,CAAC,CAAC,KAAK,KAAI;AACZ,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,gBAAgB,CAAC,eAAe,EAAE;QACpC;IACF,CAAC,CAAC,CACH;AAED,IAAA,OAAO,cAAc,CAAC,MAAM,CAAC;AAC/B;;AC1CA;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-guards.mjs","sources":["../../../projects/ccc-lib/guards/can-deactivate.guard.ts","../../../projects/ccc-lib/guards/cccteam-ccc-lib-guards.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { CanDeactivateFn, UrlTree } from '@angular/router';\nimport { LeavePageConfirmationModalComponent } from '@cccteam/ccc-lib/ccc-resource-modals';\nimport { FormStateService } from '@cccteam/ccc-lib/ccc-resource-services';\nimport { FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';\nimport { firstValueFrom, Observable, tap } from 'rxjs';\n\nexport type CanDeactivateType = Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => CanDeactivateType;\n}\n\nexport const canDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = async (_, __, ___, nextState) => {\n const dialog = inject(MatDialog);\n const formStateService = inject(FormStateService);\n const loginPath = inject(FRONTEND_LOGIN_PATH);\n\n if (nextState?.url.includes(loginPath)) {\n return true;\n }\n\n if (!formStateService.isDirty()) {\n return true;\n }\n\n const existingDialog = dialog.openDialogs.find(\n (d) => d.componentInstance instanceof LeavePageConfirmationModalComponent,\n );\n\n const dialogRef = existingDialog ?? dialog.open(LeavePageConfirmationModalComponent, { delayFocusTrap: false });\n\n const result = dialogRef.afterClosed().pipe(\n tap((value) => {\n if (value === true) {\n formStateService.resetDirtyForms();\n }\n }),\n );\n\n return firstValueFrom(result);\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;AAcO,MAAM,kBAAkB,GAA4C,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,KAAI;AACzG,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;AAChC,IAAA,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;AACjD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAE7C,IAAI,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;AACtC,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE;AAC/B,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAC5C,CAAC,CAAC,KAAK,CAAC,CAAC,iBAAiB,YAAY,mCAAmC,CAC1E;AAED,IAAA,MAAM,SAAS,GAAG,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAE/G,IAAA,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,IAAI,CACzC,GAAG,CAAC,CAAC,KAAK,KAAI;AACZ,QAAA,IAAI,KAAK,KAAK,IAAI,EAAE;YAClB,gBAAgB,CAAC,eAAe,EAAE;QACpC;IACF,CAAC,CAAC,CACH;AAED,IAAA,OAAO,cAAc,CAAC,MAAM,CAAC;AAC/B;;AC1CA;;AAEG;;;;"}
@@ -3,7 +3,7 @@ import { inject, signal, computed, Injectable } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Router } from '@angular/router';
5
5
  import { AuthService } from '@cccteam/ccc-lib/auth-service';
6
- import { IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, IDLE_KEEPALIVE_DURATION, AlertLevel } from '@cccteam/ccc-lib/types';
6
+ import { FRONTEND_LOGIN_PATH, IDLE_SESSION_DURATION, IDLE_WARNING_DURATION, IDLE_KEEPALIVE_DURATION, AlertLevel } from '@cccteam/ccc-lib/types';
7
7
  import { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';
8
8
  import { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';
9
9
  import { interval } from 'rxjs';
@@ -13,6 +13,7 @@ class IdleService {
13
13
  core = inject(UiCoreService);
14
14
  router = inject(Router);
15
15
  notifications = inject(NotificationService);
16
+ loginPath = inject(FRONTEND_LOGIN_PATH);
16
17
  sessionDuration = inject(IDLE_SESSION_DURATION);
17
18
  warningDuration = inject(IDLE_WARNING_DURATION);
18
19
  keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);
@@ -73,7 +74,7 @@ class IdleService {
73
74
  */
74
75
  logoutAndStop() {
75
76
  this.stop();
76
- this.router.navigate([this.auth.loginRoute()]);
77
+ this.router.navigate([this.loginPath]);
77
78
  this.core.publishError({
78
79
  message: 'You have been logged out due to inactivity.',
79
80
  level: AlertLevel.INFO,
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-ui-idle-service.mjs","sources":["../../../projects/ccc-lib/ui-idle-service/idle.service.ts","../../../projects/ccc-lib/ui-idle-service/cccteam-ccc-lib-ui-idle-service.ts"],"sourcesContent":["import { computed, inject, Injectable, OnDestroy, signal, WritableSignal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport {\n AlertLevel,\n IDLE_KEEPALIVE_DURATION,\n IDLE_SESSION_DURATION,\n IDLE_WARNING_DURATION,\n} from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';\nimport { interval, Subscription } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class IdleService implements OnDestroy {\n private auth = inject(AuthService);\n private core = inject(UiCoreService);\n private router = inject(Router);\n private notifications = inject(NotificationService);\n\n private readonly sessionDuration = inject(IDLE_SESSION_DURATION);\n private readonly warningDuration = inject(IDLE_WARNING_DURATION);\n private readonly keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);\n private readonly idleCheckFrequency = 1000;\n private readonly warningThreshold = this.sessionDuration - this.warningDuration;\n\n public readonly isActive = signal(false);\n private lastActivityTimestamp: WritableSignal<number> = signal(0);\n private tick = signal(Date.now());\n\n public readonly secondsIdle = computed(() => {\n if (!this.isActive() || this.lastActivityTimestamp() === 0) {\n return 0;\n }\n // Depends on tick() to force re-evaluation as time passes\n return Math.floor((this.tick() - this.lastActivityTimestamp()) / 1000);\n });\n\n public readonly isWarning = computed(() => this.secondsIdle() >= this.warningThreshold);\n public readonly countdown = computed(() => {\n if (!this.isWarning()) {\n return 0;\n }\n const remaining = this.sessionDuration - this.secondsIdle();\n return Math.max(0, remaining);\n });\n\n private alertId: number | undefined;\n private mainTickerSubscription: Subscription | undefined;\n\n private readonly activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n\n constructor() {\n interval(this.keepAliveDuration * 1000)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.checkSession());\n }\n\n ngOnDestroy(): void {\n this.stop();\n }\n\n /**\n * Starts the idle monitoring service.\n */\n start(): void {\n if (this.isActive()) {\n return;\n }\n this.isActive.set(true);\n this.lastActivityTimestamp.set(Date.now());\n this.addActivityListeners();\n this.startMainTicker();\n }\n\n /**\n * Stops the idle monitoring service and cleans up timers and alerts.\n */\n stop(): void {\n this.isActive.set(false);\n this.mainTickerSubscription?.unsubscribe();\n this.removeActivityListeners();\n this.dismissWarningAlert();\n }\n\n /**\n * Logs out the user due to inactivity and stops the service.\n */\n logoutAndStop(): void {\n this.stop();\n\n this.router.navigate([this.auth.loginRoute()]);\n this.core.publishError({\n message: 'You have been logged out due to inactivity.',\n level: AlertLevel.INFO,\n link: '',\n });\n }\n\n private startMainTicker(): void {\n this.mainTickerSubscription = interval(this.idleCheckFrequency).subscribe(() => {\n this.tick.set(Date.now());\n\n if (this.secondsIdle() >= this.sessionDuration) {\n this.logoutAndStop();\n return;\n }\n\n if (this.isWarning()) {\n this.showOrUpdateWarningAlert(this.countdown());\n } else {\n this.dismissWarningAlert();\n }\n });\n }\n\n private checkSession(): void {\n if (this.auth.authenticated()) {\n this.auth.checkUserSession().subscribe({\n next: () => {\n if (!this.auth.authenticated()) {\n this.logoutAndStop();\n }\n },\n });\n }\n }\n\n setLastActivity(): void {\n this.lastActivityTimestamp.set(Date.now());\n }\n boundActivity = this.setLastActivity.bind(this);\n\n private addActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.addEventListener(event, this.boundActivity, true);\n });\n }\n\n private removeActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.removeEventListener(event, this.boundActivity, true);\n });\n }\n\n private showOrUpdateWarningAlert(countdown: number): void {\n const message = `You will be logged out in ${countdown} seconds due to inactivity.`;\n if (this.alertId !== undefined) {\n this.notifications.updateNotification({ id: this.alertId, level: AlertLevel.INFO, link: '', message });\n } else {\n this.alertId = this.notifications.addGlobalNotification({\n message,\n level: AlertLevel.INFO,\n link: '',\n });\n }\n }\n\n private dismissWarningAlert(): void {\n if (this.alertId !== undefined) {\n this.notifications.dismissGlobalNotificationById(this.alertId);\n this.alertId = undefined;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cccteam-ccc-lib-ui-idle-service.mjs","sources":["../../../projects/ccc-lib/ui-idle-service/idle.service.ts","../../../projects/ccc-lib/ui-idle-service/cccteam-ccc-lib-ui-idle-service.ts"],"sourcesContent":["import { computed, inject, Injectable, OnDestroy, signal, WritableSignal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport {\n AlertLevel,\n FRONTEND_LOGIN_PATH,\n IDLE_KEEPALIVE_DURATION,\n IDLE_SESSION_DURATION,\n IDLE_WARNING_DURATION,\n} from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { NotificationService } from '@cccteam/ccc-lib/ui-notification-service';\nimport { interval, Subscription } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class IdleService implements OnDestroy {\n private auth = inject(AuthService);\n private core = inject(UiCoreService);\n private router = inject(Router);\n private notifications = inject(NotificationService);\n private readonly loginPath = inject(FRONTEND_LOGIN_PATH);\n\n private readonly sessionDuration = inject(IDLE_SESSION_DURATION);\n private readonly warningDuration = inject(IDLE_WARNING_DURATION);\n private readonly keepAliveDuration = inject(IDLE_KEEPALIVE_DURATION);\n private readonly idleCheckFrequency = 1000;\n private readonly warningThreshold = this.sessionDuration - this.warningDuration;\n\n public readonly isActive = signal(false);\n private lastActivityTimestamp: WritableSignal<number> = signal(0);\n private tick = signal(Date.now());\n\n public readonly secondsIdle = computed(() => {\n if (!this.isActive() || this.lastActivityTimestamp() === 0) {\n return 0;\n }\n // Depends on tick() to force re-evaluation as time passes\n return Math.floor((this.tick() - this.lastActivityTimestamp()) / 1000);\n });\n\n public readonly isWarning = computed(() => this.secondsIdle() >= this.warningThreshold);\n public readonly countdown = computed(() => {\n if (!this.isWarning()) {\n return 0;\n }\n const remaining = this.sessionDuration - this.secondsIdle();\n return Math.max(0, remaining);\n });\n\n private alertId: number | undefined;\n private mainTickerSubscription: Subscription | undefined;\n\n private readonly activityEvents = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart', 'click'];\n\n constructor() {\n interval(this.keepAliveDuration * 1000)\n .pipe(takeUntilDestroyed())\n .subscribe(() => this.checkSession());\n }\n\n ngOnDestroy(): void {\n this.stop();\n }\n\n /**\n * Starts the idle monitoring service.\n */\n start(): void {\n if (this.isActive()) {\n return;\n }\n this.isActive.set(true);\n this.lastActivityTimestamp.set(Date.now());\n this.addActivityListeners();\n this.startMainTicker();\n }\n\n /**\n * Stops the idle monitoring service and cleans up timers and alerts.\n */\n stop(): void {\n this.isActive.set(false);\n this.mainTickerSubscription?.unsubscribe();\n this.removeActivityListeners();\n this.dismissWarningAlert();\n }\n\n /**\n * Logs out the user due to inactivity and stops the service.\n */\n logoutAndStop(): void {\n this.stop();\n\n this.router.navigate([this.loginPath]);\n this.core.publishError({\n message: 'You have been logged out due to inactivity.',\n level: AlertLevel.INFO,\n link: '',\n });\n }\n\n private startMainTicker(): void {\n this.mainTickerSubscription = interval(this.idleCheckFrequency).subscribe(() => {\n this.tick.set(Date.now());\n\n if (this.secondsIdle() >= this.sessionDuration) {\n this.logoutAndStop();\n return;\n }\n\n if (this.isWarning()) {\n this.showOrUpdateWarningAlert(this.countdown());\n } else {\n this.dismissWarningAlert();\n }\n });\n }\n\n private checkSession(): void {\n if (this.auth.authenticated()) {\n this.auth.checkUserSession().subscribe({\n next: () => {\n if (!this.auth.authenticated()) {\n this.logoutAndStop();\n }\n },\n });\n }\n }\n\n setLastActivity(): void {\n this.lastActivityTimestamp.set(Date.now());\n }\n boundActivity = this.setLastActivity.bind(this);\n\n private addActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.addEventListener(event, this.boundActivity, true);\n });\n }\n\n private removeActivityListeners(): void {\n this.activityEvents.forEach((event) => {\n document.removeEventListener(event, this.boundActivity, true);\n });\n }\n\n private showOrUpdateWarningAlert(countdown: number): void {\n const message = `You will be logged out in ${countdown} seconds due to inactivity.`;\n if (this.alertId !== undefined) {\n this.notifications.updateNotification({ id: this.alertId, level: AlertLevel.INFO, link: '', message });\n } else {\n this.alertId = this.notifications.addGlobalNotification({\n message,\n level: AlertLevel.INFO,\n link: '',\n });\n }\n }\n\n private dismissWarningAlert(): void {\n if (this.alertId !== undefined) {\n this.notifications.dismissGlobalNotificationById(this.alertId);\n this.alertId = undefined;\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { inject, NgZone, Injectable } from '@angular/core';
3
3
  import { Router } from '@angular/router';
4
4
  import { AuthService } from '@cccteam/ccc-lib/auth-service';
5
- import { BASE_URL, AlertLevel } from '@cccteam/ccc-lib/types';
5
+ import { BASE_URL, FRONTEND_LOGIN_PATH, AlertLevel } from '@cccteam/ccc-lib/types';
6
6
  import { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';
7
7
  import { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';
8
8
  import { catchError, throwError, finalize } from 'rxjs';
@@ -13,13 +13,14 @@ class ApiInterceptor {
13
13
  router = inject(Router);
14
14
  ngZone = inject(NgZone);
15
15
  baseUrl = inject(BASE_URL);
16
+ loginPath = inject(FRONTEND_LOGIN_PATH);
16
17
  intercept(request, next) {
17
18
  this.ui.beginActivity(request.method + ' ' + request.url);
18
19
  return next.handle(request).pipe(catchError((error) => {
19
20
  if (error.status === 401) {
20
21
  this.ngZone.run(() => {
21
22
  this.auth.redirectUrl.set(this.baseUrl + this.router.url);
22
- this.router.navigate([this.auth.loginRoute()]);
23
+ this.router.navigate([this.loginPath]);
23
24
  });
24
25
  }
25
26
  if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {
@@ -1 +1 @@
1
- {"version":3,"file":"cccteam-ccc-lib-ui-interceptor.mjs","sources":["../../../projects/ccc-lib/ui-interceptor/api.interceptor.ts","../../../projects/ccc-lib/ui-interceptor/cccteam-ccc-lib-ui-interceptor.ts"],"sourcesContent":["import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { inject, Injectable, NgZone } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { AlertLevel, BASE_URL } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';\nimport { catchError, finalize, Observable, throwError } from 'rxjs';\n\n@Injectable()\nexport class ApiInterceptor implements HttpInterceptor {\n private ui = inject(UiCoreService);\n private auth = inject(AuthService);\n private router = inject(Router);\n private ngZone = inject(NgZone);\n private baseUrl = inject(BASE_URL);\n\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n this.ui.beginActivity(request.method + ' ' + request.url);\n\n return next.handle(request).pipe(\n catchError((error: HttpErrorResponse): Observable<HttpEvent<unknown>> => {\n if (error.status === 401) {\n this.ngZone.run(() => {\n this.auth.redirectUrl.set(this.baseUrl + this.router.url);\n this.router.navigate([this.auth.loginRoute()]);\n });\n }\n if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {\n const message = error.error?.message ?? error.message ?? error.error;\n this.ui.publishError({\n message: message,\n level: AlertLevel.ERROR,\n link: '',\n });\n }\n\n return throwError(() => error);\n }),\n finalize(() => {\n this.ui.endActivity(request.method + ' ' + request.url);\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAUa,cAAc,CAAA;AACjB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAC1B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAElC,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;AACxD,QAAA,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;AAEzD,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAC9B,UAAU,CAAC,CAAC,KAAwB,KAAoC;AACtE,YAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE;AACxB,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAK;AACnB,oBAAA,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AACzD,oBAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;AAChD,gBAAA,CAAC,CAAC;YACJ;AACA,YAAA,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,mBAAmB,EAAE;AACzE,gBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;AACpE,gBAAA,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;AACnB,oBAAA,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,UAAU,CAAC,KAAK;AACvB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC;YACJ;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,QAAA,CAAC,CAAC,EACF,QAAQ,CAAC,MAAK;AACZ,YAAA,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACzD,CAAC,CAAC,CACH;IACH;uGAjCW,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAd,cAAc,EAAA,CAAA;;2FAAd,cAAc,EAAA,UAAA,EAAA,CAAA;kBAD1B;;;ACTD;;AAEG;;;;"}
1
+ {"version":3,"file":"cccteam-ccc-lib-ui-interceptor.mjs","sources":["../../../projects/ccc-lib/ui-interceptor/api.interceptor.ts","../../../projects/ccc-lib/ui-interceptor/cccteam-ccc-lib-ui-interceptor.ts"],"sourcesContent":["import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';\nimport { inject, Injectable, NgZone } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { AuthService } from '@cccteam/ccc-lib/auth-service';\nimport { AlertLevel, BASE_URL, FRONTEND_LOGIN_PATH } from '@cccteam/ccc-lib/types';\nimport { UiCoreService } from '@cccteam/ccc-lib/ui-core-service';\nimport { CUSTOM_HTTP_REQUEST_OPTIONS } from '@cccteam/ccc-lib/util-request-options';\nimport { catchError, finalize, Observable, throwError } from 'rxjs';\n\n@Injectable()\nexport class ApiInterceptor implements HttpInterceptor {\n private ui = inject(UiCoreService);\n private auth = inject(AuthService);\n private router = inject(Router);\n private ngZone = inject(NgZone);\n private baseUrl = inject(BASE_URL);\n private loginPath = inject(FRONTEND_LOGIN_PATH);\n\n intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {\n this.ui.beginActivity(request.method + ' ' + request.url);\n\n return next.handle(request).pipe(\n catchError((error: HttpErrorResponse): Observable<HttpEvent<unknown>> => {\n if (error.status === 401) {\n this.ngZone.run(() => {\n this.auth.redirectUrl.set(this.baseUrl + this.router.url);\n this.router.navigate([this.loginPath]);\n });\n }\n if (!request.context.get(CUSTOM_HTTP_REQUEST_OPTIONS).suppressGlobalError) {\n const message = error.error?.message ?? error.message ?? error.error;\n this.ui.publishError({\n message: message,\n level: AlertLevel.ERROR,\n link: '',\n });\n }\n\n return throwError(() => error);\n }),\n finalize(() => {\n this.ui.endActivity(request.method + ' ' + request.url);\n }),\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;MAUa,cAAc,CAAA;AACjB,IAAA,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;AAC1B,IAAA,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;AAC1B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC1B,IAAA,SAAS,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAE/C,SAAS,CAAC,OAA6B,EAAE,IAAiB,EAAA;AACxD,QAAA,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;AAEzD,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAC9B,UAAU,CAAC,CAAC,KAAwB,KAAoC;AACtE,YAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE;AACxB,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAK;AACnB,oBAAA,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;oBACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACxC,gBAAA,CAAC,CAAC;YACJ;AACA,YAAA,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,mBAAmB,EAAE;AACzE,gBAAA,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK;AACpE,gBAAA,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC;AACnB,oBAAA,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,UAAU,CAAC,KAAK;AACvB,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC;YACJ;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;AAChC,QAAA,CAAC,CAAC,EACF,QAAQ,CAAC,MAAK;AACZ,YAAA,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACzD,CAAC,CAAC,CACH;IACH;uGAlCW,cAAc,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;2GAAd,cAAc,EAAA,CAAA;;2FAAd,cAAc,EAAA,UAAA,EAAA,CAAA;kBAD1B;;;ACTD;;AAEG;;;;"}
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@cccteam/ccc-lib",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git://github.com/cccteam/ccc-lib.git"
7
7
  },
8
8
  "peerDependencies": {
9
9
  "@angular/common": "^21.0.0",
10
- "@angular/core": "^21.0.0"
10
+ "@angular/core": "^21.0.0",
11
+ "@contentful/rich-text-types": "^17.2.5"
11
12
  },
12
13
  "dependencies": {
13
14
  "date-fns": "^4.1.0",
@@ -1,6 +1,22 @@
1
1
  import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
2
2
  import { Observable } from 'rxjs';
3
3
 
4
- declare const AuthenticationGuard: (route: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) => Observable<boolean>;
4
+ /**
5
+ * Route guard that protects routes using OIDC (OpenID Connect) authentication.
6
+ *
7
+ * If the user is not authenticated, they are redirected to the external OIDC
8
+ * login endpoint with the current URL encoded as a return URL parameter.
9
+ *
10
+ */
11
+ declare const OIDCAuthenticationGuard: (_: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) => Observable<boolean>;
12
+ /**
13
+ * Route guard that protects routes using internal login-based authentication.
14
+ *
15
+ * If the user is not authenticated, they are redirected to the application's
16
+ * internal FRONTEND_LOGIN_PATH route. The attempted URL is stored in the AuthService so the
17
+ * user can be redirected back after successful login.
18
+ *
19
+ */
20
+ declare const LoginAuthenticationGuard: (_: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) => Observable<boolean>;
5
21
 
6
- export { AuthenticationGuard };
22
+ export { LoginAuthenticationGuard, OIDCAuthenticationGuard };
@@ -1,6 +1,7 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { Type, InjectionToken } from '@angular/core';
3
3
  import { TooltipPosition } from '@angular/material/tooltip';
4
+ import { Document } from '@contentful/rich-text-types';
4
5
  import { ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
5
6
 
6
7
  type Brand<K, T> = K & {
@@ -20,7 +21,7 @@ interface PermissionScope {
20
21
  declare const ReadPermission: Permission;
21
22
  declare const UpdatePermission: Permission;
22
23
 
23
- type ValidDisplayTypes = 'boolean' | 'nullboolean' | 'number' | 'string' | 'date' | 'enumerated' | 'link' | 'uuid' | 'civildate' | 'string[]' | 'customtypes.document';
24
+ type ValidDisplayTypes = 'boolean' | 'nullboolean' | 'number' | 'string' | 'date' | 'enumerated' | 'link' | 'uuid' | 'civildate' | 'string[]' | 'customtypes.contentfuldocument';
24
25
  type ValidRPCTypes = ValidDisplayTypes | `${Exclude<ValidDisplayTypes, 'string[]'>}[]`;
25
26
  interface RPCFieldMeta {
26
27
  fieldName: string;
@@ -57,9 +58,7 @@ interface ResourceMeta {
57
58
  }
58
59
  type Meta = MethodMeta | ResourceMeta;
59
60
  declare namespace CustomTypes {
60
- interface Document {
61
- placeholder: string;
62
- }
61
+ type ContentfulDocument = Document;
63
62
  }
64
63
 
65
64
  declare const defaultEmptyFieldValue = "-";
@@ -6,6 +6,7 @@ declare class IdleService implements OnDestroy {
6
6
  private core;
7
7
  private router;
8
8
  private notifications;
9
+ private readonly loginPath;
9
10
  private readonly sessionDuration;
10
11
  private readonly warningDuration;
11
12
  private readonly keepAliveDuration;
@@ -8,6 +8,7 @@ declare class ApiInterceptor implements HttpInterceptor {
8
8
  private router;
9
9
  private ngZone;
10
10
  private baseUrl;
11
+ private loginPath;
11
12
  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
12
13
  static ɵfac: i0.ɵɵFactoryDeclaration<ApiInterceptor, never>;
13
14
  static ɵprov: i0.ɵɵInjectableDeclaration<ApiInterceptor>;