@verisoft/security-core 18.6.0 → 18.7.0

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.
Files changed (85) hide show
  1. package/.eslintrc.json +48 -0
  2. package/README.md +52 -3
  3. package/jest.config.ts +21 -0
  4. package/ng-package.json +7 -0
  5. package/package.json +11 -27
  6. package/project.json +36 -0
  7. package/src/index.ts +1 -0
  8. package/src/lib/directives/has-permission.directive.ts +54 -0
  9. package/src/lib/directives/has-role.directive.ts +54 -0
  10. package/{lib/directives/index.d.ts → src/lib/directives/index.ts} +2 -2
  11. package/src/lib/guards/auth.guard.ts +55 -0
  12. package/{lib/guards/index.d.ts → src/lib/guards/index.ts} +1 -1
  13. package/{lib/index.d.ts → src/lib/index.ts} +6 -6
  14. package/{lib/models/authenticated-user.model.d.ts → src/lib/models/authenticated-user.model.ts} +8 -8
  15. package/{lib/models/config.model.d.ts → src/lib/models/config.model.ts} +9 -8
  16. package/src/lib/models/functions.spec.ts +159 -0
  17. package/src/lib/models/functions.ts +103 -0
  18. package/{lib/models/index.d.ts → src/lib/models/index.ts} +3 -3
  19. package/src/lib/provider.ts +58 -0
  20. package/src/lib/services/auth-context.service.ts +38 -0
  21. package/{lib/services/index.d.ts → src/lib/services/index.ts} +7 -7
  22. package/src/lib/services/local-storage-token-provider.ts +23 -0
  23. package/src/lib/services/local-token-provider.ts +15 -0
  24. package/src/lib/services/login.service.ts +23 -0
  25. package/src/lib/services/logout.service.ts +15 -0
  26. package/src/lib/services/security-initializer.ts +26 -0
  27. package/src/lib/services/session-token-provider.ts +15 -0
  28. package/{lib/services/token-provider.d.ts → src/lib/services/token-provider.ts} +5 -4
  29. package/src/lib/state/actions.ts +7 -0
  30. package/src/lib/state/feature.ts +10 -0
  31. package/{lib/state/index.d.ts → src/lib/state/index.ts} +4 -4
  32. package/src/lib/state/reducers.ts +11 -0
  33. package/src/lib/state/selectors.ts +9 -0
  34. package/src/lib/state/state.ts +9 -0
  35. package/src/test-setup.ts +8 -0
  36. package/tsconfig.json +28 -0
  37. package/tsconfig.lib.json +17 -0
  38. package/tsconfig.lib.prod.json +9 -0
  39. package/tsconfig.spec.json +16 -0
  40. package/esm2022/index.mjs +0 -2
  41. package/esm2022/lib/directives/has-permission.directive.mjs +0 -55
  42. package/esm2022/lib/directives/has-role.directive.mjs +0 -55
  43. package/esm2022/lib/directives/index.mjs +0 -3
  44. package/esm2022/lib/guards/auth.guard.mjs +0 -40
  45. package/esm2022/lib/guards/index.mjs +0 -2
  46. package/esm2022/lib/index.mjs +0 -7
  47. package/esm2022/lib/models/authenticated-user.model.mjs +0 -2
  48. package/esm2022/lib/models/config.model.mjs +0 -2
  49. package/esm2022/lib/models/functions.mjs +0 -70
  50. package/esm2022/lib/models/index.mjs +0 -4
  51. package/esm2022/lib/provider.mjs +0 -47
  52. package/esm2022/lib/services/auth-context.service.mjs +0 -36
  53. package/esm2022/lib/services/index.mjs +0 -8
  54. package/esm2022/lib/services/local-storage-token-provider.mjs +0 -23
  55. package/esm2022/lib/services/login.service.mjs +0 -27
  56. package/esm2022/lib/services/logout.service.mjs +0 -18
  57. package/esm2022/lib/services/security-initializer.mjs +0 -14
  58. package/esm2022/lib/services/session-token-provider.mjs +0 -17
  59. package/esm2022/lib/services/token-provider.mjs +0 -2
  60. package/esm2022/lib/state/actions.mjs +0 -3
  61. package/esm2022/lib/state/feature.mjs +0 -8
  62. package/esm2022/lib/state/index.mjs +0 -5
  63. package/esm2022/lib/state/reducers.mjs +0 -8
  64. package/esm2022/lib/state/selectors.mjs +0 -5
  65. package/esm2022/lib/state/state.mjs +0 -4
  66. package/esm2022/verisoft-security-core.mjs +0 -5
  67. package/fesm2022/verisoft-security-core.mjs +0 -382
  68. package/fesm2022/verisoft-security-core.mjs.map +0 -1
  69. package/index.d.ts +0 -1
  70. package/lib/directives/has-permission.directive.d.ts +0 -17
  71. package/lib/directives/has-role.directive.d.ts +0 -17
  72. package/lib/guards/auth.guard.d.ts +0 -13
  73. package/lib/models/functions.d.ts +0 -5
  74. package/lib/provider.d.ts +0 -14
  75. package/lib/services/auth-context.service.d.ts +0 -15
  76. package/lib/services/local-storage-token-provider.d.ts +0 -11
  77. package/lib/services/login.service.d.ts +0 -10
  78. package/lib/services/logout.service.d.ts +0 -8
  79. package/lib/services/security-initializer.d.ts +0 -5
  80. package/lib/services/session-token-provider.d.ts +0 -9
  81. package/lib/state/actions.d.ts +0 -6
  82. package/lib/state/feature.d.ts +0 -7
  83. package/lib/state/reducers.d.ts +0 -1
  84. package/lib/state/selectors.d.ts +0 -2
  85. package/lib/state/state.d.ts +0 -5
@@ -0,0 +1,103 @@
1
+ import { AuthenticatedUser } from './authenticated-user.model';
2
+
3
+ export function hasRequiredPermission(
4
+ user: AuthenticatedUser | undefined,
5
+ permission: string | string[]
6
+ ): boolean {
7
+ return hasItems(user?.permissions, permission);
8
+ }
9
+
10
+ export function hasRequiredRole(
11
+ user: AuthenticatedUser | undefined,
12
+ role: string | string[]
13
+ ): boolean {
14
+ return hasItems(user?.roles, role);
15
+ }
16
+
17
+ function hasItems(
18
+ userItems: string[] | undefined,
19
+ neededItems: string | string[]
20
+ ): boolean {
21
+ if (!neededItems || !neededItems.length) {
22
+ return true;
23
+ }
24
+
25
+ if (!userItems || !userItems.length) {
26
+ return false;
27
+ }
28
+
29
+ const userItemsSet = new Set(userItems);
30
+ if (Array.isArray(neededItems)) {
31
+ return neededItems.some((item) => hasItems(userItems, item));
32
+ }
33
+
34
+ if (neededItems.includes(',')) {
35
+ const splitItems = neededItems.split(',').map((i) => i.trim());
36
+ return splitItems.every((i) => userItemsSet.has(i));
37
+ }
38
+
39
+ return userItemsSet.has(neededItems);
40
+ }
41
+
42
+ export function convertJWTToUser(
43
+ base64Token?: string
44
+ ): AuthenticatedUser | undefined {
45
+ if (!base64Token) {
46
+ return undefined;
47
+ }
48
+
49
+ try {
50
+ const parts = base64Token.split('.');
51
+ if (parts.length < 2) {
52
+ return undefined;
53
+ }
54
+ const payload = decodeJwtPayload(parts[1]);
55
+
56
+ const userName = payload['unique_name'] ?? payload['nameid'];
57
+ if (!userName) {
58
+ return undefined;
59
+ }
60
+
61
+ const user: AuthenticatedUser = {
62
+ userName,
63
+ userId: payload['nameid'],
64
+ email: payload['email'],
65
+ displayName: payload['name'],
66
+ roles: convertToArray(payload, 'role'),
67
+ permissions: convertToArray(payload, 'permission'),
68
+ };
69
+
70
+ return user;
71
+ } catch (error) {
72
+ return undefined;
73
+ }
74
+ }
75
+
76
+ export function decodeJwtPayload(jwt: string): any {
77
+ const base64 = jwt.replace(/-/g, '+').replace(/_/g, '/');
78
+
79
+ const jsonPayload = decodeURIComponent(
80
+ atob(base64)
81
+ .split('')
82
+ .map(c => '%' + c.charCodeAt(0).toString(16).padStart(2, '0'))
83
+ .join('')
84
+ );
85
+
86
+ return JSON.parse(jsonPayload);
87
+ }
88
+
89
+ function convertToArray(
90
+ item: { [key: string]: string | string[] },
91
+ propertyName: string
92
+ ): string[] | undefined {
93
+ const rawValue = item[propertyName];
94
+ if (!rawValue) {
95
+ return undefined;
96
+ }
97
+
98
+ if (Array.isArray(rawValue)) {
99
+ return rawValue;
100
+ }
101
+
102
+ return [rawValue];
103
+ }
@@ -1,3 +1,3 @@
1
- export * from './authenticated-user.model';
2
- export * from './functions';
3
- export * from './config.model';
1
+ export * from './authenticated-user.model';
2
+ export * from './functions';
3
+ export * from './config.model';
@@ -0,0 +1,58 @@
1
+ import {
2
+ APP_INITIALIZER,
3
+ InjectionToken,
4
+ ModuleWithProviders,
5
+ NgModule,
6
+ Provider,
7
+ } from '@angular/core';
8
+ import { Router } from '@angular/router';
9
+ import { StoreModule } from '@ngrx/store';
10
+ import { AuthGuard } from './guards';
11
+ import { SecurityConfig } from './models';
12
+ import {
13
+ AuthContextService,
14
+ LocalStorageTokenProvider,
15
+ securityInitializerFactory,
16
+ } from './services';
17
+ import { SecurityFeature } from './state/feature';
18
+
19
+ export function provideSecurity(
20
+ config: Partial<SecurityConfig> | undefined = undefined
21
+ ): Provider[] {
22
+ const securityConfig: SecurityConfig = {
23
+ tokenStorageKey: 'APP_TOKEN',
24
+ notAuthorizedPage: '/not-authorized',
25
+ ...(config ?? {}),
26
+ };
27
+ return [
28
+ AuthGuard,
29
+ SECURITY_INITIALIZER_PROVIDER,
30
+ { provide: SECURITY_CONTEXT_TOKEN_PROVIDER, useClass: LocalStorageTokenProvider },
31
+ { provide: SECURITY_CONFIG, useValue: securityConfig },
32
+ ];
33
+ }
34
+
35
+ @NgModule({
36
+ imports: [StoreModule.forFeature(SecurityFeature)],
37
+ })
38
+ export class SecurityModule {
39
+ static forRoot(
40
+ config?: Partial<SecurityConfig>
41
+ ): ModuleWithProviders<SecurityModule> {
42
+ return {
43
+ ngModule: SecurityModule,
44
+ providers: [...provideSecurity(config)],
45
+ };
46
+ }
47
+ }
48
+
49
+ export const SECURITY_CONTEXT_TOKEN_PROVIDER = new InjectionToken('SECURITY_CONTEXT_TOKEN_PROVIDER');
50
+
51
+ export const SECURITY_CONFIG = new InjectionToken('SECURITY_CONFIG');
52
+
53
+ export const SECURITY_INITIALIZER_PROVIDER: Provider = {
54
+ provide: APP_INITIALIZER,
55
+ useFactory: securityInitializerFactory,
56
+ deps: [SECURITY_CONTEXT_TOKEN_PROVIDER, AuthContextService, SECURITY_CONFIG, Router],
57
+ multi: true,
58
+ };
@@ -0,0 +1,38 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Store } from '@ngrx/store';
3
+ import { map, Observable } from 'rxjs';
4
+ import { AuthenticatedUser } from '../models';
5
+ import { hasRequiredPermission, hasRequiredRole } from '../models/functions';
6
+ import { setUser } from '../state/actions';
7
+ import { selectIsAuthenticated, selectUser } from '../state/selectors';
8
+
9
+ @Injectable({
10
+ providedIn: 'root',
11
+ })
12
+ export class AuthContextService {
13
+ user$: Observable<AuthenticatedUser | undefined>;
14
+ isAuthenticated$: Observable<boolean>;
15
+
16
+ constructor(private store: Store) {
17
+ this.user$ = this.store.select(selectUser);
18
+ this.isAuthenticated$ = this.store.select(selectIsAuthenticated);
19
+ }
20
+
21
+ setUser(user: AuthenticatedUser | undefined): void {
22
+ this.store.dispatch(setUser({ user }));
23
+ }
24
+
25
+ hasRequiredPermission(
26
+ requiredPermissions: string | string[]
27
+ ): Observable<boolean> {
28
+ return this.user$.pipe(
29
+ map((user) => hasRequiredPermission(user, requiredPermissions))
30
+ );
31
+ }
32
+
33
+ hasRequiredRole(requiredPermissions: string | string[]): Observable<boolean> {
34
+ return this.user$.pipe(
35
+ map((user) => hasRequiredRole(user, requiredPermissions))
36
+ );
37
+ }
38
+ }
@@ -1,7 +1,7 @@
1
- export * from './auth-context.service';
2
- export * from './local-storage-token-provider';
3
- export * from './security-initializer';
4
- export * from './session-token-provider';
5
- export * from './token-provider';
6
- export * from './login.service';
7
- export * from './logout.service';
1
+ export * from './auth-context.service';
2
+ export * from './local-storage-token-provider';
3
+ export * from './security-initializer';
4
+ export * from './session-token-provider';
5
+ export * from './token-provider';
6
+ export * from './login.service';
7
+ export * from './logout.service';
@@ -0,0 +1,23 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { Observable, of } from 'rxjs';
3
+ import { SecurityConfig } from '../models';
4
+ import { SECURITY_CONFIG } from '../provider';
5
+ import { TokenProvider } from './token-provider';
6
+
7
+ @Injectable()
8
+ export class LocalStorageTokenProvider implements TokenProvider {
9
+ private config = inject<SecurityConfig>(SECURITY_CONFIG);
10
+
11
+ getToken(): Observable<string | undefined> {
12
+ const token = localStorage.getItem(this.config.tokenStorageKey);
13
+ return of(token ?? undefined);
14
+ }
15
+
16
+ setToken(token: string): void {
17
+ localStorage.setItem(this.config.tokenStorageKey, token);
18
+ }
19
+
20
+ removeToken(): void {
21
+ localStorage.clear();
22
+ }
23
+ }
@@ -0,0 +1,15 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { Observable, of } from 'rxjs';
3
+ import { SecurityConfig } from '../models';
4
+ import { SECURITY_CONFIG } from '../provider';
5
+ import { TokenProvider } from './token-provider';
6
+
7
+ @Injectable()
8
+ export class LocalStorageTokenProvider implements TokenProvider {
9
+ private config = inject<SecurityConfig>(SECURITY_CONFIG);
10
+
11
+ getToken(): Observable<string | undefined> {
12
+ const token = localStorage.getItem(this.config.tokenStorageKey);
13
+ return of(token ?? undefined);
14
+ }
15
+ }
@@ -0,0 +1,23 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { Router } from '@angular/router';
3
+ import { convertJWTToUser, SecurityConfig } from '../models';
4
+ import { SECURITY_CONFIG, SECURITY_CONTEXT_TOKEN_PROVIDER } from '../provider';
5
+ import { AuthContextService } from './auth-context.service';
6
+ import { LocalStorageTokenProvider } from './local-storage-token-provider';
7
+
8
+ @Injectable()
9
+ export class LoginService {
10
+ private config = inject<SecurityConfig>(SECURITY_CONFIG);
11
+ private tokenProvider = inject<LocalStorageTokenProvider>(SECURITY_CONTEXT_TOKEN_PROVIDER);
12
+ private authService = inject(AuthContextService);
13
+ private router = inject(Router);
14
+
15
+ login(token?: string): void {
16
+ if (token) {
17
+ this.tokenProvider.setToken(token);
18
+ this.authService.setUser(convertJWTToUser(token));
19
+ } else {
20
+ this.router.navigate([this.config.loginPage]);
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,15 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { SECURITY_CONTEXT_TOKEN_PROVIDER } from '../provider';
3
+ import { AuthContextService } from './auth-context.service';
4
+ import { LocalStorageTokenProvider } from './local-storage-token-provider';
5
+
6
+ @Injectable()
7
+ export class LogoutService {
8
+ private readonly tokenProvider = inject<LocalStorageTokenProvider>(SECURITY_CONTEXT_TOKEN_PROVIDER);
9
+ private readonly authService = inject(AuthContextService);
10
+
11
+ logout(): void {
12
+ this.tokenProvider.removeToken();
13
+ this.authService.setUser(undefined);
14
+ }
15
+ }
@@ -0,0 +1,26 @@
1
+ import { Router } from '@angular/router';
2
+ import { firstValueFrom, from, of, switchMap } from 'rxjs';
3
+ import { convertJWTToUser, SecurityConfig } from '../models';
4
+ import { AuthContextService } from './auth-context.service';
5
+ import { TokenProvider } from './token-provider';
6
+
7
+ export function securityInitializerFactory(
8
+ tokenProvider: TokenProvider,
9
+ authService: AuthContextService,
10
+ config: SecurityConfig,
11
+ router: Router
12
+ ): () => Promise<unknown> {
13
+ const initializationFn = tokenProvider.getToken().pipe(
14
+ switchMap((token) => {
15
+ const user = convertJWTToUser(token);
16
+ if (config.loginPage && !user) {
17
+ return from(router.navigate([config.loginPage]));
18
+ }
19
+
20
+ authService.setUser(user);
21
+ return of({});
22
+ })
23
+ );
24
+
25
+ return () => firstValueFrom(initializationFn)
26
+ }
@@ -0,0 +1,15 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { Observable, of } from 'rxjs';
3
+ import { SecurityConfig } from '../models';
4
+ import { SECURITY_CONFIG } from '../provider';
5
+ import { TokenProvider } from './token-provider';
6
+
7
+ @Injectable()
8
+ export class SessionStorageTokenProvider implements TokenProvider {
9
+ private config = inject<SecurityConfig>(SECURITY_CONFIG);
10
+
11
+ getToken(): Observable<string | undefined> {
12
+ const token = sessionStorage.getItem(this.config.tokenStorageKey);
13
+ return of(token ?? undefined);
14
+ }
15
+ }
@@ -1,4 +1,5 @@
1
- import { Observable } from "rxjs";
2
- export interface TokenProvider {
3
- getToken(): Observable<string | undefined>;
4
- }
1
+ import { Observable } from "rxjs";
2
+
3
+ export interface TokenProvider {
4
+ getToken(): Observable<string | undefined>;
5
+ }
@@ -0,0 +1,7 @@
1
+ import { createAction, props } from '@ngrx/store';
2
+ import { AuthenticatedUser } from '../models';
3
+
4
+ export const setUser = createAction(
5
+ '[Auth] Set User',
6
+ props<{ user: AuthenticatedUser | undefined }>()
7
+ );
@@ -0,0 +1,10 @@
1
+ import { createFeature } from "@ngrx/store"
2
+ import { authReducer } from "./reducers"
3
+
4
+ export const SECURITY_FEATURE_NAME = 'SECURITY';
5
+
6
+ export const SecurityFeature = createFeature({
7
+ name: SECURITY_FEATURE_NAME,
8
+ reducer: authReducer
9
+ });
10
+
@@ -1,4 +1,4 @@
1
- export * from './actions';
2
- export * from './state';
3
- export * from './reducers';
4
- export * from './selectors';
1
+ export * from './actions';
2
+ export * from './state';
3
+ export * from './reducers';
4
+ export * from './selectors';
@@ -0,0 +1,11 @@
1
+ import { createReducer, on } from '@ngrx/store';
2
+ import { setUser } from './actions';
3
+ import { initialState } from './state';
4
+
5
+ export const authReducer = createReducer(
6
+ initialState,
7
+ on(setUser, (state, action) => ({
8
+ ...state,
9
+ user: action.user
10
+ }))
11
+ );
@@ -0,0 +1,9 @@
1
+ import { createSelector } from '@ngrx/store';
2
+ import { SecurityFeature } from './feature';
3
+
4
+ export const selectIsAuthenticated = createSelector(
5
+ SecurityFeature.selectUser,
6
+ (user) => !!user
7
+ );
8
+
9
+ export const selectUser = SecurityFeature.selectUser;
@@ -0,0 +1,9 @@
1
+ import { AuthenticatedUser } from '../models';
2
+
3
+ export interface AuthState {
4
+ user: AuthenticatedUser | undefined;
5
+ }
6
+
7
+ export const initialState: AuthState = {
8
+ user: undefined,
9
+ };
@@ -0,0 +1,8 @@
1
+ // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
2
+ globalThis.ngJest = {
3
+ testEnvironmentOptions: {
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ },
7
+ };
8
+ import 'jest-preset-angular/setup-jest';
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "forceConsistentCasingInFileNames": true,
5
+ "strict": true,
6
+ "noImplicitOverride": true,
7
+ "noPropertyAccessFromIndexSignature": true,
8
+ "noImplicitReturns": true,
9
+ "noFallthroughCasesInSwitch": true
10
+ },
11
+ "files": [],
12
+ "include": [],
13
+ "references": [
14
+ {
15
+ "path": "./tsconfig.lib.json"
16
+ },
17
+ {
18
+ "path": "./tsconfig.spec.json"
19
+ }
20
+ ],
21
+ "extends": "../../../../tsconfig.base.json",
22
+ "angularCompilerOptions": {
23
+ "enableI18nLegacyMessageIdFormat": false,
24
+ "strictInjectionParameters": true,
25
+ "strictInputAccessModifiers": true,
26
+ "strictTemplates": true
27
+ }
28
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../../dist/out-tsc",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "inlineSources": true,
8
+ "types": []
9
+ },
10
+ "exclude": [
11
+ "src/**/*.spec.ts",
12
+ "src/test-setup.ts",
13
+ "jest.config.ts",
14
+ "src/**/*.test.ts"
15
+ ],
16
+ "include": ["src/**/*.ts"]
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "declarationMap": false
5
+ },
6
+ "angularCompilerOptions": {
7
+ "compilationMode": "partial"
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "target": "es2016",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "files": ["src/test-setup.ts"],
10
+ "include": [
11
+ "jest.config.ts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.d.ts"
15
+ ]
16
+ }
package/esm2022/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- export * from './lib';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGlicy9zZWN1cml0eS9jb3JlL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLE9BQU8sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vbGliJzsiXX0=
@@ -1,55 +0,0 @@
1
- import { Directive, Input, TemplateRef, ViewContainerRef, } from '@angular/core';
2
- import { distinctUntilChanged } from 'rxjs';
3
- import { AuthContextService } from '../services';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "../services";
6
- export class HasPermissionDirective {
7
- templateRef;
8
- viewContainer;
9
- authContext;
10
- requiredPermissions = '';
11
- sub;
12
- constructor(templateRef, viewContainer, authContext) {
13
- this.templateRef = templateRef;
14
- this.viewContainer = viewContainer;
15
- this.authContext = authContext;
16
- }
17
- set hasPermission(value) {
18
- this.requiredPermissions = value;
19
- this.updateView();
20
- }
21
- ngOnDestroy() {
22
- this.unregister();
23
- }
24
- unregister() {
25
- this.sub?.unsubscribe();
26
- }
27
- updateView() {
28
- this.unregister();
29
- if (this.requiredPermissions || this.requiredPermissions.length) {
30
- this.sub = this.authContext
31
- .hasRequiredPermission(this.requiredPermissions)
32
- .pipe(distinctUntilChanged())
33
- .subscribe((hasPerm) => {
34
- if (hasPerm) {
35
- this.viewContainer.createEmbeddedView(this.templateRef);
36
- }
37
- else {
38
- this.viewContainer.clear();
39
- }
40
- });
41
- }
42
- }
43
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HasPermissionDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i1.AuthContextService }], target: i0.ɵɵFactoryTarget.Directive });
44
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.8", type: HasPermissionDirective, isStandalone: true, selector: "[hasPermission]", inputs: { hasPermission: "hasPermission" }, ngImport: i0 });
45
- }
46
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HasPermissionDirective, decorators: [{
47
- type: Directive,
48
- args: [{
49
- standalone: true,
50
- selector: '[hasPermission]',
51
- }]
52
- }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: i1.AuthContextService }], propDecorators: { hasPermission: [{
53
- type: Input
54
- }] } });
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFzLXBlcm1pc3Npb24uZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYnMvc2VjdXJpdHkvY29yZS9zcmMvbGliL2RpcmVjdGl2ZXMvaGFzLXBlcm1pc3Npb24uZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsR0FFakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLG9CQUFvQixFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMxRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7OztBQU1qRCxNQUFNLE9BQU8sc0JBQXNCO0lBS3ZCO0lBQ0E7SUFDQTtJQU5GLG1CQUFtQixHQUFzQixFQUFFLENBQUM7SUFDNUMsR0FBRyxDQUFnQjtJQUUzQixZQUNVLFdBQTJCLEVBQzNCLGFBQStCLEVBQy9CLFdBQStCO1FBRi9CLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixrQkFBYSxHQUFiLGFBQWEsQ0FBa0I7UUFDL0IsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO0lBQ3RDLENBQUM7SUFFSixJQUNJLGFBQWEsQ0FBQyxLQUF3QjtRQUN4QyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRU8sVUFBVTtRQUNoQixJQUFJLENBQUMsR0FBRyxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFTyxVQUFVO1FBQ2hCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEUsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsV0FBVztpQkFDeEIscUJBQXFCLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDO2lCQUMvQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztpQkFDNUIsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7Z0JBQ3JCLElBQUksT0FBTyxFQUFFLENBQUM7b0JBQ1osSUFBSSxDQUFDLGFBQWEsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQzFELENBQUM7cUJBQU0sQ0FBQztvQkFDTixJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUM3QixDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDO0lBQ0gsQ0FBQzt1R0F0Q1Usc0JBQXNCOzJGQUF0QixzQkFBc0I7OzJGQUF0QixzQkFBc0I7a0JBSmxDLFNBQVM7bUJBQUM7b0JBQ1QsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFFBQVEsRUFBRSxpQkFBaUI7aUJBQzVCO2dKQVlLLGFBQWE7c0JBRGhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSxcclxuICBJbnB1dCxcclxuICBUZW1wbGF0ZVJlZixcclxuICBWaWV3Q29udGFpbmVyUmVmLFxyXG4gIE9uRGVzdHJveSxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBBdXRoQ29udGV4dFNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcyc7XHJcblxyXG5ARGlyZWN0aXZlKHtcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIHNlbGVjdG9yOiAnW2hhc1Blcm1pc3Npb25dJyxcclxufSlcclxuZXhwb3J0IGNsYXNzIEhhc1Blcm1pc3Npb25EaXJlY3RpdmU8VD4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xyXG4gIHByaXZhdGUgcmVxdWlyZWRQZXJtaXNzaW9uczogc3RyaW5nIHwgc3RyaW5nW10gPSAnJztcclxuICBwcml2YXRlIHN1Yj86IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIHRlbXBsYXRlUmVmOiBUZW1wbGF0ZVJlZjxUPixcclxuICAgIHByaXZhdGUgdmlld0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZixcclxuICAgIHByaXZhdGUgYXV0aENvbnRleHQ6IEF1dGhDb250ZXh0U2VydmljZVxyXG4gICkge31cclxuXHJcbiAgQElucHV0KClcclxuICBzZXQgaGFzUGVybWlzc2lvbih2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIHRoaXMucmVxdWlyZWRQZXJtaXNzaW9ucyA9IHZhbHVlO1xyXG4gICAgdGhpcy51cGRhdGVWaWV3KCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMudW5yZWdpc3RlcigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1bnJlZ2lzdGVyKCkge1xyXG4gICAgdGhpcy5zdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVZpZXcoKTogdm9pZCB7XHJcbiAgICB0aGlzLnVucmVnaXN0ZXIoKTtcclxuICAgIGlmICh0aGlzLnJlcXVpcmVkUGVybWlzc2lvbnMgfHwgdGhpcy5yZXF1aXJlZFBlcm1pc3Npb25zLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnN1YiA9IHRoaXMuYXV0aENvbnRleHRcclxuICAgICAgICAuaGFzUmVxdWlyZWRQZXJtaXNzaW9uKHRoaXMucmVxdWlyZWRQZXJtaXNzaW9ucylcclxuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKVxyXG4gICAgICAgIC5zdWJzY3JpYmUoKGhhc1Blcm0pID0+IHtcclxuICAgICAgICAgIGlmIChoYXNQZXJtKSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlld0NvbnRhaW5lci5jcmVhdGVFbWJlZGRlZFZpZXcodGhpcy50ZW1wbGF0ZVJlZik7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdDb250YWluZXIuY2xlYXIoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19
@@ -1,55 +0,0 @@
1
- import { Directive, Input, TemplateRef, ViewContainerRef, } from '@angular/core';
2
- import { distinctUntilChanged } from 'rxjs';
3
- import { AuthContextService } from '../services';
4
- import * as i0 from "@angular/core";
5
- import * as i1 from "../services";
6
- export class HasRoleDirective {
7
- templateRef;
8
- viewContainer;
9
- authContext;
10
- requiredRoles;
11
- sub;
12
- constructor(templateRef, viewContainer, authContext) {
13
- this.templateRef = templateRef;
14
- this.viewContainer = viewContainer;
15
- this.authContext = authContext;
16
- }
17
- set hasRole(value) {
18
- this.requiredRoles = value;
19
- this.updateView();
20
- }
21
- ngOnDestroy() {
22
- this.unregister();
23
- }
24
- unregister() {
25
- this.sub?.unsubscribe();
26
- }
27
- updateView() {
28
- this.unregister();
29
- if (this.requiredRoles || this.requiredRoles?.length) {
30
- this.sub = this.authContext
31
- .hasRequiredRole(this.requiredRoles)
32
- .pipe(distinctUntilChanged())
33
- .subscribe((hasRole) => {
34
- if (hasRole) {
35
- this.viewContainer.createEmbeddedView(this.templateRef);
36
- }
37
- else {
38
- this.viewContainer.clear();
39
- }
40
- });
41
- }
42
- }
43
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HasRoleDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: i1.AuthContextService }], target: i0.ɵɵFactoryTarget.Directive });
44
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.8", type: HasRoleDirective, isStandalone: true, selector: "[hasRole]", inputs: { hasRole: "hasRole" }, ngImport: i0 });
45
- }
46
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: HasRoleDirective, decorators: [{
47
- type: Directive,
48
- args: [{
49
- standalone: true,
50
- selector: '[hasRole]',
51
- }]
52
- }], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: i1.AuthContextService }], propDecorators: { hasRole: [{
53
- type: Input
54
- }] } });
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFzLXJvbGUuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYnMvc2VjdXJpdHkvY29yZS9zcmMvbGliL2RpcmVjdGl2ZXMvaGFzLXJvbGUuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLFdBQVcsRUFDWCxnQkFBZ0IsR0FFakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLG9CQUFvQixFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMxRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7OztBQU1qRCxNQUFNLE9BQU8sZ0JBQWdCO0lBS2pCO0lBQ0E7SUFDQTtJQU5GLGFBQWEsQ0FBZ0M7SUFDN0MsR0FBRyxDQUFnQjtJQUUzQixZQUNVLFdBQTJCLEVBQzNCLGFBQStCLEVBQy9CLFdBQStCO1FBRi9CLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixrQkFBYSxHQUFiLGFBQWEsQ0FBa0I7UUFDL0IsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO0lBQ3RDLENBQUM7SUFFSixJQUNJLE9BQU8sQ0FBQyxLQUF3QjtRQUNsQyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVPLFVBQVU7UUFDaEIsSUFBSSxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sVUFBVTtRQUNoQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDckQsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsV0FBVztpQkFDeEIsZUFBZSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7aUJBQ25DLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2lCQUM1QixTQUFTLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDckIsSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDWixJQUFJLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDMUQsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzdCLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUM7SUFDSCxDQUFDO3VHQXRDVSxnQkFBZ0I7MkZBQWhCLGdCQUFnQjs7MkZBQWhCLGdCQUFnQjtrQkFKNUIsU0FBUzttQkFBQztvQkFDVCxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsUUFBUSxFQUFFLFdBQVc7aUJBQ3RCO2dKQVlLLE9BQU87c0JBRFYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgRGlyZWN0aXZlLFxyXG4gIElucHV0LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDb250YWluZXJSZWYsXHJcbiAgT25EZXN0cm95LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEF1dGhDb250ZXh0U2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzJztcclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgc2VsZWN0b3I6ICdbaGFzUm9sZV0nLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgSGFzUm9sZURpcmVjdGl2ZTxUPiBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XHJcbiAgcHJpdmF0ZSByZXF1aXJlZFJvbGVzOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcclxuICBwcml2YXRlIHN1Yj86IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIHRlbXBsYXRlUmVmOiBUZW1wbGF0ZVJlZjxUPixcclxuICAgIHByaXZhdGUgdmlld0NvbnRhaW5lcjogVmlld0NvbnRhaW5lclJlZixcclxuICAgIHByaXZhdGUgYXV0aENvbnRleHQ6IEF1dGhDb250ZXh0U2VydmljZVxyXG4gICkge31cclxuXHJcbiAgQElucHV0KClcclxuICBzZXQgaGFzUm9sZSh2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10pIHtcclxuICAgIHRoaXMucmVxdWlyZWRSb2xlcyA9IHZhbHVlO1xyXG4gICAgdGhpcy51cGRhdGVWaWV3KCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMudW5yZWdpc3RlcigpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1bnJlZ2lzdGVyKCkge1xyXG4gICAgdGhpcy5zdWI/LnVuc3Vic2NyaWJlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVZpZXcoKTogdm9pZCB7XHJcbiAgICB0aGlzLnVucmVnaXN0ZXIoKTtcclxuICAgIGlmICh0aGlzLnJlcXVpcmVkUm9sZXMgfHwgdGhpcy5yZXF1aXJlZFJvbGVzPy5sZW5ndGgpIHtcclxuICAgICAgdGhpcy5zdWIgPSB0aGlzLmF1dGhDb250ZXh0XHJcbiAgICAgICAgLmhhc1JlcXVpcmVkUm9sZSh0aGlzLnJlcXVpcmVkUm9sZXMpXHJcbiAgICAgICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcclxuICAgICAgICAuc3Vic2NyaWJlKChoYXNSb2xlKSA9PiB7XHJcbiAgICAgICAgICBpZiAoaGFzUm9sZSkge1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdDb250YWluZXIuY3JlYXRlRW1iZWRkZWRWaWV3KHRoaXMudGVtcGxhdGVSZWYpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy52aWV3Q29udGFpbmVyLmNsZWFyKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiJdfQ==
@@ -1,3 +0,0 @@
1
- export * from './has-permission.directive';
2
- export * from './has-role.directive';
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGlicy9zZWN1cml0eS9jb3JlL3NyYy9saWIvZGlyZWN0aXZlcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsc0JBQXNCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2hhcy1wZXJtaXNzaW9uLmRpcmVjdGl2ZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vaGFzLXJvbGUuZGlyZWN0aXZlJztcclxuIl19