@rolatech/angular-auth 20.2.9-beta.7 → 20.3.0-beta.3

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.
@@ -1,35 +1,35 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, signal, computed, Injectable, inject, output, model, PLATFORM_ID, InjectionToken, makeEnvironmentProviders } from '@angular/core';
2
+ import { Component, signal, computed, Injectable, inject, output, model, PLATFORM_ID, InjectionToken, APP_INITIALIZER, makeEnvironmentProviders } from '@angular/core';
3
3
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
4
4
  import { APP_CONFIG, AngularCommonModule } from '@rolatech/angular-common';
5
5
  import { SnackBarService } from '@rolatech/angular-services';
6
6
  import QRCode from 'qrcode';
7
7
  import { MatButtonModule } from '@angular/material/button';
8
8
  import { HttpClient, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
9
- import { map, tap, filter, catchError as catchError$1 } from 'rxjs/operators';
10
- import { ActivatedRoute, Router } from '@angular/router';
9
+ import { of, forkJoin, throwError, map as map$1, BehaviorSubject, catchError as catchError$1, NEVER, firstValueFrom } from 'rxjs';
10
+ import { switchMap, catchError, map, finalize, shareReplay, tap, filter } from 'rxjs/operators';
11
11
  import { SpinnerComponent, AngularComponentsModule } from '@rolatech/angular-components';
12
12
  import * as i1 from '@angular/forms';
13
13
  import * as i2 from '@angular/material/form-field';
14
14
  import * as i3 from '@angular/material/input';
15
15
  import { isPlatformBrowser, CommonModule } from '@angular/common';
16
- import { of, map as map$1, BehaviorSubject, catchError, throwError, NEVER } from 'rxjs';
16
+ import { Router, provideRouter, ROUTES } from '@angular/router';
17
17
  import { MatSnackBar } from '@angular/material/snack-bar';
18
18
 
19
19
  class ForbiddenComponent {
20
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ForbiddenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.1", type: ForbiddenComponent, isStandalone: true, selector: "rolatech-forbidden", ngImport: i0, template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>403.</b>\n <p>Forbidden page.</p>\n </div>\n</div>\n", styles: [""] });
20
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ForbiddenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: ForbiddenComponent, isStandalone: true, selector: "rolatech-forbidden", ngImport: i0, template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>403.</b>\n <p>Forbidden page.</p>\n </div>\n</div>\n", styles: [""] });
22
22
  }
23
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ForbiddenComponent, decorators: [{
23
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ForbiddenComponent, decorators: [{
24
24
  type: Component,
25
25
  args: [{ selector: 'rolatech-forbidden', template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>403.</b>\n <p>Forbidden page.</p>\n </div>\n</div>\n" }]
26
26
  }] });
27
27
 
28
28
  class UnauthorizedComponent {
29
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
30
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.1", type: UnauthorizedComponent, isStandalone: true, selector: "rolatech-unauthorized", ngImport: i0, template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>401.</b>\n <p>Unauthorized page.</p>\n </div>\n</div>\n", styles: [""] });
29
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
30
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: UnauthorizedComponent, isStandalone: true, selector: "rolatech-unauthorized", ngImport: i0, template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>401.</b>\n <p>Unauthorized page.</p>\n </div>\n</div>\n", styles: [""] });
31
31
  }
32
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: UnauthorizedComponent, decorators: [{
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: UnauthorizedComponent, decorators: [{
33
33
  type: Component,
34
34
  args: [{ selector: 'rolatech-unauthorized', template: "<div class=\"p-6 max-w-lg h-auto max-h-32\">\n <div class=\"flex flex-col\">\n <b>401.</b>\n <p>Unauthorized page.</p>\n </div>\n</div>\n" }]
35
35
  }] });
@@ -39,24 +39,71 @@ class AuthStore {
39
39
  userId: '',
40
40
  user: null,
41
41
  roles: [],
42
+ username: null,
43
+ platformRoles: [],
44
+ applications: [],
45
+ organizations: [],
46
+ permissions: [],
42
47
  authenticated: false,
43
48
  loaded: false,
44
49
  }, ...(ngDevMode ? [{ debugName: "_state" }] : []));
45
50
  userId = computed(() => this._state().userId, ...(ngDevMode ? [{ debugName: "userId" }] : []));
46
51
  user = computed(() => this._state().user, ...(ngDevMode ? [{ debugName: "user" }] : []));
47
52
  roles = computed(() => this._state().roles, ...(ngDevMode ? [{ debugName: "roles" }] : []));
53
+ username = computed(() => this._state().username, ...(ngDevMode ? [{ debugName: "username" }] : []));
54
+ platformRoles = computed(() => this._state().platformRoles, ...(ngDevMode ? [{ debugName: "platformRoles" }] : []));
55
+ applications = computed(() => this._state().applications, ...(ngDevMode ? [{ debugName: "applications" }] : []));
56
+ organizations = computed(() => this._state().organizations, ...(ngDevMode ? [{ debugName: "organizations" }] : []));
57
+ permissions = computed(() => this._state().permissions, ...(ngDevMode ? [{ debugName: "permissions" }] : []));
48
58
  authenticated = computed(() => this._state().authenticated, ...(ngDevMode ? [{ debugName: "authenticated" }] : []));
49
59
  loaded = computed(() => this._state().loaded, ...(ngDevMode ? [{ debugName: "loaded" }] : []));
60
+ me = computed(() => {
61
+ if (!this.loaded() || !this.authenticated()) {
62
+ return null;
63
+ }
64
+ return {
65
+ userId: this.userId(),
66
+ username: this.username() ?? this.user()?.username ?? '',
67
+ platformRoles: this.platformRoles(),
68
+ applications: this.applications(),
69
+ organizations: this.organizations(),
70
+ permissions: this.permissions(),
71
+ };
72
+ }, ...(ngDevMode ? [{ debugName: "me" }] : []));
73
+ primaryApplication = computed(() => this.applications()[0] ?? null, ...(ngDevMode ? [{ debugName: "primaryApplication" }] : []));
74
+ primaryOrganization = computed(() => this.organizations()[0] ?? null, ...(ngDevMode ? [{ debugName: "primaryOrganization" }] : []));
50
75
  update(data) {
51
76
  this._state.update((state) => {
52
77
  state.authenticated = data.authenticated;
53
- state.userId = data.userId;
54
- state.roles = data.roles;
55
- state.loaded = data.loaded;
56
- state.user = data.user;
78
+ state.userId = data.userId ?? state.userId;
79
+ state.roles = data.roles ?? state.roles;
80
+ state.loaded = data.loaded ?? state.loaded;
81
+ state.user = data.user ?? state.user;
82
+ state.username = data.username ?? state.username;
83
+ state.platformRoles = data.platformRoles ?? state.platformRoles;
84
+ state.applications = data.applications ?? state.applications;
85
+ state.organizations = data.organizations ?? state.organizations;
86
+ state.permissions = data.permissions ?? state.permissions;
57
87
  return { ...state };
58
88
  });
59
89
  }
90
+ clear() {
91
+ this._state.set({
92
+ userId: '',
93
+ user: null,
94
+ roles: [],
95
+ username: null,
96
+ platformRoles: [],
97
+ applications: [],
98
+ organizations: [],
99
+ permissions: [],
100
+ authenticated: false,
101
+ loaded: true,
102
+ });
103
+ }
104
+ resetLoading() {
105
+ this._state.update((state) => ({ ...state, loaded: false }));
106
+ }
60
107
  updateAuthenticated(authenticated) {
61
108
  this._state.update((state) => {
62
109
  state.authenticated = authenticated;
@@ -66,9 +113,21 @@ class AuthStore {
66
113
  updateUser(user) {
67
114
  this._state.update((state) => {
68
115
  state.user = user;
116
+ state.username = user.username;
69
117
  return { ...state };
70
118
  });
71
119
  }
120
+ updateContext(context) {
121
+ this._state.update((state) => ({
122
+ ...state,
123
+ userId: context.userId,
124
+ username: context.username,
125
+ platformRoles: context.platformRoles ?? [],
126
+ applications: context.applications ?? [],
127
+ organizations: context.organizations ?? [],
128
+ permissions: context.permissions ?? [],
129
+ }));
130
+ }
72
131
  updateEmail(email) {
73
132
  this._state.update((state) => {
74
133
  if (state.user) {
@@ -77,10 +136,81 @@ class AuthStore {
77
136
  return { ...state };
78
137
  });
79
138
  }
80
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
81
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthStore, providedIn: 'root' });
139
+ hasAnyRole(...roles) {
140
+ if (!roles.length) {
141
+ return false;
142
+ }
143
+ const roleSet = new Set(this.roles());
144
+ return roles.some((role) => roleSet.has(role));
145
+ }
146
+ hasPlatformRole(...roles) {
147
+ if (!roles.length) {
148
+ return false;
149
+ }
150
+ const roleSet = new Set(this.platformRoles().length ? this.platformRoles() : this.roles());
151
+ return roles.some((role) => roleSet.has(role));
152
+ }
153
+ hasApplicationRole(appId, ...roles) {
154
+ if (!roles.length) {
155
+ return false;
156
+ }
157
+ return this.applications().some((membership) => {
158
+ if (appId && membership.appId !== appId) {
159
+ return false;
160
+ }
161
+ const roleSet = new Set(membership.roles);
162
+ return roles.some((role) => roleSet.has(role));
163
+ });
164
+ }
165
+ hasOrganizationRole(appId, orgId, ...roles) {
166
+ if (!roles.length) {
167
+ return false;
168
+ }
169
+ return this.organizations().some((membership) => {
170
+ if (appId && membership.appId !== appId) {
171
+ return false;
172
+ }
173
+ if (orgId && membership.orgId !== orgId) {
174
+ return false;
175
+ }
176
+ const roleSet = new Set(membership.roles);
177
+ return roles.some((role) => roleSet.has(role));
178
+ });
179
+ }
180
+ hasPermission(permission) {
181
+ return this.permissions().includes(permission);
182
+ }
183
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
184
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthStore, providedIn: 'root' });
185
+ }
186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthStore, decorators: [{
187
+ type: Injectable,
188
+ args: [{ providedIn: 'root' }]
189
+ }] });
190
+
191
+ class AuthContextStore {
192
+ state = signal({
193
+ appId: null,
194
+ orgId: null,
195
+ }, ...(ngDevMode ? [{ debugName: "state" }] : []));
196
+ appId = computed(() => this.state().appId, ...(ngDevMode ? [{ debugName: "appId" }] : []));
197
+ orgId = computed(() => this.state().orgId, ...(ngDevMode ? [{ debugName: "orgId" }] : []));
198
+ setContext(appId, orgId) {
199
+ this.state.set({ appId, orgId });
200
+ }
201
+ setAppId(appId) {
202
+ this.state.update((state) => ({ ...state, appId }));
203
+ }
204
+ setOrgId(orgId) {
205
+ this.state.update((state) => ({ ...state, orgId }));
206
+ }
207
+ clear() {
208
+ this.state.set({ appId: null, orgId: null });
209
+ }
210
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthContextStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
211
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthContextStore, providedIn: 'root' });
82
212
  }
83
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthStore, decorators: [{
213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthContextStore, decorators: [{
84
214
  type: Injectable,
85
215
  args: [{ providedIn: 'root' }]
86
216
  }] });
@@ -88,39 +218,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
88
218
  class AuthService {
89
219
  environment = inject(APP_CONFIG);
90
220
  http = inject(HttpClient);
91
- route = inject(ActivatedRoute);
92
221
  authStore = inject(AuthStore);
222
+ authContextStore = inject(AuthContextStore);
93
223
  authenticated = this.authStore.authenticated;
94
224
  userId = this.authStore.userId;
95
225
  user = this.authStore.user;
96
226
  roles = this.authStore.roles;
227
+ meContext = this.authStore.me;
228
+ platformRoles = this.authStore.platformRoles;
229
+ applications = this.authStore.applications;
230
+ organizations = this.authStore.organizations;
231
+ permissions = this.authStore.permissions;
97
232
  loaded = this.authStore.loaded;
98
- introspect() {
99
- return this.http
233
+ pendingIntrospect$;
234
+ introspect(force = false) {
235
+ if (!force && this.authStore.loaded()) {
236
+ return of(this.currentSession());
237
+ }
238
+ if (!force && this.pendingIntrospect$) {
239
+ return this.pendingIntrospect$;
240
+ }
241
+ const request$ = this.http
100
242
  .get(`${this.environment.baseUrl}/auth/introspect`, {
101
243
  withCredentials: true,
102
244
  })
103
- .pipe(map((res) => {
104
- this.authStore.update({
105
- authenticated: res.authenticated,
106
- userId: res.userId,
107
- roles: res.roles,
108
- loaded: true,
109
- });
110
- if (res.authenticated) {
111
- this.me().subscribe();
245
+ .pipe(switchMap((res) => {
246
+ if (!res.authenticated) {
247
+ this.authStore.clear();
248
+ this.authContextStore.clear();
249
+ return of(res);
112
250
  }
113
- return res;
114
- }));
251
+ return forkJoin({
252
+ user: this.me().pipe(catchError(() => of(null))),
253
+ context: this.getMeContext().pipe(catchError(() => of(this.emptyContext(res)))),
254
+ }).pipe(map(({ user, context }) => {
255
+ this.authStore.update({
256
+ authenticated: true,
257
+ userId: res.userId,
258
+ roles: res.roles ?? [],
259
+ loaded: true,
260
+ user,
261
+ username: context.username ?? res.username ?? user?.username ?? null,
262
+ platformRoles: context.platformRoles?.length ? context.platformRoles : (res.roles ?? []),
263
+ applications: context.applications ?? [],
264
+ organizations: context.organizations ?? [],
265
+ permissions: context.permissions ?? [],
266
+ });
267
+ this.syncContext(context);
268
+ return res;
269
+ }));
270
+ }), catchError((error) => {
271
+ this.authStore.clear();
272
+ this.authContextStore.clear();
273
+ return throwError(() => error);
274
+ }), finalize(() => {
275
+ this.pendingIntrospect$ = undefined;
276
+ }), shareReplay(1));
277
+ this.pendingIntrospect$ = request$;
278
+ return request$;
279
+ }
280
+ ensureLoaded(force = false) {
281
+ return this.introspect(force);
282
+ }
283
+ getMeContext() {
284
+ return this.http
285
+ .get(`${this.environment.baseUrl}/auth/me/context`)
286
+ .pipe(map((res) => res.data));
115
287
  }
116
288
  me() {
117
289
  return this.http
118
- .get(`${this.environment.baseUrl}/auth/users/me`, {
290
+ .get(`${this.environment.baseUrl}/auth/me`, {
119
291
  withCredentials: true,
120
292
  })
121
293
  .pipe(map((res) => {
122
294
  this.authStore.updateUser(res.data);
123
- return res;
295
+ return res.data;
124
296
  }));
125
297
  }
126
298
  wechatLogin(code, state) {
@@ -161,7 +333,7 @@ class AuthService {
161
333
  withCredentials: true,
162
334
  })
163
335
  .pipe(map((res) => {
164
- this.authStore.updateAuthenticated(true);
336
+ this.authStore.resetLoading();
165
337
  return res.data;
166
338
  }));
167
339
  }
@@ -171,7 +343,7 @@ class AuthService {
171
343
  withCredentials: true,
172
344
  })
173
345
  .pipe(map((res) => {
174
- this.authStore.updateAuthenticated(true);
346
+ this.authStore.resetLoading();
175
347
  return res;
176
348
  }));
177
349
  }
@@ -181,7 +353,8 @@ class AuthService {
181
353
  withCredentials: true,
182
354
  })
183
355
  .pipe(map((res) => {
184
- this.authStore.updateAuthenticated(false);
356
+ this.authStore.clear();
357
+ this.authContextStore.clear();
185
358
  return res;
186
359
  }));
187
360
  }
@@ -202,7 +375,7 @@ class AuthService {
202
375
  .pipe(map((user) => {
203
376
  return user;
204
377
  }), tap((_) => {
205
- this.authStore.updateAuthenticated(true);
378
+ this.authStore.resetLoading();
206
379
  }));
207
380
  }
208
381
  lookup(account, next) {
@@ -225,13 +398,60 @@ class AuthService {
225
398
  .pipe(map((user) => {
226
399
  return user;
227
400
  }), tap((_) => {
228
- this.authStore.updateAuthenticated(true);
401
+ this.authStore.resetLoading();
229
402
  }));
230
403
  }
231
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
232
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthService, providedIn: 'root' });
404
+ hasAnyRole(...roles) {
405
+ return this.authStore.hasAnyRole(...roles);
406
+ }
407
+ hasPlatformRole(...roles) {
408
+ return this.authStore.hasPlatformRole(...roles);
409
+ }
410
+ hasApplicationRole(appId, ...roles) {
411
+ return this.authStore.hasApplicationRole(appId, ...roles);
412
+ }
413
+ hasOrganizationRole(appId, orgId, ...roles) {
414
+ return this.authStore.hasOrganizationRole(appId, orgId, ...roles);
415
+ }
416
+ hasPermission(permission) {
417
+ return this.authStore.hasPermission(permission);
418
+ }
419
+ emptyContext(res) {
420
+ return {
421
+ userId: res.userId,
422
+ username: res.username ?? '',
423
+ platformRoles: [],
424
+ applications: [],
425
+ organizations: [],
426
+ permissions: [],
427
+ };
428
+ }
429
+ syncContext(context) {
430
+ if (this.authContextStore.appId() || this.authContextStore.orgId()) {
431
+ return;
432
+ }
433
+ const primaryOrganization = context.organizations[0] ?? null;
434
+ if (primaryOrganization) {
435
+ this.authContextStore.setContext(primaryOrganization.appId, primaryOrganization.orgId);
436
+ return;
437
+ }
438
+ const primaryApplication = context.applications[0] ?? null;
439
+ if (primaryApplication) {
440
+ this.authContextStore.setAppId(primaryApplication.appId);
441
+ }
442
+ }
443
+ currentSession() {
444
+ return {
445
+ authenticated: !!this.authStore.authenticated(),
446
+ userId: this.authStore.userId(),
447
+ roles: this.authStore.roles(),
448
+ username: this.authStore.username() ?? this.authStore.user()?.username,
449
+ };
450
+ }
451
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
452
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthService, providedIn: 'root' });
233
453
  }
234
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthService, decorators: [{
454
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthService, decorators: [{
235
455
  type: Injectable,
236
456
  args: [{ providedIn: 'root' }]
237
457
  }] });
@@ -290,10 +510,10 @@ class FaceidDetectDialogComponent {
290
510
  console.error(err);
291
511
  }
292
512
  }
293
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: FaceidDetectDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
294
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: FaceidDetectDialogComponent, isStandalone: true, selector: "rolatech-faceid-detect-dialog", outputs: { output: "output" }, ngImport: i0, template: "<div class=\"flex flex-col p-3 max-w-[500px] mx-auto\">\n <div class=\"w-[256px] h-[256px] mx-auto flex justify-center items-center\">\n @if (loading) {\n <div>\n <rolatech-spinner></rolatech-spinner>\n </div>\n }\n <img [src]=\"qrcodeUrl\" alt />\n </div>\n</div>\n", styles: ["*{margin:0;padding:0}.normalPanel .panelContent{width:188px;height:188px}.normalPanel .wrp_code{position:relative;width:188px;height:188px;margin:0}.impowerBox .title,.normalPanel .info{display:none}.impowerBox .qrcode{margin-top:0;border:0;width:188px;height:188px}#MAXIM{content:\"veg20170418191511\"}mat-mdc-dialog-content mdc-dialog__content{padding:0}\n"], dependencies: [{ kind: "component", type: SpinnerComponent, selector: "rolatech-spinner", inputs: ["title"] }, { kind: "ngmodule", type: MatButtonModule }] });
513
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FaceidDetectDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
514
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: FaceidDetectDialogComponent, isStandalone: true, selector: "rolatech-faceid-detect-dialog", outputs: { output: "output" }, ngImport: i0, template: "<div class=\"flex flex-col p-3 max-w-[500px] mx-auto\">\n <div class=\"w-[256px] h-[256px] mx-auto flex justify-center items-center\">\n @if (loading) {\n <div>\n <rolatech-spinner></rolatech-spinner>\n </div>\n }\n <img [src]=\"qrcodeUrl\" alt />\n </div>\n</div>\n", styles: ["*{margin:0;padding:0}.normalPanel .panelContent{width:188px;height:188px}.normalPanel .wrp_code{position:relative;width:188px;height:188px;margin:0}.impowerBox .title,.normalPanel .info{display:none}.impowerBox .qrcode{margin-top:0;border:0;width:188px;height:188px}#MAXIM{content:\"veg20170418191511\"}mat-mdc-dialog-content mdc-dialog__content{padding:0}\n"], dependencies: [{ kind: "component", type: SpinnerComponent, selector: "rolatech-spinner", inputs: ["title"] }, { kind: "ngmodule", type: MatButtonModule }] });
295
515
  }
296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: FaceidDetectDialogComponent, decorators: [{
516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: FaceidDetectDialogComponent, decorators: [{
297
517
  type: Component,
298
518
  args: [{ selector: 'rolatech-faceid-detect-dialog', imports: [SpinnerComponent, MatButtonModule], template: "<div class=\"flex flex-col p-3 max-w-[500px] mx-auto\">\n <div class=\"w-[256px] h-[256px] mx-auto flex justify-center items-center\">\n @if (loading) {\n <div>\n <rolatech-spinner></rolatech-spinner>\n </div>\n }\n <img [src]=\"qrcodeUrl\" alt />\n </div>\n</div>\n", styles: ["*{margin:0;padding:0}.normalPanel .panelContent{width:188px;height:188px}.normalPanel .wrp_code{position:relative;width:188px;height:188px;margin:0}.impowerBox .title,.normalPanel .info{display:none}.impowerBox .qrcode{margin-top:0;border:0;width:188px;height:188px}#MAXIM{content:\"veg20170418191511\"}mat-mdc-dialog-content mdc-dialog__content{padding:0}\n"] }]
299
519
  }], ctorParameters: () => [], propDecorators: { output: [{ type: i0.Output, args: ["output"] }] } });
@@ -322,10 +542,10 @@ class AddressComponent {
322
542
  ngDoCheck() {
323
543
  this.output.emit(this.address());
324
544
  }
325
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AddressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
326
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: AddressComponent, isStandalone: true, selector: "rolatech-address", inputs: { address: { classPropertyName: "address", publicName: "address", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { address: "addressChange", output: "output" }, ngImport: i0, template: "<div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Name </mat-label>\n <input matInput [(ngModel)]=\"address().name\" />\n </mat-form-field>\n @if (address().type === addressType.BILLING) {\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Email </mat-label>\n <input matInput [(ngModel)]=\"address().email\" />\n </mat-form-field>\n }\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Phone </mat-label>\n <input matInput [(ngModel)]=\"address().phone\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> province </mat-label>\n <input matInput [(ngModel)]=\"address().province\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> City </mat-label>\n <input matInput [(ngModel)]=\"address().city\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> District </mat-label>\n <input matInput [(ngModel)]=\"address().district\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Street </mat-label>\n <input matInput [(ngModel)]=\"address().street\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Detail </mat-label>\n <input matInput [(ngModel)]=\"address().detail\" />\n </mat-form-field>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
545
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AddressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
546
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.1", type: AddressComponent, isStandalone: true, selector: "rolatech-address", inputs: { address: { classPropertyName: "address", publicName: "address", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { address: "addressChange", output: "output" }, ngImport: i0, template: "<div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Name </mat-label>\n <input matInput [(ngModel)]=\"address().name\" />\n </mat-form-field>\n @if (address().type === addressType.BILLING) {\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Email </mat-label>\n <input matInput [(ngModel)]=\"address().email\" />\n </mat-form-field>\n }\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Phone </mat-label>\n <input matInput [(ngModel)]=\"address().phone\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> province </mat-label>\n <input matInput [(ngModel)]=\"address().province\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> City </mat-label>\n <input matInput [(ngModel)]=\"address().city\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> District </mat-label>\n <input matInput [(ngModel)]=\"address().district\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Street </mat-label>\n <input matInput [(ngModel)]=\"address().street\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Detail </mat-label>\n <input matInput [(ngModel)]=\"address().detail\" />\n </mat-form-field>\n</div>\n", styles: ["mat-form-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: AngularCommonModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AngularComponentsModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }] });
327
547
  }
328
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AddressComponent, decorators: [{
548
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AddressComponent, decorators: [{
329
549
  type: Component,
330
550
  args: [{ selector: 'rolatech-address', imports: [AngularCommonModule, AngularComponentsModule], template: "<div>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Name </mat-label>\n <input matInput [(ngModel)]=\"address().name\" />\n </mat-form-field>\n @if (address().type === addressType.BILLING) {\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Email </mat-label>\n <input matInput [(ngModel)]=\"address().email\" />\n </mat-form-field>\n }\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Phone </mat-label>\n <input matInput [(ngModel)]=\"address().phone\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> province </mat-label>\n <input matInput [(ngModel)]=\"address().province\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> City </mat-label>\n <input matInput [(ngModel)]=\"address().city\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> District </mat-label>\n <input matInput [(ngModel)]=\"address().district\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Street </mat-label>\n <input matInput [(ngModel)]=\"address().street\" />\n </mat-form-field>\n <mat-form-field appearance=\"fill\">\n <mat-label i18n> Detail </mat-label>\n <input matInput [(ngModel)]=\"address().detail\" />\n </mat-form-field>\n</div>\n", styles: ["mat-form-field{width:100%}\n"] }]
331
551
  }], propDecorators: { address: [{ type: i0.Input, args: [{ isSignal: true, alias: "address", required: false }] }, { type: i0.Output, args: ["addressChange"] }], output: [{ type: i0.Output, args: ["output"] }] } });
@@ -341,7 +561,7 @@ const AuthGuard = (route, state) => {
341
561
  const isContinue = state.url.includes('continue');
342
562
  const continueUrl = route.queryParams['continue'];
343
563
  const isSignInPage = state.url.includes('/signin');
344
- return authService.introspect().pipe(map$1(({ roles, authenticated }) => {
564
+ return authService.ensureLoaded().pipe(map$1(({ roles, authenticated }) => {
345
565
  const routeRoles = route.data['roles'];
346
566
  const passRoled = routeRoles ? roles?.some((r) => routeRoles.indexOf(r) >= 0) : true;
347
567
  if (authenticated && !passRoled) {
@@ -381,10 +601,10 @@ const AuthGuard = (route, state) => {
381
601
 
382
602
  class AuthDialogComponent {
383
603
  dialogRef = inject(MatDialogRef);
384
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
385
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.1", type: AuthDialogComponent, isStandalone: true, selector: "rolatech-auth-dialog", ngImport: i0, template: "<p>auth-dialog works!</p>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }] });
604
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
605
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.1", type: AuthDialogComponent, isStandalone: true, selector: "rolatech-auth-dialog", ngImport: i0, template: "<p>auth-dialog works!</p>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }] });
386
606
  }
387
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthDialogComponent, decorators: [{
607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthDialogComponent, decorators: [{
388
608
  type: Component,
389
609
  args: [{ selector: 'rolatech-auth-dialog', imports: [CommonModule, MatDialogModule], template: "<p>auth-dialog works!</p>\n" }]
390
610
  }] });
@@ -419,6 +639,93 @@ const AuthDialogGuard = (route, state) => {
419
639
  }));
420
640
  };
421
641
 
642
+ function matchesRouteAccessPolicy(authStore, authContextStore, policy) {
643
+ if (!policy) {
644
+ return true;
645
+ }
646
+ if (policy.authenticated !== undefined && authStore.authenticated() !== policy.authenticated) {
647
+ return false;
648
+ }
649
+ const appId = authContextStore.appId() ?? authStore.primaryApplication()?.appId ?? authStore.primaryOrganization()?.appId ?? null;
650
+ const orgId = authContextStore.orgId() ?? authStore.primaryOrganization()?.orgId ?? null;
651
+ const groupMatches = [];
652
+ if (policy.anyRole?.length) {
653
+ groupMatches.push(authStore.hasAnyRole(...policy.anyRole));
654
+ }
655
+ if (policy.anyPlatformRole?.length) {
656
+ groupMatches.push(authStore.hasPlatformRole(...policy.anyPlatformRole));
657
+ }
658
+ if (policy.anyApplicationRole?.length) {
659
+ groupMatches.push(authStore.hasApplicationRole(appId, ...policy.anyApplicationRole));
660
+ }
661
+ if (policy.anyOrganizationRole?.length) {
662
+ groupMatches.push(authStore.hasOrganizationRole(appId, orgId, ...policy.anyOrganizationRole));
663
+ }
664
+ if (policy.anyPermission?.length) {
665
+ groupMatches.push(policy.anyPermission.some((permission) => authStore.hasPermission(permission)));
666
+ }
667
+ if (!groupMatches.length) {
668
+ return true;
669
+ }
670
+ return groupMatches.some(Boolean);
671
+ }
672
+
673
+ function accessGuard(policy, fallbackUrl = '/forbidden') {
674
+ return () => {
675
+ const router = inject(Router);
676
+ const authService = inject(AuthService);
677
+ const authStore = inject(AuthStore);
678
+ const authContextStore = inject(AuthContextStore);
679
+ return authService.ensureLoaded().pipe(map(() => (matchesRouteAccessPolicy(authStore, authContextStore, policy) ? true : router.parseUrl(fallbackUrl))));
680
+ };
681
+ }
682
+ function accessMatchGuard(policy, fallbackUrl = '/forbidden') {
683
+ return () => {
684
+ const router = inject(Router);
685
+ const authService = inject(AuthService);
686
+ const authStore = inject(AuthStore);
687
+ const authContextStore = inject(AuthContextStore);
688
+ return authService.ensureLoaded().pipe(map(() => (matchesRouteAccessPolicy(authStore, authContextStore, policy) ? true : router.parseUrl(fallbackUrl))));
689
+ };
690
+ }
691
+
692
+ const PLATFORM_ADMIN_ROLES = ['PLATFORM_ADMIN', 'ROLE_PLATFORM_ADMIN'];
693
+ const APPLICATION_OWNER_ROLES = ['APPLICATION_OWNER', 'APP_OWNER', 'ROLE_APPLICATION_OWNER', 'ROLE_APP_OWNER'];
694
+ const APPLICATION_ADMIN_ROLES = ['APPLICATION_ADMIN', 'APP_ADMIN', 'ROLE_APPLICATION_ADMIN', 'ROLE_APP_ADMIN'];
695
+ const ORGANIZATION_OWNER_ROLES = ['ORGANIZATION_OWNER', 'ORG_OWNER', 'ROLE_ORGANIZATION_OWNER', 'ROLE_ORG_OWNER'];
696
+ const ORGANIZATION_ADMIN_ROLES = ['ORGANIZATION_ADMIN', 'ORG_ADMIN', 'ROLE_ORGANIZATION_ADMIN', 'ROLE_ORG_ADMIN'];
697
+ const ORGANIZATION_MEMBER_ROLES = ['ORGANIZATION_MEMBER', 'ORG_MEMBER', 'ROLE_ORGANIZATION_MEMBER', 'ROLE_ORG_MEMBER'];
698
+ const ORGANIZATION_STAFF_ROLES = ['ORGANIZATION_STAFF', 'ORG_STAFF', 'ROLE_ORGANIZATION_STAFF', 'ROLE_ORG_STAFF'];
699
+
700
+ function landingRedirectGuard(targets = {}) {
701
+ const resolvedTargets = {
702
+ platform: targets.platform ?? '/platform',
703
+ application: targets.application ?? '/app',
704
+ organization: targets.organization ?? '/organization',
705
+ forbidden: targets.forbidden ?? '/forbidden',
706
+ };
707
+ return () => {
708
+ const router = inject(Router);
709
+ const authService = inject(AuthService);
710
+ const authStore = inject(AuthStore);
711
+ const authContextStore = inject(AuthContextStore);
712
+ return authService.ensureLoaded().pipe(map(() => {
713
+ const appId = authContextStore.appId() ?? authStore.primaryApplication()?.appId ?? authStore.primaryOrganization()?.appId ?? null;
714
+ const orgId = authContextStore.orgId() ?? authStore.primaryOrganization()?.orgId ?? null;
715
+ if (authStore.hasPlatformRole(...PLATFORM_ADMIN_ROLES)) {
716
+ return router.parseUrl(resolvedTargets.platform);
717
+ }
718
+ if (authStore.hasApplicationRole(appId, ...APPLICATION_OWNER_ROLES, ...APPLICATION_ADMIN_ROLES)) {
719
+ return router.parseUrl(resolvedTargets.application);
720
+ }
721
+ if (authStore.hasOrganizationRole(appId, orgId, ...ORGANIZATION_OWNER_ROLES, ...ORGANIZATION_ADMIN_ROLES, ...ORGANIZATION_MEMBER_ROLES, ...ORGANIZATION_STAFF_ROLES)) {
722
+ return router.parseUrl(resolvedTargets.organization);
723
+ }
724
+ return router.parseUrl(resolvedTargets.forbidden);
725
+ }));
726
+ };
727
+ }
728
+
422
729
  const RoleGuard = (route, state) => {
423
730
  const authService = inject(AuthService);
424
731
  const environment = inject(APP_CONFIG);
@@ -434,7 +741,7 @@ const RoleGuard = (route, state) => {
434
741
  // if (!routeRoles) {
435
742
  // return of(false);
436
743
  // }
437
- return authService.introspect().pipe(filter((res) => res.roles !== null && res.roles.length > 0), map$1(({ roles }) => {
744
+ return authService.ensureLoaded().pipe(filter((res) => res.roles !== null && res.roles.length > 0), map$1(({ roles }) => {
438
745
  const authed = roles.some((r) => routeRoles?.indexOf(r) >= 0);
439
746
  if (!authed) {
440
747
  router.navigate(['/forbidden']);
@@ -481,7 +788,7 @@ class AuthUserService {
481
788
  }
482
789
  me() {
483
790
  return this.http
484
- .get(`${this.environment.baseUrl}/auth/users/me`, {
791
+ .get(`${this.environment.baseUrl}/auth/me`, {
485
792
  withCredentials: true,
486
793
  })
487
794
  .pipe(map$1((res) => {
@@ -506,6 +813,19 @@ class AuthUserService {
506
813
  sendSMSCode(countryCode, phone) {
507
814
  return this.http.post(`${this.environment.baseUrl}/auth/users/verification/phone/start`, { countryCode, phone });
508
815
  }
816
+ verifyEmailByToken(token) {
817
+ return this.http
818
+ .post(`${this.environment.baseUrl}/auth/users/verification/email`, {}, {
819
+ params: { token },
820
+ withCredentials: true,
821
+ })
822
+ .pipe(map$1((response) => {
823
+ if (typeof response === 'boolean') {
824
+ return response;
825
+ }
826
+ return Boolean(response.data);
827
+ }));
828
+ }
509
829
  findByUsername(username) {
510
830
  return this.http.get(`${this.environment.baseUrl}/auth/users/info`, {
511
831
  params: { username },
@@ -530,7 +850,7 @@ class AuthUserService {
530
850
  });
531
851
  }
532
852
  changeName(name) {
533
- return this.http.put(`${this.environment.baseUrl}/auth/users/me`, { name }, {
853
+ return this.http.put(`${this.environment.baseUrl}/auth/me`, { name }, {
534
854
  withCredentials: true,
535
855
  });
536
856
  }
@@ -540,7 +860,7 @@ class AuthUserService {
540
860
  });
541
861
  }
542
862
  update(data) {
543
- return this.http.put(`${this.environment.baseUrl}/auth/users/me`, data, {
863
+ return this.http.put(`${this.environment.baseUrl}/auth/me`, data, {
544
864
  withCredentials: true,
545
865
  });
546
866
  }
@@ -598,10 +918,10 @@ class AuthUserService {
598
918
  deleteAddressById(id) {
599
919
  return this.http.delete(`${this.environment.baseUrl}/auth/users/addresses/${id}`, { withCredentials: true });
600
920
  }
601
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthUserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
602
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthUserService, providedIn: 'root' });
921
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthUserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
922
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthUserService, providedIn: 'root' });
603
923
  }
604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthUserService, decorators: [{
924
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthUserService, decorators: [{
605
925
  type: Injectable,
606
926
  args: [{
607
927
  providedIn: 'root',
@@ -648,10 +968,10 @@ class AuthAgentService {
648
968
  withCredentials: true,
649
969
  });
650
970
  }
651
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthAgentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
652
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthAgentService, providedIn: 'root' });
971
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthAgentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
972
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthAgentService, providedIn: 'root' });
653
973
  }
654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthAgentService, decorators: [{
974
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthAgentService, decorators: [{
655
975
  type: Injectable,
656
976
  args: [{
657
977
  providedIn: 'root',
@@ -695,10 +1015,10 @@ class LocalStorageService {
695
1015
  setItem(key, value) {
696
1016
  return this.storage.setItem(key, value);
697
1017
  }
698
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: LocalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
699
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: LocalStorageService, providedIn: 'root' });
1018
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LocalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1019
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LocalStorageService, providedIn: 'root' });
700
1020
  }
701
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: LocalStorageService, decorators: [{
1021
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LocalStorageService, decorators: [{
702
1022
  type: Injectable,
703
1023
  args: [{
704
1024
  providedIn: 'root',
@@ -710,7 +1030,7 @@ class ErrorInterceptor {
710
1030
  isRefreshingToken = false;
711
1031
  authService = inject(AuthService);
712
1032
  intercept(request, next) {
713
- return next.handle(request).pipe(catchError((error) => {
1033
+ return next.handle(request).pipe(catchError$1((error) => {
714
1034
  if (error instanceof HttpErrorResponse) {
715
1035
  switch (error.status) {
716
1036
  case 400:
@@ -753,13 +1073,12 @@ class ErrorInterceptor {
753
1073
  return throwError(() => error.error);
754
1074
  }
755
1075
  handleDefaultError(error) {
756
- return throwError(() => new Error('系统错误'));
757
- // return throwError(() => error.error);
1076
+ return throwError(() => new Error('System error'));
758
1077
  }
759
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ErrorInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
760
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ErrorInterceptor });
1078
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1079
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorInterceptor });
761
1080
  }
762
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: ErrorInterceptor, decorators: [{
1081
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: ErrorInterceptor, decorators: [{
763
1082
  type: Injectable
764
1083
  }] });
765
1084
 
@@ -777,7 +1096,7 @@ class AuthInterceptor {
777
1096
  // // window.location.href = res.headers.get('Location') as string;
778
1097
  // }
779
1098
  return res;
780
- }), catchError$1((error) => {
1099
+ }), catchError((error) => {
781
1100
  if (isPlatformBrowser(this.platformId)) {
782
1101
  if (error.url?.includes('auth/introspect')) {
783
1102
  // if (window.location.origin !== `${this.environment.accountsUrl}`) {
@@ -808,10 +1127,10 @@ class AuthInterceptor {
808
1127
  },
809
1128
  });
810
1129
  }
811
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
812
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthInterceptor });
1130
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthInterceptor, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1131
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthInterceptor });
813
1132
  }
814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: AuthInterceptor, decorators: [{
1133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AuthInterceptor, decorators: [{
815
1134
  type: Injectable
816
1135
  }], ctorParameters: () => [] });
817
1136
 
@@ -835,6 +1154,20 @@ function provideAngularAuth(config) {
835
1154
  useClass: AuthInterceptor,
836
1155
  multi: true,
837
1156
  },
1157
+ {
1158
+ provide: APP_INITIALIZER,
1159
+ multi: true,
1160
+ useFactory: () => {
1161
+ const authService = inject(AuthService);
1162
+ const platformId = inject(PLATFORM_ID);
1163
+ return () => {
1164
+ if (config?.autoLoadSession === false || !isPlatformBrowser(platformId)) {
1165
+ return Promise.resolve();
1166
+ }
1167
+ return firstValueFrom(authService.ensureLoaded().pipe(catchError(() => of(null))));
1168
+ };
1169
+ },
1170
+ },
838
1171
  ];
839
1172
  return makeEnvironmentProviders(providers);
840
1173
  }
@@ -850,9 +1183,116 @@ const authRoutes = [
850
1183
  },
851
1184
  ];
852
1185
 
1186
+ const ROLE_NAVIGATION_LINKS = new InjectionToken('ROLE_NAVIGATION_LINKS');
1187
+ function provideRoleNavigation(links) {
1188
+ const providers = [
1189
+ {
1190
+ provide: ROLE_NAVIGATION_LINKS,
1191
+ useValue: links,
1192
+ multi: true,
1193
+ },
1194
+ ];
1195
+ return makeEnvironmentProviders(providers);
1196
+ }
1197
+
1198
+ class AppNavigationService {
1199
+ authStore = inject(AuthStore);
1200
+ authContextStore = inject(AuthContextStore);
1201
+ linkGroups = inject(ROLE_NAVIGATION_LINKS, { optional: true }) ?? [];
1202
+ links = computed(() => {
1203
+ this.authStore.authenticated();
1204
+ this.authStore.loaded();
1205
+ this.authContextStore.appId();
1206
+ this.authContextStore.orgId();
1207
+ return this.linkGroups
1208
+ .flat()
1209
+ .sort((left, right) => (left.order ?? 0) - (right.order ?? 0))
1210
+ .map((link) => this.toNavLink(link))
1211
+ .filter((link) => link !== null);
1212
+ }, ...(ngDevMode ? [{ debugName: "links" }] : []));
1213
+ toNavLink(link) {
1214
+ if (link.visible === false || !matchesRouteAccessPolicy(this.authStore, this.authContextStore, link.access)) {
1215
+ return null;
1216
+ }
1217
+ const children = link.children
1218
+ ?.map((child) => this.toNavLink(child))
1219
+ .filter((child) => child !== null);
1220
+ if (link.children?.length && !children?.length) {
1221
+ return null;
1222
+ }
1223
+ return {
1224
+ ...link,
1225
+ children,
1226
+ };
1227
+ }
1228
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AppNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1229
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AppNavigationService, providedIn: 'root' });
1230
+ }
1231
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: AppNavigationService, decorators: [{
1232
+ type: Injectable,
1233
+ args: [{ providedIn: 'root' }]
1234
+ }] });
1235
+
1236
+ const ROLE_SHELL_CHILD_ROUTES = new InjectionToken('ROLE_SHELL_CHILD_ROUTES');
1237
+ function provideRoleShellRoutes(routes) {
1238
+ const providers = [
1239
+ {
1240
+ provide: ROLE_SHELL_CHILD_ROUTES,
1241
+ useValue: routes,
1242
+ multi: true,
1243
+ },
1244
+ ];
1245
+ return makeEnvironmentProviders(providers);
1246
+ }
1247
+ function provideRoleAwareFeature(config) {
1248
+ const providers = [];
1249
+ if (config.routes?.length) {
1250
+ providers.push(provideRoleShellRoutes(config.routes));
1251
+ }
1252
+ if (config.navigation?.length) {
1253
+ providers.push(provideRoleNavigation(config.navigation));
1254
+ }
1255
+ return makeEnvironmentProviders(providers);
1256
+ }
1257
+ function provideRoleAwareShellRouter(config, ...features) {
1258
+ const providers = [
1259
+ provideRouter([], ...features),
1260
+ {
1261
+ provide: ROUTES,
1262
+ multi: true,
1263
+ useFactory: () => {
1264
+ const contributedRoutes = inject(ROLE_SHELL_CHILD_ROUTES, { optional: true }) ?? [];
1265
+ return [
1266
+ ...(config.topLevelRoutes ?? []),
1267
+ {
1268
+ path: '',
1269
+ component: config.shellComponent,
1270
+ canActivate: config.shellCanActivate,
1271
+ canActivateChild: config.shellCanActivateChild,
1272
+ data: config.shellData,
1273
+ children: [...(config.shellChildren ?? []), ...contributedRoutes.flat()],
1274
+ },
1275
+ ...(config.fallbackRoute ? [config.fallbackRoute] : []),
1276
+ ];
1277
+ },
1278
+ },
1279
+ ];
1280
+ return makeEnvironmentProviders(providers);
1281
+ }
1282
+ function provideRoleAwareConsoleShell(config, ...features) {
1283
+ return makeEnvironmentProviders([
1284
+ provideRoleAwareShellRouter({
1285
+ ...config,
1286
+ shellCanActivate: config.shellCanActivate ?? [AuthGuard],
1287
+ shellCanActivateChild: config.shellCanActivateChild ?? [AuthGuard],
1288
+ }, ...features),
1289
+ ...(config.navigation?.length ? [provideRoleNavigation(config.navigation)] : []),
1290
+ ]);
1291
+ }
1292
+
853
1293
  /**
854
1294
  * Generated bundle index. Do not edit.
855
1295
  */
856
1296
 
857
- export { AUTH_METHODS, AddressComponent, AddressType, AuthAgentService, AuthDialogGuard, AuthGuard, AuthInterceptor, AuthMethod, AuthService, AuthStore, AuthUserService, ErrorInterceptor, FaceidDetectDialogComponent, ForbiddenComponent, LocalStorageService, PermissionGuard, RoleGuard, UnauthorizedComponent, UserStatus, authRoutes, provideAngularAuth };
1297
+ export { APPLICATION_ADMIN_ROLES, APPLICATION_OWNER_ROLES, AUTH_METHODS, AddressComponent, AddressType, AppNavigationService, AuthAgentService, AuthContextStore, AuthDialogGuard, AuthGuard, AuthInterceptor, AuthMethod, AuthService, AuthStore, AuthUserService, ErrorInterceptor, FaceidDetectDialogComponent, ForbiddenComponent, LocalStorageService, ORGANIZATION_ADMIN_ROLES, ORGANIZATION_MEMBER_ROLES, ORGANIZATION_OWNER_ROLES, ORGANIZATION_STAFF_ROLES, PLATFORM_ADMIN_ROLES, PermissionGuard, ROLE_NAVIGATION_LINKS, ROLE_SHELL_CHILD_ROUTES, RoleGuard, UnauthorizedComponent, UserStatus, accessGuard, accessMatchGuard, authRoutes, landingRedirectGuard, provideAngularAuth, provideRoleAwareConsoleShell, provideRoleAwareFeature, provideRoleAwareShellRouter, provideRoleNavigation, provideRoleShellRoutes };
858
1298
  //# sourceMappingURL=rolatech-angular-auth.mjs.map