valtech-components 2.0.428 → 2.0.430
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/esm2022/lib/components/organisms/data-table/data-table.component.mjs +17 -3
- package/esm2022/lib/components/organisms/data-table/types.mjs +1 -1
- package/esm2022/lib/services/auth/auth-state.service.mjs +173 -0
- package/esm2022/lib/services/auth/auth.service.mjs +432 -0
- package/esm2022/lib/services/auth/config.mjs +76 -0
- package/esm2022/lib/services/auth/guards.mjs +194 -0
- package/esm2022/lib/services/auth/index.mjs +70 -0
- package/esm2022/lib/services/auth/interceptor.mjs +98 -0
- package/esm2022/lib/services/auth/storage.service.mjs +138 -0
- package/esm2022/lib/services/auth/sync.service.mjs +146 -0
- package/esm2022/lib/services/auth/token.service.mjs +113 -0
- package/esm2022/lib/services/auth/types.mjs +29 -0
- package/esm2022/public-api.mjs +4 -1
- package/fesm2022/valtech-components.mjs +1465 -8
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/data-table/types.d.ts +8 -0
- package/lib/services/auth/auth-state.service.d.ts +85 -0
- package/lib/services/auth/auth.service.d.ts +123 -0
- package/lib/services/auth/config.d.ts +38 -0
- package/lib/services/auth/guards.d.ts +123 -0
- package/lib/services/auth/index.d.ts +63 -0
- package/lib/services/auth/interceptor.d.ts +22 -0
- package/lib/services/auth/storage.service.d.ts +48 -0
- package/lib/services/auth/sync.service.d.ts +49 -0
- package/lib/services/auth/token.service.d.ts +51 -0
- package/lib/services/auth/types.d.ts +264 -0
- package/package.json +1 -9
- package/public-api.d.ts +1 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { Router, } from '@angular/router';
|
|
3
|
+
import { AuthService } from './auth.service';
|
|
4
|
+
import { VALTECH_AUTH_CONFIG } from './config';
|
|
5
|
+
/**
|
|
6
|
+
* Guard que verifica si el usuario está autenticado.
|
|
7
|
+
* Redirige a loginRoute si no está autenticado.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { authGuard } from 'valtech-components';
|
|
12
|
+
*
|
|
13
|
+
* const routes: Routes = [
|
|
14
|
+
* {
|
|
15
|
+
* path: 'dashboard',
|
|
16
|
+
* canActivate: [authGuard],
|
|
17
|
+
* loadComponent: () => import('./dashboard.page'),
|
|
18
|
+
* },
|
|
19
|
+
* ];
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export const authGuard = () => {
|
|
23
|
+
const authService = inject(AuthService);
|
|
24
|
+
const router = inject(Router);
|
|
25
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
26
|
+
if (authService.isAuthenticated()) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return router.createUrlTree([config.loginRoute]);
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Guard que verifica si el usuario NO está autenticado.
|
|
33
|
+
* Redirige a homeRoute si ya está autenticado.
|
|
34
|
+
* Útil para páginas de login/registro.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* import { guestGuard } from 'valtech-components';
|
|
39
|
+
*
|
|
40
|
+
* const routes: Routes = [
|
|
41
|
+
* {
|
|
42
|
+
* path: 'login',
|
|
43
|
+
* canActivate: [guestGuard],
|
|
44
|
+
* loadComponent: () => import('./login.page'),
|
|
45
|
+
* },
|
|
46
|
+
* ];
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export const guestGuard = () => {
|
|
50
|
+
const authService = inject(AuthService);
|
|
51
|
+
const router = inject(Router);
|
|
52
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
53
|
+
if (!authService.isAuthenticated()) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return router.createUrlTree([config.homeRoute]);
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Factory para crear guard de permisos.
|
|
60
|
+
* Verifica si el usuario tiene el permiso especificado.
|
|
61
|
+
*
|
|
62
|
+
* @param permissions - Permiso o lista de permisos requeridos (OR)
|
|
63
|
+
* @returns Guard function
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { authGuard, permissionGuard } from 'valtech-components';
|
|
68
|
+
*
|
|
69
|
+
* const routes: Routes = [
|
|
70
|
+
* {
|
|
71
|
+
* path: 'templates',
|
|
72
|
+
* canActivate: [authGuard, permissionGuard('templates:read')],
|
|
73
|
+
* loadComponent: () => import('./templates.page'),
|
|
74
|
+
* },
|
|
75
|
+
* {
|
|
76
|
+
* path: 'admin',
|
|
77
|
+
* canActivate: [authGuard, permissionGuard(['admin:*', 'super_admin'])],
|
|
78
|
+
* loadComponent: () => import('./admin.page'),
|
|
79
|
+
* },
|
|
80
|
+
* ];
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function permissionGuard(permissions) {
|
|
84
|
+
return () => {
|
|
85
|
+
const authService = inject(AuthService);
|
|
86
|
+
const router = inject(Router);
|
|
87
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
88
|
+
const permArray = Array.isArray(permissions) ? permissions : [permissions];
|
|
89
|
+
if (authService.hasAnyPermission(permArray)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
console.warn(`[ValtechAuth] Permiso denegado. Requerido: ${permArray.join(' o ')}`);
|
|
93
|
+
return router.createUrlTree([config.unauthorizedRoute]);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Guard que lee permisos desde route.data.
|
|
98
|
+
* Permite configurar permisos directamente en la definición de rutas.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* import { authGuard, permissionGuardFromRoute } from 'valtech-components';
|
|
103
|
+
*
|
|
104
|
+
* const routes: Routes = [
|
|
105
|
+
* {
|
|
106
|
+
* path: 'admin/users',
|
|
107
|
+
* canActivate: [authGuard, permissionGuardFromRoute],
|
|
108
|
+
* data: {
|
|
109
|
+
* permissions: ['users:read', 'users:manage'],
|
|
110
|
+
* requireAll: false // true = AND, false = OR (default)
|
|
111
|
+
* },
|
|
112
|
+
* loadComponent: () => import('./users.page'),
|
|
113
|
+
* },
|
|
114
|
+
* ];
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export const permissionGuardFromRoute = (route) => {
|
|
118
|
+
const authService = inject(AuthService);
|
|
119
|
+
const router = inject(Router);
|
|
120
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
121
|
+
const permissions = route.data['permissions'];
|
|
122
|
+
const requireAll = route.data['requireAll'];
|
|
123
|
+
if (!permissions || permissions.length === 0) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
const hasAccess = requireAll
|
|
127
|
+
? authService.hasAllPermissions(permissions)
|
|
128
|
+
: authService.hasAnyPermission(permissions);
|
|
129
|
+
if (hasAccess) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
console.warn(`[ValtechAuth] Permiso denegado. Requerido: ${permissions.join(requireAll ? ' y ' : ' o ')}`);
|
|
133
|
+
return router.createUrlTree([config.unauthorizedRoute]);
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Guard que verifica si el usuario es super admin.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* import { authGuard, superAdminGuard } from 'valtech-components';
|
|
141
|
+
*
|
|
142
|
+
* const routes: Routes = [
|
|
143
|
+
* {
|
|
144
|
+
* path: 'super-admin',
|
|
145
|
+
* canActivate: [authGuard, superAdminGuard],
|
|
146
|
+
* loadComponent: () => import('./super-admin.page'),
|
|
147
|
+
* },
|
|
148
|
+
* ];
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export const superAdminGuard = () => {
|
|
152
|
+
const authService = inject(AuthService);
|
|
153
|
+
const router = inject(Router);
|
|
154
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
155
|
+
if (authService.isSuperAdmin()) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
console.warn('[ValtechAuth] Acceso de super admin requerido');
|
|
159
|
+
return router.createUrlTree([config.unauthorizedRoute]);
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Guard que verifica si el usuario tiene un rol específico.
|
|
163
|
+
*
|
|
164
|
+
* @param roles - Rol o lista de roles requeridos (OR)
|
|
165
|
+
* @returns Guard function
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* import { authGuard, roleGuard } from 'valtech-components';
|
|
170
|
+
*
|
|
171
|
+
* const routes: Routes = [
|
|
172
|
+
* {
|
|
173
|
+
* path: 'editor',
|
|
174
|
+
* canActivate: [authGuard, roleGuard(['editor', 'admin'])],
|
|
175
|
+
* loadComponent: () => import('./editor.page'),
|
|
176
|
+
* },
|
|
177
|
+
* ];
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export function roleGuard(roles) {
|
|
181
|
+
return () => {
|
|
182
|
+
const authService = inject(AuthService);
|
|
183
|
+
const router = inject(Router);
|
|
184
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
185
|
+
const roleArray = Array.isArray(roles) ? roles : [roles];
|
|
186
|
+
const hasRole = roleArray.some((role) => authService.hasRole(role));
|
|
187
|
+
if (hasRole) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
console.warn(`[ValtechAuth] Rol requerido: ${roleArray.join(' o ')}`);
|
|
191
|
+
return router.createUrlTree([config.unauthorizedRoute]);
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VhcmRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9hdXRoL2d1YXJkcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFDTCxNQUFNLEdBSVAsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRS9DOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFrQixHQUFzQixFQUFFO0lBQzlELE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFM0MsSUFBSSxXQUFXLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztRQUNsQyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztBQUNuRCxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQWtCLEdBQXNCLEVBQUU7SUFDL0QsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUUzQyxJQUFJLENBQUMsV0FBVyxDQUFD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Q0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLENBQUMsSUFBSSxDQUFDLCtDQUErQyxDQUFDLENBQUM7SUFDOUQsT0FBTyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztBQUMxRCxDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxLQUF3QjtJQUNoRCxPQUFPLEdBQXNCLEVBQUU7UUFDN0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUUzQyxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFekQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRXBFLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxPQUFPLENBQUMsSUFBSSxDQUNWLGdDQUFnQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQ3hELENBQUM7UUFDRixPQUFPLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQzFELENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIFJvdXRlcixcbiAgQ2FuQWN0aXZhdGVGbixcbiAgVXJsVHJlZSxcbiAgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCxcbn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgVkFMVEVDSF9BVVRIX0NPTkZJRyB9IGZyb20gJy4vY29uZmlnJztcblxuLyoqXG4gKiBHdWFyZCBxdWUgdmVyaWZpY2Egc2kgZWwgdXN1YXJpbyBlc3TDoSBhdXRlbnRpY2Fkby5cbiAqIFJlZGlyaWdlIGEgbG9naW5Sb3V0ZSBzaSBubyBlc3TDoSBhdXRlbnRpY2Fkby5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgYXV0aEd1YXJkIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICdkYXNoYm9hcmQnLFxuICogICAgIGNhbkFjdGl2YXRlOiBbYXV0aEd1YXJkXSxcbiAqICAgICBsb2FkQ29tcG9uZW50OiAoKSA9PiBpbXBvcnQoJy4vZGFzaGJvYXJkLnBhZ2UnKSxcbiAqICAgfSxcbiAqIF07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IGF1dGhHdWFyZDogQ2FuQWN0aXZhdGVGbiA9ICgpOiBib29sZWFuIHwgVXJsVHJlZSA9PiB7XG4gIGNvbnN0IGF1dGhTZXJ2aWNlID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgY29uc3Qgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XG4gIGNvbnN0IGNvbmZpZyA9IGluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKTtcblxuICBpZiAoYXV0aFNlcnZpY2UuaXNBdXRoZW50aWNhdGVkKCkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbY29uZmlnLmxvZ2luUm91dGVdKTtcbn07XG5cbi8qKlxuICogR3VhcmQgcXVlIHZlcmlmaWNhIHNpIGVsIHVzdWFyaW8gTk8gZXN0w6EgYXV0ZW50aWNhZG8uXG4gKiBSZWRpcmlnZSBhIGhvbWVSb3V0ZSBzaSB5YSBlc3TDoSBhdXRlbnRpY2Fkby5cbiAqIMOadGlsIHBhcmEgcMOhZ2luYXMgZGUgbG9naW4vcmVnaXN0cm8uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGd1ZXN0R3VhcmQgfSBmcm9tICd2YWx0ZWNoLWNvbXBvbmVudHMnO1xuICpcbiAqIGNvbnN0IHJvdXRlczogUm91dGVzID0gW1xuICogICB7XG4gKiAgICAgcGF0aDogJ2xvZ2luJyxcbiAqICAgICBjYW5BY3RpdmF0ZTogW2d1ZXN0R3VhcmRdLFxuICogICAgIGxvYWRDb21wb25lbnQ6ICgpID0+IGltcG9ydCgnLi9sb2dpbi5wYWdlJyksXG4gKiAgIH0sXG4gKiBdO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCBndWVzdEd1YXJkOiBDYW5BY3RpdmF0ZUZuID0gKCk6IGJvb2xlYW4gfCBVcmxUcmVlID0+IHtcbiAgY29uc3QgYXV0aFNlcnZpY2UgPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KFZBTFRFQ0hfQVVUSF9DT05GSUcpO1xuXG4gIGlmICghYXV0aFNlcnZpY2UuaXNBdXRoZW50aWNhdGVkKCkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbY29uZmlnLmhvbWVSb3V0ZV0pO1xufTtcblxuLyoqXG4gKiBGYWN0b3J5IHBhcmEgY3JlYXIgZ3VhcmQgZGUgcGVybWlzb3MuXG4gKiBWZXJpZmljYSBzaSBlbCB1c3VhcmlvIHRpZW5lIGVsIHBlcm1pc28gZXNwZWNpZmljYWRvLlxuICpcbiAqIEBwYXJhbSBwZXJtaXNzaW9ucyAtIFBlcm1pc28gbyBsaXN0YSBkZSBwZXJtaXNvcyByZXF1ZXJpZG9zIChPUilcbiAqIEByZXR1cm5zIEd1YXJkIGZ1bmN0aW9uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGF1dGhHdWFyZCwgcGVybWlzc2lvbkd1YXJkIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICd0ZW1wbGF0ZXMnLFxuICogICAgIGNhbkFjdGl2YXRlOiBbYXV0aEd1YXJkLCBwZXJtaXNzaW9uR3VhcmQoJ3RlbXBsYXRlczpyZWFkJyldLFxuICogICAgIGxvYWRDb21wb25lbnQ6ICgpID0+IGltcG9ydCgnLi90ZW1wbGF0ZXMucGFnZScpLFxuICogICB9LFxuICogICB7XG4gKiAgICAgcGF0aDogJ2FkbWluJyxcbiAqICAgICBjYW5BY3RpdmF0ZTogW2F1dGhHdWFyZCwgcGVybWlzc2lvbkd1YXJkKFsnYWRtaW46KicsICdzdXBlcl9hZG1pbiddKV0sXG4gKiAgICAgbG9hZENvbXBvbmVudDogKCkgPT4gaW1wb3J0KCcuL2FkbWluLnBhZ2UnKSxcbiAqICAgfSxcbiAqIF07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBlcm1pc3Npb25HdWFyZChcbiAgcGVybWlzc2lvbnM6IHN0cmluZyB8IHN0cmluZ1tdXG4pOiBDYW5BY3RpdmF0ZUZuIHtcbiAgcmV0dXJuICgpOiBib29sZWFuIHwgVXJsVHJlZSA9PiB7XG4gICAgY29uc3QgYXV0aFNlcnZpY2UgPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICAgIGNvbnN0IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICAgIGNvbnN0IGNvbmZpZyA9IGluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKTtcblxuICAgIGNvbnN0IHBlcm1BcnJheSA9IEFycmF5LmlzQXJyYXkocGVybWlzc2lvbnMpID8gcGVybWlzc2lvbnMgOiBbcGVybWlzc2lvbnNdO1xuXG4gICAgaWYgKGF1dGhTZXJ2aWNlLmhhc0FueVBlcm1pc3Npb24ocGVybUFycmF5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYFtWYWx0ZWNoQXV0aF0gUGVybWlzbyBkZW5lZ2Fkby4gUmVxdWVyaWRvOiAke3Blcm1BcnJheS5qb2luKCcgbyAnKX1gXG4gICAgKTtcbiAgICByZXR1cm4gcm91dGVyLmNyZWF0ZVVybFRyZWUoW2NvbmZpZy51bmF1dGhvcml6ZWRSb3V0ZV0pO1xuICB9O1xufVxuXG4vKipcbiAqIEd1YXJkIHF1ZSBsZWUgcGVybWlzb3MgZGVzZGUgcm91dGUuZGF0YS5cbiAqIFBlcm1pdGUgY29uZmlndXJhciBwZXJtaXNvcyBkaXJlY3RhbWVudGUgZW4gbGEgZGVmaW5pY2nDs24gZGUgcnV0YXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IGF1dGhHdWFyZCwgcGVybWlzc2lvbkd1YXJkRnJvbVJvdXRlIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICdhZG1pbi91c2VycycsXG4gKiAgICAgY2FuQWN0aXZhdGU6IFthdXRoR3VhcmQsIHBlcm1pc3Npb25HdWFyZEZyb21Sb3V0ZV0sXG4gKiAgICAgZGF0YToge1xuICogICAgICAgcGVybWlzc2lvbnM6IFsndXNlcnM6cmVhZCcsICd1c2VyczptYW5hZ2UnXSxcbiAqICAgICAgIHJlcXVpcmVBbGw6IGZhbHNlICAvLyB0cnVlID0gQU5ELCBmYWxzZSA9IE9SIChkZWZhdWx0KVxuICogICAgIH0sXG4gKiAgICAgbG9hZENvbXBvbmVudDogKCkgPT4gaW1wb3J0KCcuL3VzZXJzLnBhZ2UnKSxcbiAqICAgfSxcbiAqIF07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IHBlcm1pc3Npb25HdWFyZEZyb21Sb3V0ZTogQ2FuQWN0aXZhdGVGbiA9IChcbiAgcm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3Rcbik6IGJvb2xlYW4gfCBVcmxUcmVlID0+IHtcbiAgY29uc3QgYXV0aFNlcnZpY2UgPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgY29uc3QgY29uZmlnID0gaW5qZWN0KFZBTFRFQ0hfQVVUSF9DT05GSUcpO1xuXG4gIGNvbnN0IHBlcm1pc3Npb25zID0gcm91dGUuZGF0YVsncGVybWlzc2lvbnMnXSBhcyBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcbiAgY29uc3QgcmVxdWlyZUFsbCA9IHJvdXRlLmRhdGFbJ3JlcXVpcmVBbGwnXSBhcyBib29sZWFuIHwgdW5kZWZpbmVkO1xuXG4gIGlmICghcGVybWlzc2lvbnMgfHwgcGVybWlzc2lvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBoYXNBY2Nlc3MgPSByZXF1aXJlQWxsXG4gICAgPyBhdXRoU2VydmljZS5oYXNBbGxQZXJtaXNzaW9ucyhwZXJtaXNzaW9ucylcbiAgICA6IGF1dGhTZXJ2aWNlLmhhc0FueVBlcm1pc3Npb24ocGVybWlzc2lvbnMpO1xuXG4gIGlmIChoYXNBY2Nlc3MpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGNvbnNvbGUud2FybihcbiAgICBgW1ZhbHRlY2hBdXRoXSBQZXJtaXNvIGRlbmVnYWRvLiBSZXF1ZXJpZG86ICR7cGVybWlzc2lvbnMuam9pbihcbiAgICAgIHJlcXVpcmVBbGwgPyAnIHkgJyA6ICcgbyAnXG4gICAgKX1gXG4gICk7XG4gIHJldHVybiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbY29uZmlnLnVuYXV0aG9yaXplZFJvdXRlXSk7XG59O1xuXG4vKipcbiAqIEd1YXJkIHF1ZSB2ZXJpZmljYSBzaSBlbCB1c3VhcmlvIGVzIHN1cGVyIGFkbWluLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBhdXRoR3VhcmQsIHN1cGVyQWRtaW5HdWFyZCB9IGZyb20gJ3ZhbHRlY2gtY29tcG9uZW50cyc7XG4gKlxuICogY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gKiAgIHtcbiAqICAgICBwYXRoOiAnc3VwZXItYWRtaW4nLFxuICogICAgIGNhbkFjdGl2YXRlOiBbYXV0aEd1YXJkLCBzdXBlckFkbWluR3VhcmRdLFxuICogICAgIGxvYWRDb21wb25lbnQ6ICgpID0+IGltcG9ydCgnLi9zdXBlci1hZG1pbi5wYWdlJyksXG4gKiAgIH0sXG4gKiBdO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCBzdXBlckFkbWluR3VhcmQ6IENhbkFjdGl2YXRlRm4gPSAoKTogYm9vbGVhbiB8IFVybFRyZWUgPT4ge1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICBjb25zdCBjb25maWcgPSBpbmplY3QoVkFMVEVDSF9BVVRIX0NPTkZJRyk7XG5cbiAgaWYgKGF1dGhTZXJ2aWNlLmlzU3VwZXJBZG1pbigpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zb2xlLndhcm4oJ1tWYWx0ZWNoQXV0aF0gQWNjZXNvIGRlIHN1cGVyIGFkbWluIHJlcXVlcmlkbycpO1xuICByZXR1cm4gcm91dGVyLmNyZWF0ZVVybFRyZWUoW2NvbmZpZy51bmF1dGhvcml6ZWRSb3V0ZV0pO1xufTtcblxuLyoqXG4gKiBHdWFyZCBxdWUgdmVyaWZpY2Egc2kgZWwgdXN1YXJpbyB0aWVuZSB1biByb2wgZXNwZWPDrWZpY28uXG4gKlxuICogQHBhcmFtIHJvbGVzIC0gUm9sIG8gbGlzdGEgZGUgcm9sZXMgcmVxdWVyaWRvcyAoT1IpXG4gKiBAcmV0dXJucyBHdWFyZCBmdW5jdGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBhdXRoR3VhcmQsIHJvbGVHdWFyZCB9IGZyb20gJ3ZhbHRlY2gtY29tcG9uZW50cyc7XG4gKlxuICogY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gKiAgIHtcbiAqICAgICBwYXRoOiAnZWRpdG9yJyxcbiAqICAgICBjYW5BY3RpdmF0ZTogW2F1dGhHdWFyZCwgcm9sZUd1YXJkKFsnZWRpdG9yJywgJ2FkbWluJ10pXSxcbiAqICAgICBsb2FkQ29tcG9uZW50OiAoKSA9PiBpbXBvcnQoJy4vZWRpdG9yLnBhZ2UnKSxcbiAqICAgfSxcbiAqIF07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvbGVHdWFyZChyb2xlczogc3RyaW5nIHwgc3RyaW5nW10pOiBDYW5BY3RpdmF0ZUZuIHtcbiAgcmV0dXJuICgpOiBib29sZWFuIHwgVXJsVHJlZSA9PiB7XG4gICAgY29uc3QgYXV0aFNlcnZpY2UgPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICAgIGNvbnN0IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICAgIGNvbnN0IGNvbmZpZyA9IGluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKTtcblxuICAgIGNvbnN0IHJvbGVBcnJheSA9IEFycmF5LmlzQXJyYXkocm9sZXMpID8gcm9sZXMgOiBbcm9sZXNdO1xuXG4gICAgY29uc3QgaGFzUm9sZSA9IHJvbGVBcnJheS5zb21lKChyb2xlKSA9PiBhdXRoU2VydmljZS5oYXNSb2xlKHJvbGUpKTtcblxuICAgIGlmIChoYXNSb2xlKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBjb25zb2xlLndhcm4oXG4gICAgICBgW1ZhbHRlY2hBdXRoXSBSb2wgcmVxdWVyaWRvOiAke3JvbGVBcnJheS5qb2luKCcgbyAnKX1gXG4gICAgKTtcbiAgICByZXR1cm4gcm91dGVyLmNyZWF0ZVVybFRyZWUoW2NvbmZpZy51bmF1dGhvcml6ZWRSb3V0ZV0pO1xuICB9O1xufVxuIl19
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valtech Auth Service
|
|
3
|
+
*
|
|
4
|
+
* Servicio de autenticación reutilizable para aplicaciones Angular.
|
|
5
|
+
* Proporciona autenticación con AuthV2, MFA, sincronización entre pestañas,
|
|
6
|
+
* y refresh proactivo de tokens.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // En main.ts
|
|
11
|
+
* import { bootstrapApplication } from '@angular/platform-browser';
|
|
12
|
+
* import { provideValtechAuth } from 'valtech-components';
|
|
13
|
+
* import { environment } from './environments/environment';
|
|
14
|
+
*
|
|
15
|
+
* bootstrapApplication(AppComponent, {
|
|
16
|
+
* providers: [
|
|
17
|
+
* provideValtechAuth({
|
|
18
|
+
* apiUrl: environment.apiUrl,
|
|
19
|
+
* enableFirebaseIntegration: true,
|
|
20
|
+
* }),
|
|
21
|
+
* ],
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // En app.routes.ts
|
|
25
|
+
* import { authGuard, guestGuard, permissionGuard } from 'valtech-components';
|
|
26
|
+
*
|
|
27
|
+
* const routes: Routes = [
|
|
28
|
+
* { path: 'login', canActivate: [guestGuard], loadComponent: () => import('./login.page') },
|
|
29
|
+
* { path: 'dashboard', canActivate: [authGuard], loadComponent: () => import('./dashboard.page') },
|
|
30
|
+
* { path: 'admin', canActivate: [authGuard, permissionGuard('admin:*')], loadComponent: () => import('./admin.page') },
|
|
31
|
+
* ];
|
|
32
|
+
*
|
|
33
|
+
* // En componentes
|
|
34
|
+
* import { AuthService } from 'valtech-components';
|
|
35
|
+
*
|
|
36
|
+
* @Component({...})
|
|
37
|
+
* export class LoginComponent {
|
|
38
|
+
* private auth = inject(AuthService);
|
|
39
|
+
*
|
|
40
|
+
* async login() {
|
|
41
|
+
* await firstValueFrom(this.auth.signin({ email, password }));
|
|
42
|
+
* if (this.auth.mfaPending().required) {
|
|
43
|
+
* // Mostrar UI de MFA
|
|
44
|
+
* } else {
|
|
45
|
+
* this.router.navigate(['/dashboard']);
|
|
46
|
+
* }
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* // En template: usar signals directamente
|
|
50
|
+
* // {{ auth.user()?.email }}
|
|
51
|
+
* // @if (auth.hasPermission('templates:edit')) { ... }
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
// Tipos
|
|
56
|
+
export * from './types';
|
|
57
|
+
// Configuración
|
|
58
|
+
export { VALTECH_AUTH_CONFIG, provideValtechAuth, provideValtechAuthInterceptor, DEFAULT_AUTH_CONFIG, } from './config';
|
|
59
|
+
// Servicio principal
|
|
60
|
+
export { AuthService } from './auth.service';
|
|
61
|
+
// Guards
|
|
62
|
+
export { authGuard, guestGuard, permissionGuard, permissionGuardFromRoute, superAdminGuard, roleGuard, } from './guards';
|
|
63
|
+
// Interceptor (para uso avanzado)
|
|
64
|
+
export { authInterceptor } from './interceptor';
|
|
65
|
+
// Servicios internos (para testing o extensión)
|
|
66
|
+
export { AuthStateService } from './auth-state.service';
|
|
67
|
+
export { TokenService } from './token.service';
|
|
68
|
+
export { AuthStorageService } from './storage.service';
|
|
69
|
+
export { AuthSyncService } from './sync.service';
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2F1dGgvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcURHO0FBRUgsUUFBUTtBQUNSLGNBQWMsU0FBUyxDQUFDO0FBRXhCLGdCQUFnQjtBQUNoQixPQUFPLEVBQ0wsbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQiw2QkFBNkIsRUFDN0IsbUJBQW1CLEdBQ3BCLE1BQU0sVUFBVSxDQUFDO0FBRWxCLHFCQUFxQjtBQUNyQixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0MsU0FBUztBQUNULE9BQU8sRUFDTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLGVBQWUsRUFDZix3QkFBd0IsRUFDeEIsZUFBZSxFQUNmLFNBQVMsR0FDVixNQUFNLFVBQVUsQ0FBQztBQUVsQixrQ0FBa0M7QUFDbEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVoRCxnREFBZ0Q7QUFDaEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVmFsdGVjaCBBdXRoIFNlcnZpY2VcbiAqXG4gKiBTZXJ2aWNpbyBkZSBhdXRlbnRpY2FjacOzbiByZXV0aWxpemFibGUgcGFyYSBhcGxpY2FjaW9uZXMgQW5ndWxhci5cbiAqIFByb3BvcmNpb25hIGF1dGVudGljYWNpw7NuIGNvbiBBdXRoVjIsIE1GQSwgc2luY3Jvbml6YWNpw7NuIGVudHJlIHBlc3Rhw7FhcyxcbiAqIHkgcmVmcmVzaCBwcm9hY3Rpdm8gZGUgdG9rZW5zLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBFbiBtYWluLnRzXG4gKiBpbXBvcnQgeyBib290c3RyYXBBcHBsaWNhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuICogaW1wb3J0IHsgcHJvdmlkZVZhbHRlY2hBdXRoIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqIGltcG9ydCB7IGVudmlyb25tZW50IH0gZnJvbSAnLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQnO1xuICpcbiAqIGJvb3RzdHJhcEFwcGxpY2F0aW9uKEFwcENvbXBvbmVudCwge1xuICogICBwcm92aWRlcnM6IFtcbiAqICAgICBwcm92aWRlVmFsdGVjaEF1dGgoe1xuICogICAgICAgYXBpVXJsOiBlbnZpcm9ubWVudC5hcGlVcmwsXG4gKiAgICAgICBlbmFibGVGaXJlYmFzZUludGVncmF0aW9uOiB0cnVlLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSk7XG4gKlxuICogLy8gRW4gYXBwLnJvdXRlcy50c1xuICogaW1wb3J0IHsgYXV0aEd1YXJkLCBndWVzdEd1YXJkLCBwZXJtaXNzaW9uR3VhcmQgfSBmcm9tICd2YWx0ZWNoLWNvbXBvbmVudHMnO1xuICpcbiAqIGNvbnN0IHJvdXRlczogUm91dGVzID0gW1xuICogICB7IHBhdGg6ICdsb2dpbicsIGNhbkFjdGl2YXRlOiBbZ3Vlc3RHdWFyZF0sIGxvYWRDb21wb25lbnQ6ICgpID0+IGltcG9ydCgnLi9sb2dpbi5wYWdlJykgfSxcbiAqICAgeyBwYXRoOiAnZGFzaGJvYXJkJywgY2FuQWN0aXZhdGU6IFthdXRoR3VhcmRdLCBsb2FkQ29tcG9uZW50OiAoKSA9PiBpbXBvcnQoJy4vZGFzaGJvYXJkLnBhZ2UnKSB9LFxuICogICB7IHBhdGg6ICdhZG1pbicsIGNhbkFjdGl2YXRlOiBbYXV0aEd1YXJkLCBwZXJtaXNzaW9uR3VhcmQoJ2FkbWluOionKV0sIGxvYWRDb21wb25lbnQ6ICgpID0+IGltcG9ydCgnLi9hZG1pbi5wYWdlJykgfSxcbiAqIF07XG4gKlxuICogLy8gRW4gY29tcG9uZW50ZXNcbiAqIGltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBAQ29tcG9uZW50KHsuLi59KVxuICogZXhwb3J0IGNsYXNzIExvZ2luQ29tcG9uZW50IHtcbiAqICAgcHJpdmF0ZSBhdXRoID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAqXG4gKiAgIGFzeW5jIGxvZ2luKCkge1xuICogICAgIGF3YWl0IGZpcnN0VmFsdWVGcm9tKHRoaXMuYXV0aC5zaWduaW4oeyBlbWFpbCwgcGFzc3dvcmQgfSkpO1xuICogICAgIGlmICh0aGlzLmF1dGgubWZhUGVuZGluZygpLnJlcXVpcmVkKSB7XG4gKiAgICAgICAvLyBNb3N0cmFyIFVJIGRlIE1GQVxuICogICAgIH0gZWxzZSB7XG4gKiAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy9kYXNoYm9hcmQnXSk7XG4gKiAgICAgfVxuICogICB9XG4gKlxuICogICAvLyBFbiB0ZW1wbGF0ZTogdXNhciBzaWduYWxzIGRpcmVjdGFtZW50ZVxuICogICAvLyB7eyBhdXRoLnVzZXIoKT8uZW1haWwgfX1cbiAqICAgLy8gQGlmIChhdXRoLmhhc1Blcm1pc3Npb24oJ3RlbXBsYXRlczplZGl0JykpIHsgLi4uIH1cbiAqIH1cbiAqIGBgYFxuICovXG5cbi8vIFRpcG9zXG5leHBvcnQgKiBmcm9tICcuL3R5cGVzJztcblxuLy8gQ29uZmlndXJhY2nDs25cbmV4cG9ydCB7XG4gIFZBTFRFQ0hfQVVUSF9DT05GSUcsXG4gIHByb3ZpZGVWYWx0ZWNoQXV0aCxcbiAgcHJvdmlkZVZhbHRlY2hBdXRoSW50ZXJjZXB0b3IsXG4gIERFRkFVTFRfQVVUSF9DT05GSUcsXG59IGZyb20gJy4vY29uZmlnJztcblxuLy8gU2VydmljaW8gcHJpbmNpcGFsXG5leHBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4vYXV0aC5zZXJ2aWNlJztcblxuLy8gR3VhcmRzXG5leHBvcnQge1xuICBhdXRoR3VhcmQsXG4gIGd1ZXN0R3VhcmQsXG4gIHBlcm1pc3Npb25HdWFyZCxcbiAgcGVybWlzc2lvbkd1YXJkRnJvbVJvdXRlLFxuICBzdXBlckFkbWluR3VhcmQsXG4gIHJvbGVHdWFyZCxcbn0gZnJvbSAnLi9ndWFyZHMnO1xuXG4vLyBJbnRlcmNlcHRvciAocGFyYSB1c28gYXZhbnphZG8pXG5leHBvcnQgeyBhdXRoSW50ZXJjZXB0b3IgfSBmcm9tICcuL2ludGVyY2VwdG9yJztcblxuLy8gU2VydmljaW9zIGludGVybm9zIChwYXJhIHRlc3RpbmcgbyBleHRlbnNpw7NuKVxuZXhwb3J0IHsgQXV0aFN0YXRlU2VydmljZSB9IGZyb20gJy4vYXV0aC1zdGF0ZS5zZXJ2aWNlJztcbmV4cG9ydCB7IFRva2VuU2VydmljZSB9IGZyb20gJy4vdG9rZW4uc2VydmljZSc7XG5leHBvcnQgeyBBdXRoU3RvcmFnZVNlcnZpY2UgfSBmcm9tICcuL3N0b3JhZ2Uuc2VydmljZSc7XG5leHBvcnQgeyBBdXRoU3luY1NlcnZpY2UgfSBmcm9tICcuL3N5bmMuc2VydmljZSc7XG4iXX0=
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { inject } from '@angular/core';
|
|
2
|
+
import { throwError, BehaviorSubject } from 'rxjs';
|
|
3
|
+
import { catchError, filter, take, switchMap, finalize } from 'rxjs/operators';
|
|
4
|
+
import { AuthService } from './auth.service';
|
|
5
|
+
import { VALTECH_AUTH_CONFIG } from './config';
|
|
6
|
+
// Control de estado de refresco (singleton a nivel de módulo)
|
|
7
|
+
let isRefreshing = false;
|
|
8
|
+
const refreshTokenSubject = new BehaviorSubject(null);
|
|
9
|
+
/**
|
|
10
|
+
* Interceptor HTTP que:
|
|
11
|
+
* 1. Agrega header Authorization con Bearer token a requests API
|
|
12
|
+
* 2. Maneja errores 401 refrescando el token automáticamente
|
|
13
|
+
* 3. Encola requests durante el refresco para evitar múltiples refresh
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Incluido automáticamente por provideValtechAuth()
|
|
18
|
+
* // Para uso manual:
|
|
19
|
+
* import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
|
20
|
+
* import { authInterceptor } from 'valtech-components';
|
|
21
|
+
*
|
|
22
|
+
* bootstrapApplication(AppComponent, {
|
|
23
|
+
* providers: [
|
|
24
|
+
* provideHttpClient(withInterceptors([authInterceptor])),
|
|
25
|
+
* ],
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const authInterceptor = (request, next) => {
|
|
30
|
+
const authService = inject(AuthService);
|
|
31
|
+
const config = inject(VALTECH_AUTH_CONFIG);
|
|
32
|
+
// Omitir requests que no son a nuestra API
|
|
33
|
+
if (!isApiRequest(request, config.apiUrl)) {
|
|
34
|
+
return next(request);
|
|
35
|
+
}
|
|
36
|
+
// Omitir endpoints de auth que no necesitan token
|
|
37
|
+
if (isAuthEndpoint(request, config.authPrefix)) {
|
|
38
|
+
return next(request);
|
|
39
|
+
}
|
|
40
|
+
const accessToken = authService.accessToken();
|
|
41
|
+
// Agregar header de autorización si hay token
|
|
42
|
+
if (accessToken) {
|
|
43
|
+
request = addAuthHeader(request, accessToken);
|
|
44
|
+
}
|
|
45
|
+
return next(request).pipe(catchError((error) => {
|
|
46
|
+
if (error.status === 401 && !isAuthEndpoint(request, config.authPrefix)) {
|
|
47
|
+
return handle401Error(request, next, authService);
|
|
48
|
+
}
|
|
49
|
+
if (error.status === 403) {
|
|
50
|
+
console.error('[ValtechAuth] Permiso denegado:', error.error?.message || 'Acceso prohibido');
|
|
51
|
+
}
|
|
52
|
+
return throwError(() => error);
|
|
53
|
+
}));
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Agrega header de autorización a la request.
|
|
57
|
+
*/
|
|
58
|
+
function addAuthHeader(request, token) {
|
|
59
|
+
return request.clone({
|
|
60
|
+
setHeaders: {
|
|
61
|
+
Authorization: `Bearer ${token}`,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verifica si la request es a nuestra API.
|
|
67
|
+
*/
|
|
68
|
+
function isApiRequest(request, apiUrl) {
|
|
69
|
+
return request.url.startsWith(apiUrl) || request.url.includes('/v2/auth');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Verifica si la request es a un endpoint de auth que no debe reintentar.
|
|
73
|
+
*/
|
|
74
|
+
function isAuthEndpoint(request, authPrefix) {
|
|
75
|
+
const authEndpoints = ['/signin', '/signup', '/refresh', '/logout', '/mfa/verify'];
|
|
76
|
+
return authEndpoints.some((endpoint) => request.url.includes(`${authPrefix}${endpoint}`));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Maneja errores 401 refrescando el token.
|
|
80
|
+
*/
|
|
81
|
+
function handle401Error(request, next, authService) {
|
|
82
|
+
if (!isRefreshing) {
|
|
83
|
+
isRefreshing = true;
|
|
84
|
+
refreshTokenSubject.next(null);
|
|
85
|
+
return authService.refreshAccessToken().pipe(switchMap((response) => {
|
|
86
|
+
refreshTokenSubject.next(response.accessToken);
|
|
87
|
+
return next(addAuthHeader(request, response.accessToken));
|
|
88
|
+
}), catchError((error) => {
|
|
89
|
+
authService.logout();
|
|
90
|
+
return throwError(() => error);
|
|
91
|
+
}), finalize(() => {
|
|
92
|
+
isRefreshing = false;
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
// Esperar a que termine el refresco en curso
|
|
96
|
+
return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => next(addAuthHeader(request, token))));
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2F1dGgvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQVF2QyxPQUFPLEVBQWMsVUFBVSxFQUFFLGVBQWUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFL0MsOERBQThEO0FBQzlELElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztBQUN6QixNQUFNLG1CQUFtQixHQUFHLElBQUksZUFBZSxDQUFnQixJQUFJLENBQUMsQ0FBQztBQUVyRTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBc0IsQ0FDaEQsT0FBNkIsRUFDN0IsSUFBbUIsRUFDYSxFQUFFO0lBQ2xDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUUzQywyQ0FBMkM7SUFDM0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDMUMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdkIsQ0FBQztJQUVELGtEQUFrRDtJQUNsRCxJQUFJLGNBQWMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLFVBQVcsQ0FBQyxFQUFFLENBQUM7UUFDaEQsT0FB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Q0FBQztRQUN2QixDQUFDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELDZDQUE2QztJQUM3QyxPQUFPLG1CQUFtQixDQUFDLElBQUksQ0FDN0IsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFtQixFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxFQUNsRCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQ1AsU0FBUyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQzFELENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBIdHRwSW50ZXJjZXB0b3JGbixcbiAgSHR0cFJlcXVlc3QsXG4gIEh0dHBIYW5kbGVyRm4sXG4gIEh0dHBFdmVudCxcbiAgSHR0cEVycm9yUmVzcG9uc2UsXG59IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE9ic2VydmFibGUsIHRocm93RXJyb3IsIEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgZmlsdGVyLCB0YWtlLCBzd2l0Y2hNYXAsIGZpbmFsaXplIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBWQUxURUNIX0FVVEhfQ09ORklHIH0gZnJvbSAnLi9jb25maWcnO1xuXG4vLyBDb250cm9sIGRlIGVzdGFkbyBkZSByZWZyZXNjbyAoc2luZ2xldG9uIGEgbml2ZWwgZGUgbcOzZHVsbylcbmxldCBpc1JlZnJlc2hpbmcgPSBmYWxzZTtcbmNvbnN0IHJlZnJlc2hUb2tlblN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IG51bGw+KG51bGwpO1xuXG4vKipcbiAqIEludGVyY2VwdG9yIEhUVFAgcXVlOlxuICogMS4gQWdyZWdhIGhlYWRlciBBdXRob3JpemF0aW9uIGNvbiBCZWFyZXIgdG9rZW4gYSByZXF1ZXN0cyBBUElcbiAqIDIuIE1hbmVqYSBlcnJvcmVzIDQwMSByZWZyZXNjYW5kbyBlbCB0b2tlbiBhdXRvbcOhdGljYW1lbnRlXG4gKiAzLiBFbmNvbGEgcmVxdWVzdHMgZHVyYW50ZSBlbCByZWZyZXNjbyBwYXJhIGV2aXRhciBtw7psdGlwbGVzIHJlZnJlc2hcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gSW5jbHVpZG8gYXV0b23DoXRpY2FtZW50ZSBwb3IgcHJvdmlkZVZhbHRlY2hBdXRoKClcbiAqIC8vIFBhcmEgdXNvIG1hbnVhbDpcbiAqIGltcG9ydCB7IHByb3ZpZGVIdHRwQ2xpZW50LCB3aXRoSW50ZXJjZXB0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuICogaW1wb3J0IHsgYXV0aEludGVyY2VwdG9yIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBib290c3RyYXBBcHBsaWNhdGlvbihBcHBDb21wb25lbnQsIHtcbiAqICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgcHJvdmlkZUh0dHBDbGllbnQod2l0aEludGVyY2VwdG9ycyhbYXV0aEludGVyY2VwdG9yXSkpLFxuICogICBdLFxuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNvbnN0IGF1dGhJbnRlcmNlcHRvcjogSHR0cEludGVyY2VwdG9yRm4gPSAoXG4gIHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PHVua25vd24+LFxuICBuZXh0OiBIdHRwSGFuZGxlckZuXG4pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDx1bmtub3duPj4gPT4ge1xuICBjb25zdCBhdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIGNvbnN0IGNvbmZpZyA9IGluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKTtcblxuICAvLyBPbWl0aXIgcmVxdWVzdHMgcXVlIG5vIHNvbiBhIG51ZXN0cmEgQVBJXG4gIGlmICghaXNBcGlSZXF1ZXN0KHJlcXVlc3QsIGNvbmZpZy5hcGlVcmwpKSB7XG4gICAgcmV0dXJuIG5leHQocmVxdWVzdCk7XG4gIH1cblxuICAvLyBPbWl0aXIgZW5kcG9pbnRzIGRlIGF1dGggcXVlIG5vIG5lY2VzaXRhbiB0b2tlblxuICBpZiAoaXNBdXRoRW5kcG9pbnQocmVxdWVzdCwgY29uZmlnLmF1dGhQcmVmaXghKSkge1xuICAgIHJldHVybiBuZXh0KHJlcXVlc3QpO1xuICB9XG5cbiAgY29uc3QgYWNjZXNzVG9rZW4gPSBhdXRoU2VydmljZS5hY2Nlc3NUb2tlbigpO1xuXG4gIC8vIEFncmVnYXIgaGVhZGVyIGRlIGF1dG9yaXphY2nDs24gc2kgaGF5IHRva2VuXG4gIGlmIChhY2Nlc3NUb2tlbikge1xuICAgIHJlcXVlc3QgPSBhZGRBdXRoSGVhZGVyKHJlcXVlc3QsIGFjY2Vzc1Rva2VuKTtcbiAgfVxuXG4gIHJldHVybiBuZXh0KHJlcXVlc3QpLnBpcGUoXG4gICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDEgJiYgIWlzQXV0aEVuZHBvaW50KHJlcXVlc3QsIGNvbmZpZy5hdXRoUHJlZml4ISkpIHtcbiAgICAgICAgcmV0dXJuIGhhbmRsZTQwMUVycm9yKHJlcXVlc3QsIG5leHQsIGF1dGhTZXJ2aWNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDAzKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgJ1tWYWx0ZWNoQXV0aF0gUGVybWlzbyBkZW5lZ2FkbzonLFxuICAgICAgICAgIGVycm9yLmVycm9yPy5tZXNzYWdlIHx8ICdBY2Nlc28gcHJvaGliaWRvJ1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgfSlcbiAgKTtcbn07XG5cbi8qKlxuICogQWdyZWdhIGhlYWRlciBkZSBhdXRvcml6YWNpw7NuIGEgbGEgcmVxdWVzdC5cbiAqL1xuZnVuY3Rpb24gYWRkQXV0aEhlYWRlcihcbiAgcmVxdWVzdDogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIHRva2VuOiBzdHJpbmdcbik6IEh0dHBSZXF1ZXN0PHVua25vd24+IHtcbiAgcmV0dXJuIHJlcXVlc3QuY2xvbmUoe1xuICAgIHNldEhlYWRlcnM6IHtcbiAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIFZlcmlmaWNhIHNpIGxhIHJlcXVlc3QgZXMgYSBudWVzdHJhIEFQSS5cbiAqL1xuZnVuY3Rpb24gaXNBcGlSZXF1ZXN0KHJlcXVlc3Q6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBhcGlVcmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gcmVxdWVzdC51cmwuc3RhcnRzV2l0aChhcGlVcmwpIHx8IHJlcXVlc3QudXJsLmluY2x1ZGVzKCcvdjIvYXV0aCcpO1xufVxuXG4vKipcbiAqIFZlcmlmaWNhIHNpIGxhIHJlcXVlc3QgZXMgYSB1biBlbmRwb2ludCBkZSBhdXRoIHF1ZSBubyBkZWJlIHJlaW50ZW50YXIuXG4gKi9cbmZ1bmN0aW9uIGlzQXV0aEVuZHBvaW50KFxuICByZXF1ZXN0OiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgYXV0aFByZWZpeDogc3RyaW5nXG4pOiBib29sZWFuIHtcbiAgY29uc3QgYXV0aEVuZHBvaW50cyA9IFsnL3NpZ25pbicsICcvc2lnbnVwJywgJy9yZWZyZXNoJywgJy9sb2dvdXQnLCAnL21mYS92ZXJpZnknXTtcbiAgcmV0dXJuIGF1dGhFbmRwb2ludHMuc29tZSgoZW5kcG9pbnQpID0+XG4gICAgcmVxdWVzdC51cmwuaW5jbHVkZXMoYCR7YXV0aFByZWZpeH0ke2VuZHBvaW50fWApXG4gICk7XG59XG5cbi8qKlxuICogTWFuZWphIGVycm9yZXMgNDAxIHJlZnJlc2NhbmRvIGVsIHRva2VuLlxuICovXG5mdW5jdGlvbiBoYW5kbGU0MDFFcnJvcihcbiAgcmVxdWVzdDogSHR0cFJlcXVlc3Q8dW5rbm93bj4sXG4gIG5leHQ6IEh0dHBIYW5kbGVyRm4sXG4gIGF1dGhTZXJ2aWNlOiBBdXRoU2VydmljZVxuKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8dW5rbm93bj4+IHtcbiAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICBpc1JlZnJlc2hpbmcgPSB0cnVlO1xuICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChudWxsKTtcblxuICAgIHJldHVybiBhdXRoU2VydmljZS5yZWZyZXNoQWNjZXNzVG9rZW4oKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKChyZXNwb25zZSkgPT4ge1xuICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQocmVzcG9uc2UuYWNjZXNzVG9rZW4pO1xuICAgICAgICByZXR1cm4gbmV4dChhZGRBdXRoSGVhZGVyKHJlcXVlc3QsIHJlc3BvbnNlLmFjY2Vzc1Rva2VuKSk7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoKGVycm9yKSA9PiB7XG4gICAgICAgIGF1dGhTZXJ2aWNlLmxvZ291dCgpO1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9KSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvLyBFc3BlcmFyIGEgcXVlIHRlcm1pbmUgZWwgcmVmcmVzY28gZW4gY3Vyc29cbiAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICBmaWx0ZXIoKHRva2VuKTogdG9rZW4gaXMgc3RyaW5nID0+IHRva2VuICE9PSBudWxsKSxcbiAgICB0YWtlKDEpLFxuICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IG5leHQoYWRkQXV0aEhlYWRlcihyZXF1ZXN0LCB0b2tlbikpKVxuICApO1xufVxuIl19
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { VALTECH_AUTH_CONFIG } from './config';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Servicio para persistencia de estado de autenticación en localStorage.
|
|
6
|
+
*/
|
|
7
|
+
export class AuthStorageService {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.config = inject(VALTECH_AUTH_CONFIG);
|
|
10
|
+
const prefix = this.config.storagePrefix || 'valtech_auth_';
|
|
11
|
+
this.keys = {
|
|
12
|
+
ACCESS_TOKEN: `${prefix}access_token`,
|
|
13
|
+
REFRESH_TOKEN: `${prefix}refresh_token`,
|
|
14
|
+
ROLES: `${prefix}roles`,
|
|
15
|
+
PERMISSIONS: `${prefix}permissions`,
|
|
16
|
+
IS_SUPER_ADMIN: `${prefix}is_super_admin`,
|
|
17
|
+
EXPIRES_AT: `${prefix}expires_at`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Guarda el estado completo de autenticación.
|
|
22
|
+
*/
|
|
23
|
+
saveState(state) {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.setItem(this.keys.ACCESS_TOKEN, state.accessToken);
|
|
26
|
+
localStorage.setItem(this.keys.REFRESH_TOKEN, state.refreshToken);
|
|
27
|
+
localStorage.setItem(this.keys.ROLES, JSON.stringify(state.roles));
|
|
28
|
+
localStorage.setItem(this.keys.PERMISSIONS, JSON.stringify(state.permissions));
|
|
29
|
+
localStorage.setItem(this.keys.IS_SUPER_ADMIN, String(state.isSuperAdmin));
|
|
30
|
+
if (state.expiresAt) {
|
|
31
|
+
localStorage.setItem(this.keys.EXPIRES_AT, String(state.expiresAt));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.warn('[ValtechAuth] Error guardando estado en storage:', e);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Carga el estado de autenticación desde storage.
|
|
40
|
+
*/
|
|
41
|
+
loadState() {
|
|
42
|
+
try {
|
|
43
|
+
const accessToken = localStorage.getItem(this.keys.ACCESS_TOKEN);
|
|
44
|
+
const refreshToken = localStorage.getItem(this.keys.REFRESH_TOKEN);
|
|
45
|
+
const rolesJson = localStorage.getItem(this.keys.ROLES);
|
|
46
|
+
const permissionsJson = localStorage.getItem(this.keys.PERMISSIONS);
|
|
47
|
+
const isSuperAdmin = localStorage.getItem(this.keys.IS_SUPER_ADMIN) === 'true';
|
|
48
|
+
const expiresAtStr = localStorage.getItem(this.keys.EXPIRES_AT);
|
|
49
|
+
return {
|
|
50
|
+
accessToken: accessToken || undefined,
|
|
51
|
+
refreshToken: refreshToken || undefined,
|
|
52
|
+
roles: rolesJson ? JSON.parse(rolesJson) : [],
|
|
53
|
+
permissions: permissionsJson ? JSON.parse(permissionsJson) : [],
|
|
54
|
+
isSuperAdmin,
|
|
55
|
+
expiresAt: expiresAtStr ? Number(expiresAtStr) : undefined,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.warn('[ValtechAuth] Error cargando estado desde storage:', e);
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Guarda solo el access token.
|
|
65
|
+
*/
|
|
66
|
+
saveAccessToken(token, expiresAt) {
|
|
67
|
+
try {
|
|
68
|
+
localStorage.setItem(this.keys.ACCESS_TOKEN, token);
|
|
69
|
+
if (expiresAt) {
|
|
70
|
+
localStorage.setItem(this.keys.EXPIRES_AT, String(expiresAt));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
console.warn('[ValtechAuth] Error guardando access token:', e);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Guarda los permisos actualizados.
|
|
79
|
+
*/
|
|
80
|
+
savePermissions(response) {
|
|
81
|
+
try {
|
|
82
|
+
localStorage.setItem(this.keys.ROLES, JSON.stringify(response.roles));
|
|
83
|
+
localStorage.setItem(this.keys.PERMISSIONS, JSON.stringify(response.permissions));
|
|
84
|
+
localStorage.setItem(this.keys.IS_SUPER_ADMIN, String(response.isSuperAdmin));
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.warn('[ValtechAuth] Error guardando permisos:', e);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Carga los permisos desde storage.
|
|
92
|
+
*/
|
|
93
|
+
loadPermissions() {
|
|
94
|
+
try {
|
|
95
|
+
const rolesJson = localStorage.getItem(this.keys.ROLES);
|
|
96
|
+
const permissionsJson = localStorage.getItem(this.keys.PERMISSIONS);
|
|
97
|
+
const isSuperAdmin = localStorage.getItem(this.keys.IS_SUPER_ADMIN) === 'true';
|
|
98
|
+
return {
|
|
99
|
+
roles: rolesJson ? JSON.parse(rolesJson) : [],
|
|
100
|
+
permissions: permissionsJson ? JSON.parse(permissionsJson) : [],
|
|
101
|
+
isSuperAdmin,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return { roles: [], permissions: [], isSuperAdmin: false };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Obtiene el refresh token.
|
|
110
|
+
*/
|
|
111
|
+
getRefreshToken() {
|
|
112
|
+
return localStorage.getItem(this.keys.REFRESH_TOKEN);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Limpia todo el estado de autenticación.
|
|
116
|
+
*/
|
|
117
|
+
clear() {
|
|
118
|
+
try {
|
|
119
|
+
Object.values(this.keys).forEach((key) => localStorage.removeItem(key));
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.warn('[ValtechAuth] Error limpiando storage:', e);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Verifica si hay estado guardado.
|
|
127
|
+
*/
|
|
128
|
+
hasStoredState() {
|
|
129
|
+
return !!localStorage.getItem(this.keys.ACCESS_TOKEN);
|
|
130
|
+
}
|
|
131
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
132
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthStorageService, providedIn: 'root' }); }
|
|
133
|
+
}
|
|
134
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AuthStorageService, decorators: [{
|
|
135
|
+
type: Injectable,
|
|
136
|
+
args: [{ providedIn: 'root' }]
|
|
137
|
+
}], ctorParameters: () => [] });
|
|
138
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9hdXRoL3N0b3JhZ2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxVQUFVLENBQUM7O0FBZS9DOztHQUVHO0FBRUgsTUFBTSxPQUFPLGtCQUFrQjtJQUk3QjtRQUhRLFdBQU0sR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUkzQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsSUFBSSxlQUFlLENBQUM7UUFDNUQsSUFBSSxDQUFDLElBQUksR0FBRztZQUNWLFlBQVksRUFBRSxHQUFHLE1BQU0sY0FBYztZQUNyQyxhQUFhLEVBQUUsR0FBRyxNQUFNLGVBQWU7WUFDdkMsS0FBSyxFQUFFLEdBQUcsTUFBTSxPQUFPO1lBQ3ZCLFdBQVcsRUFBRSxHQUFHLE1BQU0sYUFBYTtZQUNuQyxjQUFjLEVBQUUsR0FBRyxNQUFNLGdCQUFnQjtZQUN6QyxVQUFVLEVBQUUsR0FBRyxNQUFNLFlBQVk7U0FDbEMsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsQ0FBQyxLQUFzQjtRQUM5QixJQUFJLENBQUM7WUFDSCxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRSxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNsRSxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxT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QUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDL0QsWUFBWTthQUNiLENBQUM7UUFDSixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDN0QsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILGVBQWU7UUFDYixPQUFPLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDO1lBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxPQUFPLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzVELENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxjQUFjO1FBQ1osT0FBTyxDQUFDLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ3hELENBQUM7K0dBbkpVLGtCQUFrQjttSEFBbEIsa0JBQWtCLGNBREwsTUFBTTs7NEZBQ25CLGtCQUFrQjtrQkFEOUIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFZBTFRFQ0hfQVVUSF9DT05GSUcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQgeyBTdG9yZWRBdXRoU3RhdGUsIEdldFBlcm1pc3Npb25zUmVzcG9uc2UgfSBmcm9tICcuL3R5cGVzJztcblxuLyoqXG4gKiBDbGF2ZXMgZGUgc3RvcmFnZSBwYXJhIGF1dGVudGljYWNpw7NuLlxuICovXG5pbnRlcmZhY2UgU3RvcmFnZUtleXMge1xuICBBQ0NFU1NfVE9LRU46IHN0cmluZztcbiAgUkVGUkVTSF9UT0tFTjogc3RyaW5nO1xuICBST0xFUzogc3RyaW5nO1xuICBQRVJNSVNTSU9OUzogc3RyaW5nO1xuICBJU19TVVBFUl9BRE1JTjogc3RyaW5nO1xuICBFWFBJUkVTX0FUOiBzdHJpbmc7XG59XG5cbi8qKlxuICogU2VydmljaW8gcGFyYSBwZXJzaXN0ZW5jaWEgZGUgZXN0YWRvIGRlIGF1dGVudGljYWNpw7NuIGVuIGxvY2FsU3RvcmFnZS5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBBdXRoU3RvcmFnZVNlcnZpY2Uge1xuICBwcml2YXRlIGNvbmZpZyA9IGluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKTtcbiAgcHJpdmF0ZSBrZXlzOiBTdG9yYWdlS2V5cztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmNvbmZpZy5zdG9yYWdlUHJlZml4IHx8ICd2YWx0ZWNoX2F1dGhfJztcbiAgICB0aGlzLmtleXMgPSB7XG4gICAgICBBQ0NFU1NfVE9LRU46IGAke3ByZWZpeH1hY2Nlc3NfdG9rZW5gLFxuICAgICAgUkVGUkVTSF9UT0tFTjogYCR7cHJlZml4fXJlZnJlc2hfdG9rZW5gLFxuICAgICAgUk9MRVM6IGAke3ByZWZpeH1yb2xlc2AsXG4gICAgICBQRVJNSVNTSU9OUzogYCR7cHJlZml4fXBlcm1pc3Npb25zYCxcbiAgICAgIElTX1NVUEVSX0FETUlOOiBgJHtwcmVmaXh9aXNfc3VwZXJfYWRtaW5gLFxuICAgICAgRVhQSVJFU19BVDogYCR7cHJlZml4fWV4cGlyZXNfYXRgLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR3VhcmRhIGVsIGVzdGFkbyBjb21wbGV0byBkZSBhdXRlbnRpY2FjacOzbi5cbiAgICovXG4gIHNhdmVTdGF0ZShzdGF0ZTogU3RvcmVkQXV0aFN0YXRlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5cy5BQ0NFU1NfVE9LRU4sIHN0YXRlLmFjY2Vzc1Rva2VuKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5cy5SRUZSRVNIX1RPS0VOLCBzdGF0ZS5yZWZyZXNoVG9rZW4pO1xuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0odGhpcy5rZXlzLlJPTEVTLCBKU09OLnN0cmluZ2lmeShzdGF0ZS5yb2xlcykpO1xuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oXG4gICAgICAgIHRoaXMua2V5cy5QRVJNSVNTSU9OUyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoc3RhdGUucGVybWlzc2lvbnMpXG4gICAgICApO1xuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oXG4gICAgICAgIHRoaXMua2V5cy5JU19TVVBFUl9BRE1JTixcbiAgICAgICAgU3RyaW5nKHN0YXRlLmlzU3VwZXJBZG1pbilcbiAgICAgICk7XG4gICAgICBpZiAoc3RhdGUuZXhwaXJlc0F0KSB7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5cy5FWFBJUkVTX0FULCBTdHJpbmcoc3RhdGUuZXhwaXJlc0F0KSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS53YXJuKCdbVmFsdGVjaEF1dGhdIEVycm9yIGd1YXJkYW5kbyBlc3RhZG8gZW4gc3RvcmFnZTonLCBlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FyZ2EgZWwgZXN0YWRvIGRlIGF1dGVudGljYWNpw7NuIGRlc2RlIHN0b3JhZ2UuXG4gICAqL1xuICBsb2FkU3RhdGUoKTogUGFydGlhbDxTdG9yZWRBdXRoU3RhdGU+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYWNjZXNzVG9rZW4gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmtleXMuQUNDRVNTX1RPS0VOKTtcbiAgICAgIGNvbnN0IHJlZnJlc2hUb2tlbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMua2V5cy5SRUZSRVNIX1RPS0VOKTtcbiAgICAgIGNvbnN0IHJvbGVzSnNvbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMua2V5cy5ST0xFUyk7XG4gICAgICBjb25zdCBwZXJtaXNzaW9uc0pzb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmtleXMuUEVSTUlTU0lPTlMpO1xuICAgICAgY29uc3QgaXNTdXBlckFkbWluID1cbiAgICAgICAgbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5rZXlzLklTX1NVUEVSX0FETUlOKSA9PT0gJ3RydWUnO1xuICAgICAgY29uc3QgZXhwaXJlc0F0U3RyID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5rZXlzLkVYUElSRVNfQVQpO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBhY2Nlc3NUb2tlbjogYWNjZXNzVG9rZW4gfHwgdW5kZWZpbmVkLFxuICAgICAgICByZWZyZXNoVG9rZW46IHJlZnJlc2hUb2tlbiB8fCB1bmRlZmluZWQsXG4gICAgICAgIHJvbGVzOiByb2xlc0pzb24gPyBKU09OLnBhcnNlKHJvbGVzSnNvbikgOiBbXSxcbiAgICAgICAgcGVybWlzc2lvbnM6IHBlcm1pc3Npb25zSnNvbiA/IEpTT04ucGFyc2UocGVybWlzc2lvbnNKc29uKSA6IFtdLFxuICAgICAgICBpc1N1cGVyQWRtaW4sXG4gICAgICAgIGV4cGlyZXNBdDogZXhwaXJlc0F0U3RyID8gTnVtYmVyKGV4cGlyZXNBdFN0cikgOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUud2FybignW1ZhbHRlY2hBdXRoXSBFcnJvciBjYXJnYW5kbyBlc3RhZG8gZGVzZGUgc3RvcmFnZTonLCBlKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR3VhcmRhIHNvbG8gZWwgYWNjZXNzIHRva2VuLlxuICAgKi9cbiAgc2F2ZUFjY2Vzc1Rva2VuKHRva2VuOiBzdHJpbmcsIGV4cGlyZXNBdD86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLmtleXMuQUNDRVNTX1RPS0VOLCB0b2tlbik7XG4gICAgICBpZiAoZXhwaXJlc0F0KSB7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5cy5FWFBJUkVTX0FULCBTdHJpbmcoZXhwaXJlc0F0KSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS53YXJuKCdbVmFsdGVjaEF1dGhdIEVycm9yIGd1YXJkYW5kbyBhY2Nlc3MgdG9rZW46JywgZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEd1YXJkYSBsb3MgcGVybWlzb3MgYWN0dWFsaXphZG9zLlxuICAgKi9cbiAgc2F2ZVBlcm1pc3Npb25zKHJlc3BvbnNlOiBHZXRQZXJtaXNzaW9uc1Jlc3BvbnNlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMua2V5cy5ST0xFUywgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2Uucm9sZXMpKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFxuICAgICAgICB0aGlzLmtleXMuUEVSTUlTU0lPTlMsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLnBlcm1pc3Npb25zKVxuICAgICAgKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFxuICAgICAgICB0aGlzLmtleXMuSVNfU1VQRVJfQURNSU4sXG4gICAgICAgIFN0cmluZyhyZXNwb25zZS5pc1N1cGVyQWRtaW4pXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUud2FybignW1ZhbHRlY2hBdXRoXSBFcnJvciBndWFyZGFuZG8gcGVybWlzb3M6JywgZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhcmdhIGxvcyBwZXJtaXNvcyBkZXNkZSBzdG9yYWdlLlxuICAgKi9cbiAgbG9hZFBlcm1pc3Npb25zKCk6IHtcbiAgICByb2xlczogc3RyaW5nW107XG4gICAgcGVybWlzc2lvbnM6IHN0cmluZ1tdO1xuICAgIGlzU3VwZXJBZG1pbjogYm9vbGVhbjtcbiAgfSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJvbGVzSnNvbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKHRoaXMua2V5cy5ST0xFUyk7XG4gICAgICBjb25zdCBwZXJtaXNzaW9uc0pzb24gPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmtleXMuUEVSTUlTU0lPTlMpO1xuICAgICAgY29uc3QgaXNTdXBlckFkbWluID1cbiAgICAgICAgbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5rZXlzLklTX1NVUEVSX0FETUlOKSA9PT0gJ3RydWUnO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICByb2xlczogcm9sZXNKc29uID8gSlNPTi5wYXJzZShyb2xlc0pzb24pIDogW10sXG4gICAgICAgIHBlcm1pc3Npb25zOiBwZXJtaXNzaW9uc0pzb24gPyBKU09OLnBhcnNlKHBlcm1pc3Npb25zSnNvbikgOiBbXSxcbiAgICAgICAgaXNTdXBlckFkbWluLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB7IHJvbGVzOiBbXSwgcGVybWlzc2lvbnM6IFtdLCBpc1N1cGVyQWRtaW46IGZhbHNlIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgcmVmcmVzaCB0b2tlbi5cbiAgICovXG4gIGdldFJlZnJlc2hUb2tlbigpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5rZXlzLlJFRlJFU0hfVE9LRU4pO1xuICB9XG5cbiAgLyoqXG4gICAqIExpbXBpYSB0b2RvIGVsIGVzdGFkbyBkZSBhdXRlbnRpY2FjacOzbi5cbiAgICovXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBPYmplY3QudmFsdWVzKHRoaXMua2V5cykuZm9yRWFjaCgoa2V5KSA9PiBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1tWYWx0ZWNoQXV0aF0gRXJyb3IgbGltcGlhbmRvIHN0b3JhZ2U6JywgZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNpIGhheSBlc3RhZG8gZ3VhcmRhZG8uXG4gICAqL1xuICBoYXNTdG9yZWRTdGF0ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISFsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmtleXMuQUNDRVNTX1RPS0VOKTtcbiAgfVxufVxuIl19
|