Merged PR 1819: #4844 Implement dev-scanner configuration and enhance app initialization process

#4844 Implement dev-scanner configuration and enhance app initialization process
This commit is contained in:
Lorenz Hilpert
2024-11-13 17:09:34 +00:00
committed by Nino Righi
parent f2c95b6a16
commit 02bae79e4a
11 changed files with 100 additions and 30 deletions

View File

@@ -1,8 +1,9 @@
import { inject, Injectable } from '@angular/core';
import { EnvironmentService } from '@core/environment';
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
import { Observable } from 'rxjs';
import { ScanAdapter } from './scan-adapter';
import { Config } from '@core/config';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
@Injectable()
export class DevScanAdapter implements ScanAdapter {
@@ -10,11 +11,12 @@ export class DevScanAdapter implements ScanAdapter {
private _modal = inject(UiModalService);
private _config = inject(Config);
async init(): Promise<boolean> {
return Promise.resolve(false);
// return new Promise((resolve, reject) => {
// resolve(isDevMode());
// });
return new Promise((resolve, reject) => {
resolve(coerceBooleanProperty(this._config.get('dev-scanner')));
});
}
scan(): Observable<string> {

View File

@@ -37,7 +37,7 @@ export class ScanAdapterService {
for (const name of adapterOrder) {
adapter = this.getAdapter(name);
console.log('adapter', adapter);
if (adapter) {
break;
}

View File

@@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PlatformModule } from '@angular/cdk/platform';
import { Config, ConfigModule, JsonConfigLoader } from '@core/config';
import { AuthModule, AuthService } from '@core/auth';
import { AuthModule, AuthService, LoginStrategy } from '@core/auth';
import { CoreCommandModule } from '@core/command';
import { AppRoutingModule } from './app-routing.module';
@@ -45,21 +45,14 @@ import { firstValueFrom } from 'rxjs';
registerLocaleData(localeDe, localeDeExtra);
registerLocaleData(localeDe, 'de', localeDeExtra);
export function _appInitializerFactory(
config: Config,
auth: AuthService,
injector: Injector,
scanAdapter: ScanAdapterService,
nativeContainer: NativeContainerService,
networkStatus: NetworkStatusService,
) {
export function _appInitializerFactory(config: Config, injector: Injector) {
return async () => {
const statusElement = document.querySelector('#init-status');
const laoderElement = document.querySelector('#init-loader');
try {
let online = false;
const networkStatus = injector.get(NetworkStatusService);
while (!online) {
online = await firstValueFrom(networkStatus.online$);
@@ -72,19 +65,29 @@ export function _appInitializerFactory(
statusElement.innerHTML = 'Konfigurationen werden geladen...';
await config.init();
statusElement.innerHTML = 'Scanner wird initialisiert...';
const scanAdapter = injector.get(ScanAdapterService);
await scanAdapter.init();
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
const auth = injector.get(AuthService);
await auth.init();
if (auth.isAuthenticated()) {
statusElement.innerHTML = 'App wird initialisiert...';
const state = injector.get(RootStateService);
await state.init();
} else {
const strategy = injector.get(LoginStrategy);
await strategy.login();
}
statusElement.innerHTML = 'Native Container wird initialisiert...';
const nativeContainer = injector.get(NativeContainerService);
await nativeContainer.init();
statusElement.innerHTML = 'Scanner wird initialisiert...';
await scanAdapter.init();
} catch (error) {
laoderElement.remove();
statusElement.classList.add('text-xl');
@@ -160,7 +163,7 @@ export function _notificationsHubOptionsFactory(config: Config, auth: AuthServic
provide: APP_INITIALIZER,
useFactory: _appInitializerFactory,
multi: true,
deps: [Config, AuthService, Injector, ScanAdapterService, NativeContainerService, NetworkStatusService],
deps: [Config, Injector],
},
{
provide: NOTIFICATIONS_HUB_OPTIONS,

View File

@@ -0,0 +1 @@
export * from './network-status.service';

View File

@@ -4,6 +4,7 @@
"interval": 300000
},
"debug": true,
"dev-scanner": true,
"@cdn/product-image": {
"url": "https://produktbilder.paragon-data.net"
},

View File

@@ -3,7 +3,8 @@
"silentRefresh": {
"interval": 300000
},
"debug": true,
"debug": false,
"@cdn/product-image": {
"url": "https://produktbilder.paragon-data.net"
},

View File

@@ -26,6 +26,8 @@ export class AuthService {
console.log('SSO Token Expiration:', new Date(this._oAuthService.getAccessTokenExpiration()));
}
});
window['auth'] = this;
}
async init() {
@@ -44,13 +46,8 @@ export class AuthService {
this._oAuthService.tokenValidationHandler = new JwksValidationHandler();
this._oAuthService.setupAutomaticSilentRefresh();
try {
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
} catch (error) {
this.login();
throw error;
}
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
this._initialized.next(true);
}
@@ -99,9 +96,6 @@ export class AuthService {
async logout() {
await this._oAuthService.revokeTokenAndLogout();
// asapScheduler.schedule(() => {
// window.location.reload();
// }, 250);
}
hasRole(role: string | string[]) {

View File

@@ -1,3 +1,4 @@
export * from './auth.module';
export * from './auth.service';
export * from './if-role.directive';
export * from './login.strategy';

View File

@@ -0,0 +1,63 @@
import { ScanAdapterService } from '@adapter/scan';
import { inject, Injectable } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { EnvironmentService } from '@core/environment';
import { UiConfirmModalComponent, UiModalResult, UiModalService } from '@ui/modal';
import { injectNetworkStatus$ } from '../../app/services';
import { AuthService } from './auth.service';
import { AuthService as IsaAuthService } from '@swagger/isa';
import { firstValueFrom, lastValueFrom } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class LoginStrategy {
private readonly environmentService = inject(EnvironmentService);
private readonly networkStatus = toSignal(injectNetworkStatus$());
private readonly modal = inject(UiModalService);
private readonly scanAdapterService = inject(ScanAdapterService);
private readonly isaAuthService = inject(IsaAuthService);
private readonly authService = inject(AuthService);
async login(title = 'Anmeldung') {
let loginModalResult: UiModalResult<boolean>;
try {
if (this.environmentService.isMobileDevice()) {
do {
const loginModal = this.modal.open({
content: UiConfirmModalComponent,
title,
data: {
message: 'Bitte wählen Sie die Anmeldeoption aus.',
rejectLabel: 'Anmeldung mit Logindaten',
confirmLabel: 'Anmeldung mit Keycard',
},
});
loginModalResult = await loginModal.afterClosed$.toPromise();
} while (this.networkStatus() === 'offline');
}
} catch (error) {}
try {
if (loginModalResult.data) {
const result = await lastValueFrom(this.scanAdapterService.scan());
if (typeof result === 'string') {
const res = await firstValueFrom(
this.isaAuthService.AuthLogin({
code: result,
application: 'isa',
hostname: location.host,
}),
);
if (res.token) {
this.authService.setKeyCardToken(res.token);
}
}
}
} catch (error) {}
await this.authService.login();
}
}

View File

@@ -62,6 +62,10 @@ export class EnvironmentService {
matchDesktopXXLarge$ = this._breakpointObserver.observe(MATCH_DESKTOP_XXLARGE).pipe(map((result) => result.matches));
isMobileDevice(): boolean {
return this._platform.ANDROID || this._platform.IOS;
}
/**
* @deprecated Use `matchDesktopSmall` or 'matchDesktop' instead.
*/

View File

@@ -1,7 +1,7 @@
import { Component, ChangeDetectionStrategy, OnInit, inject } from '@angular/core';
import { first, map, retry } from 'rxjs/operators';
import { ShellService } from '../shell.service';
import { BehaviorSubject, Observable, combineLatest } from 'rxjs';
import { BehaviorSubject, Observable, asapScheduler, combineLatest } from 'rxjs';
import { MessageBoardItemDTO, NotificationsHub } from '@hub/notifications';
import { UiModalService } from '@ui/modal';
import { ModalNotificationsComponent } from '@modal/notifications';