@nauth-toolkit/client-angular 0.1.59 → 0.1.60
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/ngmodule/auth.service.mjs +25 -1
- package/esm2022/standalone/nauth-toolkit-client-angular-standalone.mjs +1 -1
- package/esm2022/standalone/public-api.mjs +6 -10
- package/fesm2022/nauth-toolkit-client-angular-standalone.mjs +5 -1253
- package/fesm2022/nauth-toolkit-client-angular-standalone.mjs.map +1 -1
- package/fesm2022/nauth-toolkit-client-angular.mjs +24 -0
- package/fesm2022/nauth-toolkit-client-angular.mjs.map +1 -1
- package/ngmodule/auth.service.d.ts +23 -1
- package/package.json +2 -2
- package/standalone/public-api.d.ts +4 -7
- package/esm2022/standalone/auth.guard.mjs +0 -102
- package/esm2022/standalone/auth.interceptor.mjs +0 -158
- package/esm2022/standalone/auth.service.mjs +0 -792
- package/esm2022/standalone/http-adapter.mjs +0 -127
- package/esm2022/standalone/social-redirect-callback.guard.mjs +0 -85
- package/esm2022/standalone/tokens.mjs +0 -6
- package/standalone/auth.guard.d.ts +0 -71
- package/standalone/auth.interceptor.d.ts +0 -15
- package/standalone/auth.service.d.ts +0 -593
- package/standalone/http-adapter.d.ts +0 -53
- package/standalone/social-redirect-callback.guard.d.ts +0 -25
- package/standalone/tokens.d.ts +0 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { AngularHttpAdapter } from './http-adapter';
|
|
3
|
-
import { NAuthClient, NAuthClientConfig, ChallengeResponse, AuthResponse, TokenResponse, AuthUser, ConfirmForgotPasswordResponse, ForgotPasswordResponse, UpdateProfileRequest, GetChallengeDataResponse, GetSetupDataResponse, MFAStatus, MFADevice, AuthEvent, SocialProvider, SocialLoginOptions, LinkedAccountsResponse, SocialVerifyRequest, AuditHistoryResponse } from '@nauth-toolkit/client';
|
|
3
|
+
import { NAuthClient, NAuthClientConfig, ChallengeResponse, AuthResponse, TokenResponse, AuthUser, ConfirmForgotPasswordResponse, ForgotPasswordResponse, ResetPasswordWithCodeResponse, UpdateProfileRequest, GetChallengeDataResponse, GetSetupDataResponse, MFAStatus, MFADevice, AuthEvent, SocialProvider, SocialLoginOptions, LinkedAccountsResponse, SocialVerifyRequest, AuditHistoryResponse } from '@nauth-toolkit/client';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
/**
|
|
6
6
|
* Angular wrapper around NAuthClient that provides promise-based auth methods and reactive state.
|
|
@@ -199,6 +199,28 @@ export declare class AuthService {
|
|
|
199
199
|
* ```
|
|
200
200
|
*/
|
|
201
201
|
confirmForgotPassword(identifier: string, code: string, newPassword: string): Promise<ConfirmForgotPasswordResponse>;
|
|
202
|
+
/**
|
|
203
|
+
* Reset password with code or token (generic method for both admin and user-initiated resets).
|
|
204
|
+
*
|
|
205
|
+
* Accepts either:
|
|
206
|
+
* - code: Short numeric code from email/SMS (6-10 digits)
|
|
207
|
+
* - token: Long hex token from reset link (64 chars)
|
|
208
|
+
*
|
|
209
|
+
* @param identifier - User identifier (email, username, phone)
|
|
210
|
+
* @param codeOrToken - Verification code OR token from link
|
|
211
|
+
* @param newPassword - New password
|
|
212
|
+
* @returns Promise with success response
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* // With code from email
|
|
217
|
+
* await this.auth.resetPasswordWithCode('user@example.com', '123456', 'NewPass123!');
|
|
218
|
+
*
|
|
219
|
+
* // With token from link
|
|
220
|
+
* await this.auth.resetPasswordWithCode('user@example.com', '64-char-token', 'NewPass123!');
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
resetPasswordWithCode(identifier: string, codeOrToken: string, newPassword: string): Promise<ResetPasswordWithCodeResponse>;
|
|
202
224
|
/**
|
|
203
225
|
* Change user password (requires current password).
|
|
204
226
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nauth-toolkit/client-angular",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.60",
|
|
4
4
|
"description": "Angular adapter for nauth-toolkit client SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nauth",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"@angular/common": ">=17.0.0",
|
|
26
26
|
"@angular/core": ">=17.0.0",
|
|
27
|
-
"@nauth-toolkit/client": "^0.1.
|
|
27
|
+
"@nauth-toolkit/client": "^0.1.60",
|
|
28
28
|
"rxjs": "^7.0.0 || ^8.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
@@ -3,11 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* This entry point is for standalone component-based Angular apps (Angular 14+).
|
|
5
5
|
* For NgModule apps, use: @nauth-toolkit/client-angular
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This simply re-exports the main entry point since both share the same code for now.
|
|
8
|
+
* The split allows future additions like `provideNAuth()` for standalone apps.
|
|
6
9
|
*/
|
|
7
|
-
export * from '@nauth-toolkit/client';
|
|
8
|
-
export * from './tokens';
|
|
9
|
-
export * from './auth.service';
|
|
10
|
-
export * from './http-adapter';
|
|
11
|
-
export * from './auth.interceptor';
|
|
12
|
-
export * from './auth.guard';
|
|
13
|
-
export * from './social-redirect-callback.guard';
|
|
10
|
+
export * from '@nauth-toolkit/client-angular';
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { __decorate, __param } from "tslib";
|
|
2
|
-
import { inject, Inject, Optional } from '@angular/core';
|
|
3
|
-
import { Router } from '@angular/router';
|
|
4
|
-
import { AuthService } from './auth.service';
|
|
5
|
-
import { NAUTH_CLIENT_CONFIG } from './tokens';
|
|
6
|
-
/**
|
|
7
|
-
* Functional route guard for authentication (Angular 17+).
|
|
8
|
-
*
|
|
9
|
-
* Protects routes by checking if user is authenticated.
|
|
10
|
-
* Redirects to configured session expired route (or login) if not authenticated.
|
|
11
|
-
*
|
|
12
|
-
* @param redirectTo - Optional path to redirect to if not authenticated. If not provided, uses `redirects.sessionExpired` from config (defaults to '/login')
|
|
13
|
-
* @returns CanActivateFn guard function
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* // In route configuration - uses config.redirects.sessionExpired
|
|
18
|
-
* const routes: Routes = [
|
|
19
|
-
* {
|
|
20
|
-
* path: 'home',
|
|
21
|
-
* component: HomeComponent,
|
|
22
|
-
* canActivate: [authGuard()]
|
|
23
|
-
* }
|
|
24
|
-
* ];
|
|
25
|
-
*
|
|
26
|
-
* // Override with custom route
|
|
27
|
-
* const routes: Routes = [
|
|
28
|
-
* {
|
|
29
|
-
* path: 'admin',
|
|
30
|
-
* component: AdminComponent,
|
|
31
|
-
* canActivate: [authGuard('/admin/login')]
|
|
32
|
-
* }
|
|
33
|
-
* ];
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
export function authGuard(redirectTo) {
|
|
37
|
-
return () => {
|
|
38
|
-
const auth = inject(AuthService);
|
|
39
|
-
const router = inject(Router);
|
|
40
|
-
const config = inject(NAUTH_CLIENT_CONFIG, { optional: true });
|
|
41
|
-
if (auth.isAuthenticated()) {
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
// Use provided redirectTo, or config.redirects.sessionExpired, or default to '/login'
|
|
45
|
-
const redirectPath = redirectTo ?? config?.redirects?.sessionExpired ?? '/login';
|
|
46
|
-
return router.createUrlTree([redirectPath]);
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Class-based authentication guard for NgModule compatibility.
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* ```typescript
|
|
54
|
-
* // In route configuration (NgModule)
|
|
55
|
-
* const routes: Routes = [
|
|
56
|
-
* {
|
|
57
|
-
* path: 'home',
|
|
58
|
-
* component: HomeComponent,
|
|
59
|
-
* canActivate: [AuthGuard]
|
|
60
|
-
* }
|
|
61
|
-
* ];
|
|
62
|
-
*
|
|
63
|
-
* // In module providers
|
|
64
|
-
* @NgModule({
|
|
65
|
-
* providers: [AuthGuard]
|
|
66
|
-
* })
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
let AuthGuard = class AuthGuard {
|
|
70
|
-
auth;
|
|
71
|
-
router;
|
|
72
|
-
config;
|
|
73
|
-
/**
|
|
74
|
-
* @param auth - Authentication service
|
|
75
|
-
* @param router - Angular router
|
|
76
|
-
* @param config - Optional client configuration (injected automatically)
|
|
77
|
-
*/
|
|
78
|
-
constructor(auth, router, config) {
|
|
79
|
-
this.auth = auth;
|
|
80
|
-
this.router = router;
|
|
81
|
-
this.config = config;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Check if route can be activated.
|
|
85
|
-
*
|
|
86
|
-
* @returns True if authenticated, otherwise redirects to configured session expired route (or '/login')
|
|
87
|
-
*/
|
|
88
|
-
canActivate() {
|
|
89
|
-
if (this.auth.isAuthenticated()) {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
// Use config.redirects.sessionExpired or default to '/login'
|
|
93
|
-
const redirectPath = this.config?.redirects?.sessionExpired ?? '/login';
|
|
94
|
-
return this.router.createUrlTree([redirectPath]);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
AuthGuard = __decorate([
|
|
98
|
-
__param(2, Optional()),
|
|
99
|
-
__param(2, Inject(NAUTH_CLIENT_CONFIG))
|
|
100
|
-
], AuthGuard);
|
|
101
|
-
export { AuthGuard };
|
|
102
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5ndWFyZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3N0YW5kYWxvbmUvYXV0aC5ndWFyZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBaUIsTUFBTSxFQUFXLE1BQU0saUJBQWlCLENBQUM7QUFDakUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUcvQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLFVBQW1CO0lBQzNDLE9BQU8sR0FBc0IsRUFBRTtRQUM3QixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDakMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRS9ELElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUM7WUFDM0IsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsc0ZBQXNGO1FBQ3RGLE1BQU0sWUFBWSxHQUNoQixVQUFVLElBQUksTUFBTSxFQUFFLFNBQVMsRUFBRSxjQUFjLElBQUksUUFBUSxDQUFDO1FBRTlELE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7SUFDOUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0ksSUFBTSxTQUFTLEdBQWYsTUFBTSxTQUFTO0lBT1Y7SUFDQTtJQUN5QztJQVJuRDs7OztPQUlHO0lBQ0gsWUFDVSxJQUFpQixFQUNqQixNQUFjLEVBQzJCLE1BQTBCO1FBRm5FLFNBQUksR0FBSixJQUFJLENBQWE7UUFDakIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUMyQixXQUFNLEdBQU4sTUFBTSxDQUFvQjtJQUMxRSxDQUFDO0lBRUo7Ozs7T0FJRztJQUNILFdBQVc7UUFDVCxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztZQUNoQyxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCw2REFBNkQ7UUFDN0QsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsY0FBYyxJQUFJLFFBQVEsQ0FBQztRQUV4RSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO0NBQ0YsQ0FBQTtBQTNCWSxTQUFTO0lBU2pCLFdBQUEsUUFBUSxFQUFFLENBQUE7SUFBRSxXQUFBLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO0dBVC9CLFNBQVMsQ0EyQnJCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3QsIE9wdGlvbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDYW5BY3RpdmF0ZUZuLCBSb3V0ZXIsIFVybFRyZWUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBOQVVUSF9DTElFTlRfQ09ORklHIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHR5cGUgeyBOQXV0aENsaWVudENvbmZpZyB9IGZyb20gJ0BuYXV0aC10b29sa2l0L2NsaWVudCc7XG5cbi8qKlxuICogRnVuY3Rpb25hbCByb3V0ZSBndWFyZCBmb3IgYXV0aGVudGljYXRpb24gKEFuZ3VsYXIgMTcrKS5cbiAqXG4gKiBQcm90ZWN0cyByb3V0ZXMgYnkgY2hlY2tpbmcgaWYgdXNlciBpcyBhdXRoZW50aWNhdGVkLlxuICogUmVkaXJlY3RzIHRvIGNvbmZpZ3VyZWQgc2Vzc2lvbiBleHBpcmVkIHJvdXRlIChvciBsb2dpbikgaWYgbm90IGF1dGhlbnRpY2F0ZWQuXG4gKlxuICogQHBhcmFtIHJlZGlyZWN0VG8gLSBPcHRpb25hbCBwYXRoIHRvIHJlZGlyZWN0IHRvIGlmIG5vdCBhdXRoZW50aWNhdGVkLiBJZiBub3QgcHJvdmlkZWQsIHVzZXMgYHJlZGlyZWN0cy5zZXNzaW9uRXhwaXJlZGAgZnJvbSBjb25maWcgKGRlZmF1bHRzIHRvICcvbG9naW4nKVxuICogQHJldHVybnMgQ2FuQWN0aXZhdGVGbiBndWFyZCBmdW5jdGlvblxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBJbiByb3V0ZSBjb25maWd1cmF0aW9uIC0gdXNlcyBjb25maWcucmVkaXJlY3RzLnNlc3Npb25FeHBpcmVkXG4gKiBjb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAqICAge1xuICogICAgIHBhdGg6ICdob21lJyxcbiAqICAgICBjb21wb25lbnQ6IEhvbWVDb21wb25lbnQsXG4gKiAgICAgY2FuQWN0aXZhdGU6IFthdXRoR3VhcmQoKV1cbiAqICAgfVxuICogXTtcbiAqXG4gKiAvLyBPdmVycmlkZSB3aXRoIGN1c3RvbSByb3V0ZVxuICogY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gKiAgIHtcbiAqICAgICBwYXRoOiAnYWRtaW4nLFxuICogICAgIGNvbXBvbmVudDogQWRtaW5Db21wb25lbnQsXG4gKiAgICAgY2FuQWN0aXZhdGU6IFthdXRoR3VhcmQoJy9hZG1pbi9sb2dpbicpXVxuICogICB9XG4gKiBdO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdXRoR3VhcmQocmVkaXJlY3RUbz86IHN0cmluZyk6IENhbkFjdGl2YXRlRm4ge1xuICByZXR1cm4gKCk6IGJvb2xlYW4gfCBVcmxUcmVlID0+IHtcbiAgICBjb25zdCBhdXRoID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgICBjb25zdCByb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgICBjb25zdCBjb25maWcgPSBpbmplY3QoTkFVVEhfQ0xJRU5UX0NPTkZJRywgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAgIGlmIChhdXRoLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBVc2UgcHJvdmlkZWQgcmVkaXJlY3RUbywgb3IgY29uZmlnLnJlZGlyZWN0cy5zZXNzaW9uRXhwaXJlZCwgb3IgZGVmYXVsdCB0byAnL2xvZ2luJ1xuICAgIGNvbnN0IHJlZGlyZWN0UGF0aCA9XG4gICAgICByZWRpcmVjdFRvID8/IGNvbmZpZz8ucmVkaXJlY3RzPy5zZXNzaW9uRXhwaXJlZCA/PyAnL2xvZ2luJztcblxuICAgIHJldHVybiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbcmVkaXJlY3RQYXRoXSk7XG4gIH07XG59XG5cbi8qKlxuICogQ2xhc3MtYmFzZWQgYXV0aGVudGljYXRpb24gZ3VhcmQgZm9yIE5nTW9kdWxlIGNvbXBhdGliaWxpdHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEluIHJvdXRlIGNvbmZpZ3VyYXRpb24gKE5nTW9kdWxlKVxuICogY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gKiAgIHtcbiAqICAgICBwYXRoOiAnaG9tZScsXG4gKiAgICAgY29tcG9uZW50OiBIb21lQ29tcG9uZW50LFxuICogICAgIGNhbkFjdGl2YXRlOiBbQXV0aEd1YXJkXVxuICogICB9XG4gKiBdO1xuICpcbiAqIC8vIEluIG1vZHVsZSBwcm92aWRlcnNcbiAqIEBOZ01vZHVsZSh7XG4gKiAgIHByb3ZpZGVyczogW0F1dGhHdWFyZF1cbiAqIH0pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhHdWFyZCB7XG4gIC8qKlxuICAgKiBAcGFyYW0gYXV0aCAtIEF1dGhlbnRpY2F0aW9uIHNlcnZpY2VcbiAgICogQHBhcmFtIHJvdXRlciAtIEFuZ3VsYXIgcm91dGVyXG4gICAqIEBwYXJhbSBjb25maWcgLSBPcHRpb25hbCBjbGllbnQgY29uZmlndXJhdGlvbiAoaW5qZWN0ZWQgYXV0b21hdGljYWxseSlcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYXV0aDogQXV0aFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KE5BVVRIX0NMSUVOVF9DT05GSUcpIHByaXZhdGUgY29uZmlnPzogTkF1dGhDbGllbnRDb25maWcsXG4gICkge31cblxuICAvKipcbiAgICogQ2hlY2sgaWYgcm91dGUgY2FuIGJlIGFjdGl2YXRlZC5cbiAgICpcbiAgICogQHJldHVybnMgVHJ1ZSBpZiBhdXRoZW50aWNhdGVkLCBvdGhlcndpc2UgcmVkaXJlY3RzIHRvIGNvbmZpZ3VyZWQgc2Vzc2lvbiBleHBpcmVkIHJvdXRlIChvciAnL2xvZ2luJylcbiAgICovXG4gIGNhbkFjdGl2YXRlKCk6IGJvb2xlYW4gfCBVcmxUcmVlIHtcbiAgICBpZiAodGhpcy5hdXRoLmlzQXV0aGVudGljYXRlZCgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBVc2UgY29uZmlnLnJlZGlyZWN0cy5zZXNzaW9uRXhwaXJlZCBvciBkZWZhdWx0IHRvICcvbG9naW4nXG4gICAgY29uc3QgcmVkaXJlY3RQYXRoID0gdGhpcy5jb25maWc/LnJlZGlyZWN0cz8uc2Vzc2lvbkV4cGlyZWQgPz8gJy9sb2dpbic7XG5cbiAgICByZXR1cm4gdGhpcy5yb3V0ZXIuY3JlYXRlVXJsVHJlZShbcmVkaXJlY3RQYXRoXSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { inject, PLATFORM_ID } from '@angular/core';
|
|
2
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
3
|
-
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
4
|
-
import { Router } from '@angular/router';
|
|
5
|
-
import { catchError, switchMap, throwError, filter, take, BehaviorSubject, from } from 'rxjs';
|
|
6
|
-
import { NAUTH_CLIENT_CONFIG } from './tokens';
|
|
7
|
-
import { AuthService } from './auth.service';
|
|
8
|
-
/**
|
|
9
|
-
* Refresh state management.
|
|
10
|
-
* BehaviorSubject pattern is the industry-standard for token refresh.
|
|
11
|
-
*/
|
|
12
|
-
let isRefreshing = false;
|
|
13
|
-
const refreshTokenSubject = new BehaviorSubject(null);
|
|
14
|
-
/**
|
|
15
|
-
* Track retried requests to prevent infinite loops.
|
|
16
|
-
*/
|
|
17
|
-
const retriedRequests = new WeakSet();
|
|
18
|
-
/**
|
|
19
|
-
* Get CSRF token from cookie.
|
|
20
|
-
*/
|
|
21
|
-
function getCsrfToken(cookieName) {
|
|
22
|
-
if (typeof document === 'undefined')
|
|
23
|
-
return null;
|
|
24
|
-
const match = document.cookie.match(new RegExp(`(^| )${cookieName}=([^;]+)`));
|
|
25
|
-
return match ? decodeURIComponent(match[2]) : null;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Angular HTTP interceptor for nauth-toolkit.
|
|
29
|
-
*
|
|
30
|
-
* Handles:
|
|
31
|
-
* - Cookies mode: withCredentials + CSRF tokens + refresh via POST
|
|
32
|
-
* - JSON mode: refresh via SDK, retry with new token
|
|
33
|
-
*/
|
|
34
|
-
export const authInterceptor = (req, next) => {
|
|
35
|
-
const config = inject(NAUTH_CLIENT_CONFIG);
|
|
36
|
-
const http = inject(HttpClient);
|
|
37
|
-
const authService = inject(AuthService);
|
|
38
|
-
const platformId = inject(PLATFORM_ID);
|
|
39
|
-
const router = inject(Router);
|
|
40
|
-
const isBrowser = isPlatformBrowser(platformId);
|
|
41
|
-
if (!isBrowser) {
|
|
42
|
-
return next(req);
|
|
43
|
-
}
|
|
44
|
-
const tokenDelivery = config.tokenDelivery;
|
|
45
|
-
const baseUrl = config.baseUrl;
|
|
46
|
-
const endpoints = config.endpoints ?? {};
|
|
47
|
-
const refreshPath = endpoints.refresh ?? '/refresh';
|
|
48
|
-
const loginPath = endpoints.login ?? '/login';
|
|
49
|
-
const signupPath = endpoints.signup ?? '/signup';
|
|
50
|
-
const socialExchangePath = endpoints.socialExchange ?? '/social/exchange';
|
|
51
|
-
const refreshUrl = `${baseUrl}${refreshPath}`;
|
|
52
|
-
const isAuthApiRequest = req.url.includes(baseUrl);
|
|
53
|
-
const isRefreshEndpoint = req.url.includes(refreshPath);
|
|
54
|
-
const isPublicEndpoint = req.url.includes(loginPath) || req.url.includes(signupPath) || req.url.includes(socialExchangePath);
|
|
55
|
-
// Build request with credentials (cookies mode only)
|
|
56
|
-
let authReq = req;
|
|
57
|
-
if (tokenDelivery === 'cookies') {
|
|
58
|
-
authReq = authReq.clone({ withCredentials: true });
|
|
59
|
-
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
|
|
60
|
-
const csrfCookieName = config.csrf?.cookieName ?? 'nauth_csrf_token';
|
|
61
|
-
const csrfHeaderName = config.csrf?.headerName ?? 'x-csrf-token';
|
|
62
|
-
const csrfToken = getCsrfToken(csrfCookieName);
|
|
63
|
-
if (csrfToken) {
|
|
64
|
-
authReq = authReq.clone({ setHeaders: { [csrfHeaderName]: csrfToken } });
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return next(authReq).pipe(catchError((error) => {
|
|
69
|
-
const shouldHandle = error instanceof HttpErrorResponse &&
|
|
70
|
-
error.status === 401 &&
|
|
71
|
-
isAuthApiRequest &&
|
|
72
|
-
!isRefreshEndpoint &&
|
|
73
|
-
!isPublicEndpoint &&
|
|
74
|
-
!retriedRequests.has(req);
|
|
75
|
-
if (!shouldHandle) {
|
|
76
|
-
return throwError(() => error);
|
|
77
|
-
}
|
|
78
|
-
if (config.debug) {
|
|
79
|
-
console.warn('[nauth-interceptor] 401 detected:', req.url);
|
|
80
|
-
}
|
|
81
|
-
if (!isRefreshing) {
|
|
82
|
-
isRefreshing = true;
|
|
83
|
-
refreshTokenSubject.next(null);
|
|
84
|
-
if (config.debug) {
|
|
85
|
-
console.warn('[nauth-interceptor] Starting refresh...');
|
|
86
|
-
}
|
|
87
|
-
// Refresh based on mode
|
|
88
|
-
const refresh$ = tokenDelivery === 'cookies'
|
|
89
|
-
? http.post(refreshUrl, {}, { withCredentials: true })
|
|
90
|
-
: from(authService.refresh());
|
|
91
|
-
return refresh$.pipe(switchMap((response) => {
|
|
92
|
-
if (config.debug) {
|
|
93
|
-
console.warn('[nauth-interceptor] Refresh successful');
|
|
94
|
-
}
|
|
95
|
-
isRefreshing = false;
|
|
96
|
-
// Get new token (JSON mode) or signal success (cookies mode)
|
|
97
|
-
const newToken = 'accessToken' in response ? response.accessToken : 'success';
|
|
98
|
-
refreshTokenSubject.next(newToken ?? 'success');
|
|
99
|
-
// Build retry request
|
|
100
|
-
const retryReq = buildRetryRequest(authReq, tokenDelivery, newToken);
|
|
101
|
-
retriedRequests.add(retryReq);
|
|
102
|
-
if (config.debug) {
|
|
103
|
-
console.warn('[nauth-interceptor] Retrying:', req.url);
|
|
104
|
-
}
|
|
105
|
-
return next(retryReq);
|
|
106
|
-
}), catchError((err) => {
|
|
107
|
-
if (config.debug) {
|
|
108
|
-
console.error('[nauth-interceptor] Refresh failed:', err);
|
|
109
|
-
}
|
|
110
|
-
isRefreshing = false;
|
|
111
|
-
refreshTokenSubject.next(null);
|
|
112
|
-
// Handle session expiration - redirect to configured URL
|
|
113
|
-
if (config.redirects?.sessionExpired) {
|
|
114
|
-
router.navigateByUrl(config.redirects.sessionExpired).catch((navError) => {
|
|
115
|
-
if (config.debug) {
|
|
116
|
-
console.error('[nauth-interceptor] Navigation failed:', navError);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
return throwError(() => err);
|
|
121
|
-
}));
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
// Wait for ongoing refresh
|
|
125
|
-
if (config.debug) {
|
|
126
|
-
console.warn('[nauth-interceptor] Waiting for refresh...');
|
|
127
|
-
}
|
|
128
|
-
return refreshTokenSubject.pipe(filter((token) => token !== null), take(1), switchMap((token) => {
|
|
129
|
-
if (config.debug) {
|
|
130
|
-
console.warn('[nauth-interceptor] Refresh done, retrying:', req.url);
|
|
131
|
-
}
|
|
132
|
-
const retryReq = buildRetryRequest(authReq, tokenDelivery, token);
|
|
133
|
-
retriedRequests.add(retryReq);
|
|
134
|
-
return next(retryReq);
|
|
135
|
-
}));
|
|
136
|
-
}
|
|
137
|
-
}));
|
|
138
|
-
};
|
|
139
|
-
/**
|
|
140
|
-
* Build retry request with appropriate auth.
|
|
141
|
-
*/
|
|
142
|
-
function buildRetryRequest(originalReq, tokenDelivery, newToken) {
|
|
143
|
-
if (tokenDelivery === 'json' && newToken && newToken !== 'success') {
|
|
144
|
-
return originalReq.clone({
|
|
145
|
-
setHeaders: { Authorization: `Bearer ${newToken}` },
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
return originalReq.clone();
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Class-based interceptor for NgModule compatibility.
|
|
152
|
-
*/
|
|
153
|
-
export class AuthInterceptor {
|
|
154
|
-
intercept(req, next) {
|
|
155
|
-
return authInterceptor(req, next);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5pbnRlcmNlcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3N0YW5kYWxvbmUvYXV0aC5pbnRlcmNlcHRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQWlELFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzlGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0M7OztHQUdHO0FBQ0gsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQ3pCLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxlQUFlLENBQWdCLElBQUksQ0FBQyxDQUFDO0FBRXJFOztHQUVHO0FBQ0gsTUFBTSxlQUFlLEdBQUcsSUFBSSxPQUFPLEVBQXdCLENBQUM7QUFFNUQ7O0dBRUc7QUFDSCxTQUFTLFlBQVksQ0FBQyxVQUFrQjtJQUN0QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFdBQVc7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNqRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLFVBQVUsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUM5RSxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsa0JBQWtCLENBQUMsS0FBSyxD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SSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDbkUsT0FBTyxXQUFXLENBQUMsS0FBSyxDQUFDO1lBQ3ZCLFVBQVUsRUFBRSxFQUFFLGFBQWEsRUFBRSxVQUFVLFFBQVEsRUFBRSxFQUFFO1NBQ3BELENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztBQUM3QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUMxQixTQUFTLENBQUMsR0FBeUIsRUFBRSxJQUFtQjtRQUN0RCxPQUFPLGVBQWUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBQTEFURk9STV9JRCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSHR0cEhhbmRsZXJGbiwgSHR0cEludGVyY2VwdG9yRm4sIEh0dHBSZXF1ZXN0LCBIdHRwQ2xpZW50LCBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBzd2l0Y2hNYXAsIHRocm93RXJyb3IsIGZpbHRlciwgdGFrZSwgQmVoYXZpb3JTdWJqZWN0LCBmcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBOQVVUSF9DTElFTlRfQ09ORklHIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuL2F1dGguc2VydmljZSc7XG5cbi8qKlxuICogUmVmcmVzaCBzdGF0ZSBtYW5hZ2VtZW50LlxuICogQmVoYXZpb3JTdWJqZWN0IHBhdHRlcm4gaXMgdGhlIGluZHVzdHJ5LXN0YW5kYXJkIGZvciB0b2tlbiByZWZyZXNoLlxuICovXG5sZXQgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG5jb25zdCByZWZyZXNoVG9rZW5TdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuLyoqXG4gKiBUcmFjayByZXRyaWVkIHJlcXVlc3RzIHRvIHByZXZlbnQgaW5maW5pdGUgbG9vcHMuXG4gKi9cbmNvbnN0IHJldHJpZWRSZXF1ZXN0cyA9IG5ldyBXZWFrU2V0PEh0dHBSZXF1ZXN0PHVua25vd24+PigpO1xuXG4vKipcbiAqIEdldCBDU1JGIHRva2VuIGZyb20gY29va2llLlxuICovXG5mdW5jdGlvbiBnZXRDc3JmVG9rZW4oY29va2llTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgZG9jdW1lbnQgPT09ICd1bmRlZmluZWQnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cChgKF58ICkke2Nvb2tpZU5hbWV9PShbXjtdKylgKSk7XG4gIHJldHVybiBtYXRjaCA/IGRlY29kZVVSSUNvbXBvbmVudChtYXRjaFsyXSkgOiBudWxsO1xufVxuXG4vKipcbiAqIEFuZ3VsYXIgSFRUUCBpbnRlcmNlcHRvciBmb3IgbmF1dGgtdG9vbGtpdC5cbiAqXG4gKiBIYW5kbGVzOlxuICogLSBDb29raWVzIG1vZGU6IHdpdGhDcmVkZW50aWFscyArIENTUkYgdG9rZW5zICsgcmVmcmVzaCB2aWEgUE9TVFxuICogLSBKU09OIG1vZGU6IHJlZnJlc2ggdmlhIFNESywgcmV0cnkgd2l0aCBuZXcgdG9rZW5cbiAqL1xuZXhwb3J0IGNvbnN0IGF1dGhJbnRlcmNlcHRvcjogSHR0cEludGVyY2VwdG9yRm4gPSAocmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXJGbikgPT4ge1xuICBjb25zdCBjb25maWcgPSBpbmplY3QoTkFVVEhfQ0xJRU5UX0NPTkZJRyk7XG4gIGNvbnN0IGh0dHAgPSBpbmplY3QoSHR0cENsaWVudCk7XG4gIGNvbnN0IGF1dGhTZXJ2aWNlID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTtcbiAgY29uc3QgcGxhdGZvcm1JZCA9IGluamVjdChQTEFURk9STV9JRCk7XG4gIGNvbnN0IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICBjb25zdCBpc0Jyb3dzZXIgPSBpc1BsYXRmb3JtQnJvd3NlcihwbGF0Zm9ybUlkKTtcblxuICBpZiAoIWlzQnJvd3Nlcikge1xuICAgIHJldHVybiBuZXh0KHJlcSk7XG4gIH1cblxuICBjb25zdCB0b2tlbkRlbGl2ZXJ5ID0gY29uZmlnLnRva2VuRGVsaXZlcnk7XG4gIGNvbnN0IGJhc2VVcmwgPSBjb25maWcuYmFzZVVybDtcbiAgY29uc3QgZW5kcG9pbnRzID0gY29uZmlnLmVuZHBvaW50cyA/PyB7fTtcbiAgY29uc3QgcmVmcmVzaFBhdGggPSBlbmRwb2ludHMucmVmcmVzaCA/PyAnL3JlZnJlc2gnO1xuICBjb25zdCBsb2dpblBhdGggPSBlbmRwb2ludHMubG9naW4gPz8gJy9sb2dpbic7XG4gIGNvbnN0IHNpZ251cFBhdGggPSBlbmRwb2ludHMuc2lnbnVwID8/ICcvc2lnbnVwJztcbiAgY29uc3Qgc29jaWFsRXhjaGFuZ2VQYXRoID0gZW5kcG9pbnRzLnNvY2lhbEV4Y2hhbmdlID8/ICcvc29jaWFsL2V4Y2hhbmdlJztcbiAgY29uc3QgcmVmcmVzaFVybCA9IGAke2Jhc2VVcmx9JHtyZWZyZXNoUGF0aH1gO1xuXG4gIGNvbnN0IGlzQXV0aEFwaVJlcXVlc3QgPSByZXEudXJsLmluY2x1ZGVzKGJhc2VVcmwpO1xuICBjb25zdCBpc1JlZnJlc2hFbmRwb2ludCA9IHJlcS51cmwuaW5jbHVkZXMocmVmcmVzaFBhdGgpO1xuICBjb25zdCBpc1B1YmxpY0VuZHBvaW50ID1cbiAgICByZXEudXJsLmluY2x1ZGVzKGxvZ2luUGF0aCkgfHwgcmVxLnVybC5pbmNsdWRlcyhzaWdudXBQYXRoKSB8fCByZXEudXJsLmluY2x1ZGVzKHNvY2lhbEV4Y2hhbmdlUGF0aCk7XG5cbiAgLy8gQnVpbGQgcmVxdWVzdCB3aXRoIGNyZWRlbnRpYWxzIChjb29raWVzIG1vZGUgb25seSlcbiAgbGV0IGF1dGhSZXEgPSByZXE7XG4gIGlmICh0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcycpIHtcbiAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHdpdGhDcmVkZW50aWFsczogdHJ1ZSB9KTtcblxuICAgIGlmIChbJ1BPU1QnLCAnUFVUJywgJ1BBVENIJywgJ0RFTEVURSddLmluY2x1ZGVzKHJlcS5tZXRob2QpKSB7XG4gICAgICBjb25zdCBjc3JmQ29va2llTmFtZSA9IGNvbmZpZy5jc3JmPy5jb29raWVOYW1lID8/ICduYXV0aF9jc3JmX3Rva2VuJztcbiAgICAgIGNvbnN0IGNzcmZIZWFkZXJOYW1lID0gY29uZmlnLmNzcmY/LmhlYWRlck5hbWUgPz8gJ3gtY3NyZi10b2tlbic7XG4gICAgICBjb25zdCBjc3JmVG9rZW4gPSBnZXRDc3JmVG9rZW4oY3NyZkNvb2tpZU5hbWUpO1xuICAgICAgaWYgKGNzcmZUb2tlbikge1xuICAgICAgICBhdXRoUmVxID0gYXV0aFJlcS5jbG9uZSh7IHNldEhlYWRlcnM6IHsgW2NzcmZIZWFkZXJOYW1lXTogY3NyZlRva2VuIH0gfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5leHQoYXV0aFJlcSkucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgY29uc3Qgc2hvdWxkSGFuZGxlID1cbiAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSAmJlxuICAgICAgICBlcnJvci5zdGF0dXMgPT09IDQwMSAmJlxuICAgICAgICBpc0F1dGhBcGlSZXF1ZXN0ICYmXG4gICAgICAgICFpc1JlZnJlc2hFbmRwb2ludCAmJlxuICAgICAgICAhaXNQdWJsaWNFbmRwb2ludCAmJlxuICAgICAgICAhcmV0cmllZFJlcXVlc3RzLmhhcyhyZXEpO1xuXG4gICAgICBpZiAoIXNob3VsZEhhbmRsZSkge1xuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIDQwMSBkZXRlY3RlZDonLCByZXEudXJsKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc1JlZnJlc2hpbmcpIHtcbiAgICAgICAgaXNSZWZyZXNoaW5nID0gdHJ1ZTtcbiAgICAgICAgcmVmcmVzaFRva2VuU3ViamVjdC5uZXh0KG51bGwpO1xuXG4gICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tuYXV0aC1pbnRlcmNlcHRvcl0gU3RhcnRpbmcgcmVmcmVzaC4uLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmcmVzaCBiYXNlZCBvbiBtb2RlXG4gICAgICAgIGNvbnN0IHJlZnJlc2gkID1cbiAgICAgICAgICB0b2tlbkRlbGl2ZXJ5ID09PSAnY29va2llcydcbiAgICAgICAgICAgID8gaHR0cC5wb3N0PHsgYWNjZXNzVG9rZW4/OiBzdHJpbmcgfT4ocmVmcmVzaFVybCwge30sIHsgd2l0aENyZWRlbnRpYWxzOiB0cnVlIH0pXG4gICAgICAgICAgICA6IGZyb20oYXV0aFNlcnZpY2UucmVmcmVzaCgpKTtcblxuICAgICAgICByZXR1cm4gcmVmcmVzaCQucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIHN1Y2Nlc3NmdWwnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlzUmVmcmVzaGluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBHZXQgbmV3IHRva2VuIChKU09OIG1vZGUpIG9yIHNpZ25hbCBzdWNjZXNzIChjb29raWVzIG1vZGUpXG4gICAgICAgICAgICBjb25zdCBuZXdUb2tlbiA9ICdhY2Nlc3NUb2tlbicgaW4gcmVzcG9uc2UgPyByZXNwb25zZS5hY2Nlc3NUb2tlbiA6ICdzdWNjZXNzJztcbiAgICAgICAgICAgIHJlZnJlc2hUb2tlblN1YmplY3QubmV4dChuZXdUb2tlbiA/PyAnc3VjY2VzcycpO1xuXG4gICAgICAgICAgICAvLyBCdWlsZCByZXRyeSByZXF1ZXN0XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIG5ld1Rva2VuKTtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmV0cnlSZXEpO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBSZXRyeWluZzonLCByZXEudXJsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXh0KHJldHJ5UmVxKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBjYXRjaEVycm9yKChlcnIpID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignW25hdXRoLWludGVyY2VwdG9yXSBSZWZyZXNoIGZhaWxlZDonLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaXNSZWZyZXNoaW5nID0gZmFsc2U7XG4gICAgICAgICAgICByZWZyZXNoVG9rZW5TdWJqZWN0Lm5leHQobnVsbCk7XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBzZXNzaW9uIGV4cGlyYXRpb24gLSByZWRpcmVjdCB0byBjb25maWd1cmVkIFVSTFxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZWRpcmVjdHM/LnNlc3Npb25FeHBpcmVkKSB7XG4gICAgICAgICAgICAgIHJvdXRlci5uYXZpZ2F0ZUJ5VXJsKGNvbmZpZy5yZWRpcmVjdHMuc2Vzc2lvbkV4cGlyZWQpLmNhdGNoKChuYXZFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1tuYXV0aC1pbnRlcmNlcHRvcl0gTmF2aWdhdGlvbiBmYWlsZWQ6JywgbmF2RXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycik7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXYWl0IGZvciBvbmdvaW5nIHJlZnJlc2hcbiAgICAgICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgICAgIGNvbnNvbGUud2FybignW25hdXRoLWludGVyY2VwdG9yXSBXYWl0aW5nIGZvciByZWZyZXNoLi4uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlZnJlc2hUb2tlblN1YmplY3QucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKHRva2VuKTogdG9rZW4gaXMgc3RyaW5nID0+IHRva2VuICE9PSBudWxsKSxcbiAgICAgICAgICB0YWtlKDEpLFxuICAgICAgICAgIHN3aXRjaE1hcCgodG9rZW4pID0+IHtcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVidWcpIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdbbmF1dGgtaW50ZXJjZXB0b3JdIFJlZnJlc2ggZG9uZSwgcmV0cnlpbmc6JywgcmVxLnVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyeVJlcSA9IGJ1aWxkUmV0cnlSZXF1ZXN0KGF1dGhSZXEsIHRva2VuRGVsaXZlcnksIHRva2VuKTtcbiAgICAgICAgICAgIHJldHJpZWRSZXF1ZXN0cy5hZGQocmV0cnlSZXEpO1xuICAgICAgICAgICAgcmV0dXJuIG5leHQocmV0cnlSZXEpO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pLFxuICApO1xufTtcblxuLyoqXG4gKiBCdWlsZCByZXRyeSByZXF1ZXN0IHdpdGggYXBwcm9wcmlhdGUgYXV0aC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRSZXRyeVJlcXVlc3QoXG4gIG9yaWdpbmFsUmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPixcbiAgdG9rZW5EZWxpdmVyeTogc3RyaW5nLFxuICBuZXdUb2tlbj86IHN0cmluZyxcbik6IEh0dHBSZXF1ZXN0PHVua25vd24+IHtcbiAgaWYgKHRva2VuRGVsaXZlcnkgPT09ICdqc29uJyAmJiBuZXdUb2tlbiAmJiBuZXdUb2tlbiAhPT0gJ3N1Y2Nlc3MnKSB7XG4gICAgcmV0dXJuIG9yaWdpbmFsUmVxLmNsb25lKHtcbiAgICAgIHNldEhlYWRlcnM6IHsgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke25ld1Rva2VufWAgfSxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gb3JpZ2luYWxSZXEuY2xvbmUoKTtcbn1cblxuLyoqXG4gKiBDbGFzcy1iYXNlZCBpbnRlcmNlcHRvciBmb3IgTmdNb2R1bGUgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciB7XG4gIGludGVyY2VwdChyZXE6IEh0dHBSZXF1ZXN0PHVua25vd24+LCBuZXh0OiBIdHRwSGFuZGxlckZuKSB7XG4gICAgcmV0dXJuIGF1dGhJbnRlcmNlcHRvcihyZXEsIG5leHQpO1xuICB9XG59XG4iXX0=
|