@odx/auth 3.3.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/esm2020/index.mjs +2 -2
- package/esm2020/lib/auth.config.mjs +7 -1
- package/esm2020/lib/auth.providers.mjs +14 -15
- package/esm2020/lib/components/auth-loading-screen/auth-loading-screen.component.mjs +41 -0
- package/esm2020/lib/components/index.mjs +2 -0
- package/esm2020/lib/helpers/handle-auth-error.mjs +21 -0
- package/esm2020/lib/helpers/index.mjs +2 -1
- package/esm2020/lib/models/auth-http-cache.mjs +15 -6
- package/esm2020/lib/models/index.mjs +2 -1
- package/esm2020/lib/models/offline-auth-error-handler.mjs +7 -0
- package/esm2020/lib/plugins/index.mjs +2 -1
- package/esm2020/lib/plugins/loading-screen-plugin.mjs +16 -0
- package/esm2020/plugins/service-connect/lib/helpers/service-connect-plugin-factory.mjs +5 -17
- package/esm2020/plugins/service-connect/lib/service-connect-rights.plugin.mjs +1 -2
- package/esm2020/plugins/service-connect/lib/service-connect.config.mjs +4 -3
- package/fesm2015/odx-auth-plugins-service-connect.mjs +7 -21
- package/fesm2015/odx-auth-plugins-service-connect.mjs.map +1 -1
- package/fesm2015/odx-auth.mjs +119 -74
- package/fesm2015/odx-auth.mjs.map +1 -1
- package/fesm2020/odx-auth-plugins-service-connect.mjs +7 -19
- package/fesm2020/odx-auth-plugins-service-connect.mjs.map +1 -1
- package/fesm2020/odx-auth.mjs +116 -72
- package/fesm2020/odx-auth.mjs.map +1 -1
- package/index.d.ts +1 -1
- package/lib/auth.config.d.ts +4 -0
- package/lib/auth.providers.d.ts +1 -1
- package/lib/components/auth-loading-screen/auth-loading-screen.component.d.ts +11 -0
- package/lib/components/index.d.ts +1 -0
- package/lib/helpers/handle-auth-error.d.ts +3 -0
- package/lib/helpers/index.d.ts +1 -0
- package/lib/models/auth-http-cache.d.ts +2 -1
- package/lib/models/index.d.ts +1 -0
- package/lib/models/offline-auth-error-handler.d.ts +2 -0
- package/lib/plugins/index.d.ts +1 -0
- package/lib/plugins/loading-screen-plugin.d.ts +2 -0
- package/package.json +1 -1
- package/plugins/service-connect/lib/helpers/service-connect-plugin-factory.d.ts +3 -2
- package/plugins/service-connect/lib/service-connect-rights.plugin.d.ts +1 -1
- package/plugins/service-connect/lib/service-connect.config.d.ts +3 -0
- package/esm2020/lib/auth-overlay.component.mjs +0 -46
- package/lib/auth-overlay.component.d.ts +0 -9
package/fesm2020/odx-auth.mjs
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
import { trigger, transition, useAnimation } from '@angular/animations';
|
|
2
|
-
import * as i1 from '@angular/common';
|
|
3
|
-
import { CommonModule, NgIf } from '@angular/common';
|
|
4
1
|
import * as i0 from '@angular/core';
|
|
5
|
-
import {
|
|
6
|
-
import { fadeOut } from '@odx/angular/animations';
|
|
7
|
-
import { DynamicViewService } from '@odx/angular/cdk/dynamic-view';
|
|
8
|
-
import * as i6 from '@odx/angular/components/button';
|
|
9
|
-
import { ButtonComponent } from '@odx/angular/components/button';
|
|
10
|
-
import { CircularProgressComponent } from '@odx/angular/components/circular-progress';
|
|
11
|
-
import * as i7 from '@odx/angular/components/icon';
|
|
12
|
-
import { IconComponent } from '@odx/angular/components/icon';
|
|
13
|
-
import { LogoDirective } from '@odx/angular/components/logo';
|
|
14
|
-
import { BehaviorSubject, filter, map, distinctUntilChanged, share, of, switchMap, combineLatest, tap, take, fromEvent, startWith, merge, shareReplay, EMPTY } from 'rxjs';
|
|
15
|
-
import { isString, createConfigTokens, untilDestroyed, Position, buildUrl } from '@odx/angular/utils';
|
|
16
|
-
import { HttpErrorResponse } from '@angular/common/http';
|
|
17
|
-
import { Router } from '@angular/router';
|
|
2
|
+
import { inject, EnvironmentInjector, InjectionToken, Injectable, Directive, EventEmitter, Output, HostListener, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, NgModule, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, APP_INITIALIZER } from '@angular/core';
|
|
18
3
|
import { WindowRef, CoreModule } from '@odx/angular';
|
|
19
|
-
import { OAuthService, OAuthErrorEvent, provideOAuthClient, OAuthModuleConfig, OAuthStorage } from 'angular-oauth2-oidc';
|
|
20
|
-
import { deepmerge } from 'deepmerge-ts';
|
|
21
|
-
import jwtDecode from 'jwt-decode';
|
|
22
4
|
import * as i3 from '@odx/angular/components/area-header';
|
|
23
5
|
import { AreaHeaderModule } from '@odx/angular/components/area-header';
|
|
24
6
|
import * as i8 from '@odx/angular/components/dropdown';
|
|
25
7
|
import { DropdownModule } from '@odx/angular/components/dropdown';
|
|
26
8
|
import { HeaderModule } from '@odx/angular/components/header';
|
|
27
|
-
import * as i1
|
|
9
|
+
import * as i1 from '@odx/angular/components/loading-spinner';
|
|
28
10
|
import { LoadingSpinnerDirective, LoadingSpinnerModule } from '@odx/angular/components/loading-spinner';
|
|
11
|
+
import { LogoDirective } from '@odx/angular/components/logo';
|
|
12
|
+
import { isString, createConfigTokens, untilDestroyed, Position, buildUrl } from '@odx/angular/utils';
|
|
13
|
+
import { OAuthErrorEvent, OAuthService, provideOAuthClient, OAuthModuleConfig, OAuthStorage } from 'angular-oauth2-oidc';
|
|
14
|
+
import { HttpErrorResponse } from '@angular/common/http';
|
|
15
|
+
import { Router } from '@angular/router';
|
|
16
|
+
import { deepmerge } from 'deepmerge-ts';
|
|
17
|
+
import jwtDecode from 'jwt-decode';
|
|
18
|
+
import { BehaviorSubject, filter, map, distinctUntilChanged, share, of, switchMap, combineLatest, tap, take, fromEvent, startWith, merge, shareReplay, EMPTY } from 'rxjs';
|
|
19
|
+
import * as i1$1 from '@angular/common';
|
|
20
|
+
import { NgIf, CommonModule } from '@angular/common';
|
|
29
21
|
import * as i2 from '@ngrx/component';
|
|
30
22
|
import * as i4 from '@odx/angular/components/avatar';
|
|
31
23
|
import * as i5 from '@odx/angular/components/action-group';
|
|
24
|
+
import * as i6 from '@odx/angular/components/button';
|
|
25
|
+
import { ButtonComponent } from '@odx/angular/components/button';
|
|
26
|
+
import * as i7 from '@odx/angular/components/icon';
|
|
27
|
+
import { IconComponent } from '@odx/angular/components/icon';
|
|
28
|
+
import { DynamicViewDirective, DynamicViewService } from '@odx/angular/cdk/dynamic-view';
|
|
29
|
+
import { trigger, transition, useAnimation } from '@angular/animations';
|
|
30
|
+
import { fadeOut } from '@odx/angular/animations';
|
|
31
|
+
import { CircularProgressComponent } from '@odx/angular/components/circular-progress';
|
|
32
32
|
|
|
33
33
|
function createInitials(value) {
|
|
34
34
|
if (!value)
|
|
@@ -45,6 +45,25 @@ function createInitials(value) {
|
|
|
45
45
|
}, '');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
function handleAuthError(handlers) {
|
|
49
|
+
const injector = inject(EnvironmentInjector);
|
|
50
|
+
return (error) => {
|
|
51
|
+
injector.runInContext(() => {
|
|
52
|
+
for (const handler of handlers) {
|
|
53
|
+
try {
|
|
54
|
+
handler(error);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
catch (unhandledError) {
|
|
58
|
+
if (!(unhandledError instanceof OAuthErrorEvent))
|
|
59
|
+
throw error;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
function resolveEmail(claims) {
|
|
49
68
|
if (isString(claims['email'])) {
|
|
50
69
|
return claims['email'];
|
|
@@ -84,6 +103,10 @@ const ODX_AUTH_CORE_PLUGINS = new InjectionToken('@odx/auth::CorePlugins', {
|
|
|
84
103
|
providedIn: 'root',
|
|
85
104
|
factory: () => [],
|
|
86
105
|
});
|
|
106
|
+
const ODX_AUTH_ERROR_HANDLERS = new InjectionToken('@odx/auth::ErrorHandlers', {
|
|
107
|
+
providedIn: 'root',
|
|
108
|
+
factory: () => [],
|
|
109
|
+
});
|
|
87
110
|
const ODX_AUTH_PLUGINS = new InjectionToken('@odx/auth::Plugins', {
|
|
88
111
|
providedIn: 'root',
|
|
89
112
|
factory: () => {
|
|
@@ -108,6 +131,8 @@ const { AuthDefaultConfig, AuthConfig, injectAuthConfig, provideAuthConfig } = c
|
|
|
108
131
|
showRedirectOverlay: false,
|
|
109
132
|
plugins: [],
|
|
110
133
|
defaultAuthorizedHandler: null,
|
|
134
|
+
enableLoadingScreen: false,
|
|
135
|
+
loadingScreenMessage: null,
|
|
111
136
|
});
|
|
112
137
|
|
|
113
138
|
const ODX_AUTH_HTTP_CACHE_STORAGE = new InjectionToken('@odx/auth::AuthHttpCacheStorage', {
|
|
@@ -117,18 +142,26 @@ const ODX_AUTH_HTTP_CACHE_STORAGE = new InjectionToken('@odx/auth::AuthHttpCache
|
|
|
117
142
|
class AuthHttpCache {
|
|
118
143
|
constructor() {
|
|
119
144
|
this.cacheStorage = inject(ODX_AUTH_HTTP_CACHE_STORAGE);
|
|
145
|
+
this.oauthService = inject(OAuthService);
|
|
120
146
|
}
|
|
121
147
|
async delete(request) {
|
|
122
148
|
const cache = await this.cacheStorage.open(AuthHttpCache.CACHE_KEY);
|
|
123
149
|
return cache.delete(request);
|
|
124
150
|
}
|
|
125
|
-
async request(
|
|
151
|
+
async request(requestInfo, authentication = false) {
|
|
152
|
+
const request = new Request(requestInfo);
|
|
153
|
+
const authorizationHeader = authentication ? this.oauthService.authorizationHeader() : null;
|
|
154
|
+
if (authorizationHeader) {
|
|
155
|
+
request.headers.set('Authorization', authorizationHeader);
|
|
156
|
+
}
|
|
126
157
|
const cache = await this.cacheStorage.open(AuthHttpCache.CACHE_KEY);
|
|
127
|
-
|
|
128
|
-
|
|
158
|
+
const response = await fetch(request).catch(() => null);
|
|
159
|
+
if (response?.ok) {
|
|
160
|
+
await cache.put(request, response);
|
|
129
161
|
}
|
|
130
|
-
|
|
131
|
-
|
|
162
|
+
if (authorizationHeader && response?.status === 401) {
|
|
163
|
+
await cache.delete(request);
|
|
164
|
+
await this.oauthService.refreshToken().catch(() => null);
|
|
132
165
|
}
|
|
133
166
|
return cache.match(request).then((res) => res?.json() ?? null);
|
|
134
167
|
}
|
|
@@ -165,6 +198,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
|
165
198
|
args: [{ providedIn: 'root' }]
|
|
166
199
|
}] });
|
|
167
200
|
|
|
201
|
+
const offlineAuthErrorHandler = (error) => {
|
|
202
|
+
if (error.type === 'discovery_document_load_error' && error.reason?.status === 504) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
throw error;
|
|
206
|
+
};
|
|
207
|
+
|
|
168
208
|
class AuthService {
|
|
169
209
|
constructor() {
|
|
170
210
|
this.authConfig = injectAuthConfig();
|
|
@@ -294,38 +334,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
|
294
334
|
args: [{ providedIn: 'root' }]
|
|
295
335
|
}], ctorParameters: function () { return []; } });
|
|
296
336
|
|
|
297
|
-
class AuthOverlayComponent {
|
|
298
|
-
constructor() {
|
|
299
|
-
this.icon$ = inject(AuthService).isRedirecting$.pipe(startWith(false), distinctUntilChanged(), map((isRedirecting) => (isRedirecting ? 'link-external' : 'user')));
|
|
300
|
-
}
|
|
301
|
-
static initialize() {
|
|
302
|
-
const dynamicViewService = inject(DynamicViewService);
|
|
303
|
-
inject(AuthService).isLoading$.subscribe((isLoading) => {
|
|
304
|
-
if (isLoading) {
|
|
305
|
-
AuthOverlayComponent.instance ?? (AuthOverlayComponent.instance = dynamicViewService.createView(AuthOverlayComponent));
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
AuthOverlayComponent.instance?.destroy();
|
|
309
|
-
AuthOverlayComponent.instance = null;
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
AuthOverlayComponent.instance = null;
|
|
315
|
-
AuthOverlayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
316
|
-
AuthOverlayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: AuthOverlayComponent, isStandalone: true, selector: "div.odx-auth-overlay", host: { properties: { "@hostAnimation": "true" } }, ngImport: i0, template: "<div class=\"odx-auth-overlay__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-overlay-spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n</div>\n", styles: ["@keyframes odx-auth-overlay-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-overlay{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-overlay__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-overlay-animation .75s ease}.odx-auth-overlay-spinner{position:relative}.odx-auth-overlay-spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "component", type: IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "component", type: CircularProgressComponent, selector: "odx-circular-progress", inputs: ["stroke", "size", "value"] }], animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
317
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthOverlayComponent, decorators: [{
|
|
318
|
-
type: Component,
|
|
319
|
-
args: [{ standalone: true, selector: 'div.odx-auth-overlay', imports: [CommonModule, ButtonComponent, IconComponent, LogoDirective, CircularProgressComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
320
|
-
'[@hostAnimation]': 'true',
|
|
321
|
-
}, animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], template: "<div class=\"odx-auth-overlay__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-overlay-spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n</div>\n", styles: ["@keyframes odx-auth-overlay-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-overlay{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-overlay__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-overlay-animation .75s ease}.odx-auth-overlay-spinner{position:relative}.odx-auth-overlay-spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"] }]
|
|
322
|
-
}] });
|
|
323
|
-
function initalizeAuthOverlay() {
|
|
324
|
-
if (!injectAuthConfig().showRedirectOverlay)
|
|
325
|
-
return;
|
|
326
|
-
AuthOverlayComponent.initialize();
|
|
327
|
-
}
|
|
328
|
-
|
|
329
337
|
class AuthActionDirective {
|
|
330
338
|
constructor() {
|
|
331
339
|
this.takeUntilDestroyed = untilDestroyed();
|
|
@@ -357,7 +365,7 @@ class SignInDirective extends AuthActionDirective {
|
|
|
357
365
|
}
|
|
358
366
|
}
|
|
359
367
|
SignInDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SignInDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
360
|
-
SignInDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SignInDirective, isStandalone: true, selector: "[odxButton][odxAuthSignIn]", outputs: { afterSignIn: "odxAuthSignIn" }, host: { listeners: { "click": "handleClick()" } }, usesInheritance: true, hostDirectives: [{ directive: i1
|
|
368
|
+
SignInDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SignInDirective, isStandalone: true, selector: "[odxButton][odxAuthSignIn]", outputs: { afterSignIn: "odxAuthSignIn" }, host: { listeners: { "click": "handleClick()" } }, usesInheritance: true, hostDirectives: [{ directive: i1.LoadingSpinnerDirective }], ngImport: i0 });
|
|
361
369
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SignInDirective, decorators: [{
|
|
362
370
|
type: Directive,
|
|
363
371
|
args: [{
|
|
@@ -385,7 +393,7 @@ class SignOutDirective extends AuthActionDirective {
|
|
|
385
393
|
}
|
|
386
394
|
}
|
|
387
395
|
SignOutDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SignOutDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
388
|
-
SignOutDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SignOutDirective, isStandalone: true, selector: "[odxButton][odxAuthSignOut]", outputs: { afterSignOut: "odxAuthSignOut" }, host: { listeners: { "click": "handleClick()" } }, usesInheritance: true, hostDirectives: [{ directive: i1
|
|
396
|
+
SignOutDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: SignOutDirective, isStandalone: true, selector: "[odxButton][odxAuthSignOut]", outputs: { afterSignOut: "odxAuthSignOut" }, host: { listeners: { "click": "handleClick()" } }, usesInheritance: true, hostDirectives: [{ directive: i1.LoadingSpinnerDirective }], ngImport: i0 });
|
|
389
397
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: SignOutDirective, decorators: [{
|
|
390
398
|
type: Directive,
|
|
391
399
|
args: [{
|
|
@@ -415,7 +423,7 @@ class AuthComponent {
|
|
|
415
423
|
}
|
|
416
424
|
}
|
|
417
425
|
AuthComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
418
|
-
AuthComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: AuthComponent, isStandalone: true, selector: "odx-auth", inputs: { signInButtonText: "signInButtonText", signOutButtonText: "signOutButtonText" }, ngImport: i0, template: "<odx-action-group>\n <ng-template [ngrxLet]=\"{ idClaims: authService.identityClaims$, isAuthenticated: authService.isAuthenticated$ }\" let-vm>\n <ng-template [ngIf]=\"vm.isAuthenticated\" [ngIfElse]=\"notAuthenticated\">\n <button odxButton [odxDropdown]=\"userProfileMenu\" [odxDropdownOptions]=\"dropdownOptions\" data-testid=\"odx-auth-user-profile-button\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\"></ng-template>\n </button>\n <ng-template #userProfileMenu>\n <odx-area-header class=\"odx-padding-x-12\" size=\"small\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\" ngProjectAs=\"odx-avatar\"></ng-template>\n {{ vm.idClaims?.username }}\n <odx-area-header-subtitle>\n {{ vm.idClaims?.email }}\n </odx-area-header-subtitle>\n </odx-area-header>\n <ng-content></ng-content>\n <div class=\"odx-margin-top-12\" odxLayout=\"flex vertical-center\">\n <odx-logo odxLayout=\"auto\" class=\"odx-margin-left-12 odx-margin-right-auto\"></odx-logo>\n <button odxButton odxAuthSignOut variant=\"ghost\" data-testid=\"odx-auth-sign-out-button\">\n {{ signOutButtonText }}\n <odx-icon name=\"logout\" alignRight></odx-icon>\n </button>\n </div>\n </ng-template>\n </ng-template>\n <ng-template #notAuthenticated>\n <button class=\"odx-auth-sign-in\" odxButton odxAuthSignIn variant=\"secondary\" data-testid=\"odx-auth-sign-in-button\">\n <odx-icon name=\"user\" alignLeft></odx-icon>\n {{ signInButtonText }}\n </button>\n </ng-template>\n <ng-template #userAvatar>\n <odx-avatar class=\"odx-auth-user-avatar\">\n {{ vm.idClaims?.initials ?? '' }}\n </odx-avatar>\n </ng-template>\n </ng-template>\n</odx-action-group>\n", styles: [".odx-auth-user-profile .odx-dropdown__inner>.odx-area-header{max-width:max(360px,25vw);min-width:296px}\n"], dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.LetDirective, selector: "[ngrxLet]", inputs: ["ngrxLet", "ngrxLetSuspenseTpl"] }, { kind: "ngmodule", type: AreaHeaderModule }, { kind: "component", type: i3.AreaHeaderComponent, selector: "odx-area-header", inputs: ["size"] }, { kind: "directive", type: i3.AreaHeaderSubtitleDirective, selector: "odx-area-header-subtitle" }, { kind: "component", type: i4.AvatarComponent, selector: "odx-avatar", inputs: ["size", "variant"] }, { kind: "component", type: i5.ActionGroupComponent, selector: "odx-action-group", inputs: ["reverse"] }, { kind: "component", type: i6.ButtonComponent, selector: "button[odxButton], a[odxButton]", inputs: ["variant", "size"] }, { kind: "component", type: i7.IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "directive", type: i8.DropdownDirective, selector: "[odxDropdown]", inputs: ["odxDropdown", "odxDropdownDisabled", "odxDropdownShowLoader", "odxDropdownClickOutsideActive", "odxDropdownOptions", "odxDropdownReferenceElement", "odxDropdownTriggerElement", "odxDropdownHost", "odxDropdownOpenTrigger", "odxDropdownCloseTrigger"], outputs: ["odxDropdownBeforeOpen", "odxDropdownAfterOpen", "odxDropdownBeforeClose", "odxDropdownAfterClose"], exportAs: ["odxDropdown"] }, { kind: "ngmodule", type: HeaderModule }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "directive", type: SignInDirective, selector: "[odxButton][odxAuthSignIn]", outputs: ["odxAuthSignIn"] }, { kind: "directive", type: SignOutDirective, selector: "[odxButton][odxAuthSignOut]", outputs: ["odxAuthSignOut"] }, { kind: "ngmodule", type: LoadingSpinnerModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
426
|
+
AuthComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: AuthComponent, isStandalone: true, selector: "odx-auth", inputs: { signInButtonText: "signInButtonText", signOutButtonText: "signOutButtonText" }, ngImport: i0, template: "<odx-action-group>\n <ng-template [ngrxLet]=\"{ idClaims: authService.identityClaims$, isAuthenticated: authService.isAuthenticated$ }\" let-vm>\n <ng-template [ngIf]=\"vm.isAuthenticated\" [ngIfElse]=\"notAuthenticated\">\n <button odxButton [odxDropdown]=\"userProfileMenu\" [odxDropdownOptions]=\"dropdownOptions\" data-testid=\"odx-auth-user-profile-button\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\"></ng-template>\n </button>\n <ng-template #userProfileMenu>\n <odx-area-header class=\"odx-padding-x-12\" size=\"small\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\" ngProjectAs=\"odx-avatar\"></ng-template>\n {{ vm.idClaims?.username }}\n <odx-area-header-subtitle>\n {{ vm.idClaims?.email }}\n </odx-area-header-subtitle>\n </odx-area-header>\n <ng-content></ng-content>\n <div class=\"odx-margin-top-12\" odxLayout=\"flex vertical-center\">\n <odx-logo odxLayout=\"auto\" class=\"odx-margin-left-12 odx-margin-right-auto\"></odx-logo>\n <button odxButton odxAuthSignOut variant=\"ghost\" data-testid=\"odx-auth-sign-out-button\">\n {{ signOutButtonText }}\n <odx-icon name=\"logout\" alignRight></odx-icon>\n </button>\n </div>\n </ng-template>\n </ng-template>\n <ng-template #notAuthenticated>\n <button class=\"odx-auth-sign-in\" odxButton odxAuthSignIn variant=\"secondary\" data-testid=\"odx-auth-sign-in-button\">\n <odx-icon name=\"user\" alignLeft></odx-icon>\n {{ signInButtonText }}\n </button>\n </ng-template>\n <ng-template #userAvatar>\n <odx-avatar class=\"odx-auth-user-avatar\">\n {{ vm.idClaims?.initials ?? '' }}\n </odx-avatar>\n </ng-template>\n </ng-template>\n</odx-action-group>\n", styles: [".odx-auth-user-profile .odx-dropdown__inner>.odx-area-header{max-width:max(360px,25vw);min-width:296px}\n"], dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.LetDirective, selector: "[ngrxLet]", inputs: ["ngrxLet", "ngrxLetSuspenseTpl"] }, { kind: "ngmodule", type: AreaHeaderModule }, { kind: "component", type: i3.AreaHeaderComponent, selector: "odx-area-header", inputs: ["size"] }, { kind: "directive", type: i3.AreaHeaderSubtitleDirective, selector: "odx-area-header-subtitle" }, { kind: "component", type: i4.AvatarComponent, selector: "odx-avatar", inputs: ["size", "variant"] }, { kind: "component", type: i5.ActionGroupComponent, selector: "odx-action-group", inputs: ["reverse"] }, { kind: "component", type: i6.ButtonComponent, selector: "button[odxButton], a[odxButton]", inputs: ["variant", "size"] }, { kind: "component", type: i7.IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "ngmodule", type: DropdownModule }, { kind: "directive", type: i8.DropdownDirective, selector: "[odxDropdown]", inputs: ["odxDropdown", "odxDropdownDisabled", "odxDropdownShowLoader", "odxDropdownClickOutsideActive", "odxDropdownOptions", "odxDropdownReferenceElement", "odxDropdownTriggerElement", "odxDropdownHost", "odxDropdownOpenTrigger", "odxDropdownCloseTrigger"], outputs: ["odxDropdownBeforeOpen", "odxDropdownAfterOpen", "odxDropdownBeforeClose", "odxDropdownAfterClose"], exportAs: ["odxDropdown"] }, { kind: "ngmodule", type: HeaderModule }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "directive", type: SignInDirective, selector: "[odxButton][odxAuthSignIn]", outputs: ["odxAuthSignIn"] }, { kind: "directive", type: SignOutDirective, selector: "[odxButton][odxAuthSignOut]", outputs: ["odxAuthSignOut"] }, { kind: "ngmodule", type: LoadingSpinnerModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
419
427
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthComponent, decorators: [{
|
|
420
428
|
type: Component,
|
|
421
429
|
args: [{ standalone: true, selector: 'odx-auth', imports: [CoreModule, AreaHeaderModule, DropdownModule, HeaderModule, LogoDirective, SignInDirective, SignOutDirective, LoadingSpinnerModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<odx-action-group>\n <ng-template [ngrxLet]=\"{ idClaims: authService.identityClaims$, isAuthenticated: authService.isAuthenticated$ }\" let-vm>\n <ng-template [ngIf]=\"vm.isAuthenticated\" [ngIfElse]=\"notAuthenticated\">\n <button odxButton [odxDropdown]=\"userProfileMenu\" [odxDropdownOptions]=\"dropdownOptions\" data-testid=\"odx-auth-user-profile-button\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\"></ng-template>\n </button>\n <ng-template #userProfileMenu>\n <odx-area-header class=\"odx-padding-x-12\" size=\"small\">\n <ng-template [ngTemplateOutlet]=\"userAvatar\" ngProjectAs=\"odx-avatar\"></ng-template>\n {{ vm.idClaims?.username }}\n <odx-area-header-subtitle>\n {{ vm.idClaims?.email }}\n </odx-area-header-subtitle>\n </odx-area-header>\n <ng-content></ng-content>\n <div class=\"odx-margin-top-12\" odxLayout=\"flex vertical-center\">\n <odx-logo odxLayout=\"auto\" class=\"odx-margin-left-12 odx-margin-right-auto\"></odx-logo>\n <button odxButton odxAuthSignOut variant=\"ghost\" data-testid=\"odx-auth-sign-out-button\">\n {{ signOutButtonText }}\n <odx-icon name=\"logout\" alignRight></odx-icon>\n </button>\n </div>\n </ng-template>\n </ng-template>\n <ng-template #notAuthenticated>\n <button class=\"odx-auth-sign-in\" odxButton odxAuthSignIn variant=\"secondary\" data-testid=\"odx-auth-sign-in-button\">\n <odx-icon name=\"user\" alignLeft></odx-icon>\n {{ signInButtonText }}\n </button>\n </ng-template>\n <ng-template #userAvatar>\n <odx-avatar class=\"odx-auth-user-avatar\">\n {{ vm.idClaims?.initials ?? '' }}\n </odx-avatar>\n </ng-template>\n </ng-template>\n</odx-action-group>\n", styles: [".odx-auth-user-profile .odx-dropdown__inner>.odx-area-header{max-width:max(360px,25vw);min-width:296px}\n"] }]
|
|
@@ -444,7 +452,7 @@ class AuthDirective {
|
|
|
444
452
|
}
|
|
445
453
|
}
|
|
446
454
|
AuthDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
447
|
-
AuthDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: AuthDirective, isStandalone: true, selector: "ng-template[odxAuth]", inputs: { authorizationHandler: ["odxAuth", "authorizationHandler"], elseTemplate: ["odxAuthElse", "elseTemplate"] }, hostDirectives: [{ directive: i1.NgIf }], ngImport: i0 });
|
|
455
|
+
AuthDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: AuthDirective, isStandalone: true, selector: "ng-template[odxAuth]", inputs: { authorizationHandler: ["odxAuth", "authorizationHandler"], elseTemplate: ["odxAuthElse", "elseTemplate"] }, hostDirectives: [{ directive: i1$1.NgIf }], ngImport: i0 });
|
|
448
456
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthDirective, decorators: [{
|
|
449
457
|
type: Directive,
|
|
450
458
|
args: [{
|
|
@@ -509,6 +517,44 @@ const coreIdentityPlugin = () => {
|
|
|
509
517
|
};
|
|
510
518
|
};
|
|
511
519
|
|
|
520
|
+
class AuthLoadingScreenComponent {
|
|
521
|
+
constructor() {
|
|
522
|
+
this.authConfig = injectAuthConfig();
|
|
523
|
+
this.icon$ = inject(AuthService).isRedirecting$.pipe(startWith(false), distinctUntilChanged(), map((isRedirecting) => (isRedirecting ? 'link-external' : 'user')));
|
|
524
|
+
}
|
|
525
|
+
static initialize(authService, dynamicViewService) {
|
|
526
|
+
authService.isLoading$.subscribe((isLoading) => {
|
|
527
|
+
if (isLoading) {
|
|
528
|
+
AuthLoadingScreenComponent.instance ?? (AuthLoadingScreenComponent.instance = dynamicViewService.createView(AuthLoadingScreenComponent));
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
AuthLoadingScreenComponent.instance?.destroy();
|
|
532
|
+
AuthLoadingScreenComponent.instance = null;
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
AuthLoadingScreenComponent.instance = null;
|
|
538
|
+
AuthLoadingScreenComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthLoadingScreenComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
539
|
+
AuthLoadingScreenComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: AuthLoadingScreenComponent, isStandalone: true, selector: "div.odx-auth-loading-screen", host: { properties: { "@hostAnimation": "true" } }, ngImport: i0, template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\"></ng-template>\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-loading-screen__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-loading-screen-animation .75s ease}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "component", type: IconComponent, selector: "odx-icon", inputs: ["inline", "size", "name", "iconSet"] }, { kind: "directive", type: LogoDirective, selector: "odx-logo", inputs: ["size", "variant"] }, { kind: "component", type: CircularProgressComponent, selector: "odx-circular-progress", inputs: ["stroke", "size", "value"] }, { kind: "directive", type: DynamicViewDirective, selector: "ng-template[odxDynamicView]", inputs: ["odxDynamicView", "odxDynamicViewInjector", "odxDynamicViewContext"] }], animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
540
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AuthLoadingScreenComponent, decorators: [{
|
|
541
|
+
type: Component,
|
|
542
|
+
args: [{ standalone: true, selector: 'div.odx-auth-loading-screen', imports: [CommonModule, ButtonComponent, IconComponent, LogoDirective, CircularProgressComponent, DynamicViewDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
543
|
+
'[@hostAnimation]': 'true',
|
|
544
|
+
}, animations: [trigger('hostAnimation', [transition(':leave', useAnimation(fadeOut()))])], template: "<div class=\"odx-auth-loading-screen__content\" odxLayout=\"grid 12 horizontal-center vertical-center gap-small\">\n <odx-logo size=\"large\"></odx-logo>\n <odx-circular-progress class=\"odx-auth-loading-screen__spinner\" value=\"-1\" size=\"medium\" stroke=\"3\">\n <odx-icon [name]=\"icon$ | async\" iconSet=\"core\"></odx-icon>\n </odx-circular-progress>\n <p class=\"odx-auth-loading-screen__message\" *ngIf=\"authConfig.loadingScreenMessage as content\">\n <ng-template [odxDynamicView]=\"content\"></ng-template>\n </p>\n</div>\n", styles: ["@keyframes odx-auth-loading-screen-animation{0%{opacity:0;transform:translate(-50%,-50%) scale(.9)}to{opacity:1;transform:translate(-50%,-50%)}}.odx-auth-loading-screen{--odx-c-highlight: var(--odx-c-primary);background-color:var(--odx-c-background-content);position:fixed;z-index:var(--odx-v-layer-5);inset:0}.odx-auth-loading-screen__content{top:50%;left:50%;transform:translate(-50%,-50%);position:absolute;animation:odx-auth-loading-screen-animation .75s ease}.odx-auth-loading-screen__message{text-align:center}.odx-auth-loading-screen__spinner{position:relative}.odx-auth-loading-screen__spinner .odx-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}\n"] }]
|
|
545
|
+
}] });
|
|
546
|
+
|
|
547
|
+
const loadingScreenPlugin = () => {
|
|
548
|
+
const { enableLoadingScreen, showRedirectOverlay } = injectAuthConfig();
|
|
549
|
+
const dynamicViewService = inject(DynamicViewService);
|
|
550
|
+
return (authService) => {
|
|
551
|
+
if (enableLoadingScreen || showRedirectOverlay) {
|
|
552
|
+
AuthLoadingScreenComponent.initialize(authService, dynamicViewService);
|
|
553
|
+
}
|
|
554
|
+
return of({});
|
|
555
|
+
};
|
|
556
|
+
};
|
|
557
|
+
|
|
512
558
|
function configureInterceptor() {
|
|
513
559
|
const { allowedUrls } = injectAuthConfig();
|
|
514
560
|
return {
|
|
@@ -518,11 +564,10 @@ function configureInterceptor() {
|
|
|
518
564
|
},
|
|
519
565
|
};
|
|
520
566
|
}
|
|
521
|
-
function
|
|
567
|
+
function initializeAuthErrorHandlers() {
|
|
522
568
|
const authService = inject(AuthService);
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
authService.errors$.pipe(tap((error) => injector.runInContext(() => errorHandler(error)))).subscribe();
|
|
569
|
+
const handler = handleAuthError(inject(ODX_AUTH_ERROR_HANDLERS));
|
|
570
|
+
authService.errors$.pipe(tap((error) => handler(error))).subscribe();
|
|
526
571
|
}
|
|
527
572
|
function initalizeAuthConfig() {
|
|
528
573
|
const { clientId, scopes, redirectPath, environment, postLogoutRedirectUrl, issuer, timeoutFactor, discoveryUrl } = injectAuthConfig();
|
|
@@ -552,13 +597,12 @@ function provideAuth(config) {
|
|
|
552
597
|
},
|
|
553
598
|
{
|
|
554
599
|
provide: ENVIRONMENT_INITIALIZER,
|
|
555
|
-
useValue:
|
|
600
|
+
useValue: initializeAuthErrorHandlers,
|
|
556
601
|
multi: true,
|
|
557
602
|
},
|
|
558
603
|
{
|
|
559
|
-
provide:
|
|
560
|
-
|
|
561
|
-
multi: true,
|
|
604
|
+
provide: ODX_AUTH_ERROR_HANDLERS,
|
|
605
|
+
useFactory: () => [offlineAuthErrorHandler, injectAuthConfig().errorHandler],
|
|
562
606
|
},
|
|
563
607
|
{
|
|
564
608
|
provide: APP_INITIALIZER,
|
|
@@ -567,11 +611,11 @@ function provideAuth(config) {
|
|
|
567
611
|
},
|
|
568
612
|
{
|
|
569
613
|
provide: OAuthStorage,
|
|
570
|
-
useFactory: () =>
|
|
614
|
+
useFactory: () => injectAuthConfig().storage ?? inject(WindowRef).nativeWindow.localStorage,
|
|
571
615
|
},
|
|
572
616
|
{
|
|
573
617
|
provide: ODX_AUTH_CORE_PLUGINS,
|
|
574
|
-
useValue: [coreIdentityPlugin],
|
|
618
|
+
useValue: [coreIdentityPlugin, loadingScreenPlugin],
|
|
575
619
|
},
|
|
576
620
|
]);
|
|
577
621
|
}
|
|
@@ -598,5 +642,5 @@ function unauthGuard(authorizedHandler, redirectTo) {
|
|
|
598
642
|
* Generated bundle index. Do not edit.
|
|
599
643
|
*/
|
|
600
644
|
|
|
601
|
-
export { AuthActionDirective, AuthComponent, AuthConfig, AuthDefaultConfig, AuthDirective, AuthHttpCache,
|
|
645
|
+
export { AuthActionDirective, AuthComponent, AuthConfig, AuthDefaultConfig, AuthDirective, AuthHttpCache, AuthLoadingScreenComponent, AuthModule, AuthPluginManager, AuthService, DEFAULT_AUTH_SCOPES, DEFAULT_ISSUERS, ODX_AUTH_CORE_PLUGINS, ODX_AUTH_ERROR_HANDLERS, ODX_AUTH_HTTP_CACHE_STORAGE, ODX_AUTH_PLUGINS, SignInDirective, SignOutDirective, authGuard, configureInterceptor, coreIdentityPlugin, createInitials, handleAuthError, initalizeAuthConfig, initializeAuthErrorHandlers, injectAuthConfig, loadingScreenPlugin, offlineAuthErrorHandler, provideAuth, provideAuthConfig, resolveEmail, resolveUsername, unauthGuard };
|
|
602
646
|
//# sourceMappingURL=odx-auth.mjs.map
|