@@ -1,7 +1,7 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, HostListener } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationEnd, Router, RouterOutlet } from '@angular/router';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
|
||||
|
||||
import { filter } from 'rxjs/operators';
|
||||
import build from '../build';
|
||||
@@ -45,14 +45,38 @@ export class AppComponent {
|
||||
this.actualRoute = currentRoute.snapshot.url[0].path;
|
||||
});
|
||||
}
|
||||
ngOnInit() {}
|
||||
ngOnInit() {
|
||||
// Überwache Keycloak-Events, um den Token-Refresh zu kontrollieren
|
||||
this.keycloakService.keycloakEvents$.subscribe({
|
||||
next: event => {
|
||||
if (event.type === KeycloakEventType.OnTokenExpired) {
|
||||
// Wenn der Token abgelaufen ist, versuchen wir einen Refresh
|
||||
this.handleTokenExpiration();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
private async handleTokenExpiration(): Promise<void> {
|
||||
try {
|
||||
// Versuche, den Token zu erneuern
|
||||
const refreshed = await this.keycloakService.updateToken();
|
||||
if (!refreshed) {
|
||||
// Wenn der Token nicht erneuert werden kann, leite zur Login-Seite weiter
|
||||
this.keycloakService.login({
|
||||
redirectUri: window.location.href, // oder eine andere Seite
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.error === 'invalid_grant' && error.error_description === 'Token is not active') {
|
||||
// Hier wird der Fehler "invalid_grant" abgefangen
|
||||
this.keycloakService.login({
|
||||
redirectUri: window.location.href,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@HostListener('window:keydown', ['$event'])
|
||||
handleKeyboardEvent(event: KeyboardEvent) {
|
||||
// this.router.events.subscribe(event => {
|
||||
// if (event instanceof NavigationEnd) {
|
||||
// initFlowbite();
|
||||
// }
|
||||
// });
|
||||
if (event.shiftKey && event.ctrlKey && event.key === 'V') {
|
||||
this.showVersionDialog();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APP_INITIALIZER, ApplicationConfig } from '@angular/core';
|
||||
import { APP_INITIALIZER, ApplicationConfig, ErrorHandler } from '@angular/core';
|
||||
import { provideRouter, withEnabledBlockingInitialNavigation, withInMemoryScrolling } from '@angular/router';
|
||||
|
||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||
@@ -9,11 +9,10 @@ import { provideQuillConfig } from 'ngx-quill';
|
||||
import { provideShareButtonsOptions, SharerMethods, withConfig } from 'ngx-sharebuttons';
|
||||
import { shareIcons } from 'ngx-sharebuttons/icons';
|
||||
import { provideNgxStripe } from 'ngx-stripe';
|
||||
import { environment } from '../environments/environment';
|
||||
import { customKeycloakAdapter } from '../keycloak';
|
||||
import { routes } from './app.routes';
|
||||
import { LoadingInterceptor } from './interceptors/loading.interceptor';
|
||||
import { TimeoutInterceptor } from './interceptors/timeout.interceptor';
|
||||
import { GlobalErrorHandler } from './services/globalErrorHandler';
|
||||
import { KeycloakInitializerService } from './services/keycloak-initializer.service';
|
||||
import { SelectOptionsService } from './services/select-options.service';
|
||||
import { createLogger } from './utils/utils';
|
||||
@@ -25,9 +24,9 @@ export const appConfig: ApplicationConfig = {
|
||||
{ provide: KeycloakService },
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
// useFactory: initializeKeycloak,
|
||||
//useFactory: initializeKeycloak,
|
||||
useFactory: initializeKeycloak3,
|
||||
// useFactory: initializeKeycloak1,
|
||||
//useFactory: initializeKeycloak2,
|
||||
useFactory: initializeKeycloak,
|
||||
multi: true,
|
||||
//deps: [KeycloakService],
|
||||
deps: [KeycloakInitializerService],
|
||||
@@ -64,6 +63,7 @@ export const appConfig: ApplicationConfig = {
|
||||
imageSize: 'cover',
|
||||
} as GalleryConfig,
|
||||
},
|
||||
{ provide: ErrorHandler, useClass: GlobalErrorHandler }, // Registriere den globalen ErrorHandler
|
||||
provideShareButtonsOptions(
|
||||
shareIcons(),
|
||||
withConfig({
|
||||
@@ -100,47 +100,47 @@ function initServices(selectOptions: SelectOptionsService) {
|
||||
await selectOptions.init();
|
||||
};
|
||||
}
|
||||
export function initializeKeycloak3(keycloak: KeycloakInitializerService) {
|
||||
export function initializeKeycloak(keycloak: KeycloakInitializerService) {
|
||||
return () => keycloak.initialize();
|
||||
}
|
||||
|
||||
export function initializeKeycloak2(keycloak: KeycloakService): () => Promise<void> {
|
||||
return async () => {
|
||||
const { url, realm, clientId } = environment.keycloak;
|
||||
const adapter = customKeycloakAdapter(() => keycloak.getKeycloakInstance(), {});
|
||||
if (window.location.search.length > 0) {
|
||||
sessionStorage.setItem('SEARCH', window.location.search);
|
||||
}
|
||||
const { host, hostname, href, origin, pathname, port, protocol, search } = window.location;
|
||||
await keycloak.init({
|
||||
config: { url, realm, clientId },
|
||||
initOptions: {
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri: window.location.hostname === 'localhost' ? `${window.location.origin}/assets/silent-check-sso.html` : `${window.location.origin}/dealerweb/assets/silent-check-sso.html`,
|
||||
adapter,
|
||||
redirectUri: `${origin}${pathname}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
function initializeKeycloak(keycloak: KeycloakService) {
|
||||
return async () => {
|
||||
logger.info(`###>calling keycloakService init ...`);
|
||||
const authenticated = await keycloak.init({
|
||||
config: {
|
||||
url: environment.keycloak.url,
|
||||
realm: environment.keycloak.realm,
|
||||
clientId: environment.keycloak.clientId,
|
||||
},
|
||||
initOptions: {
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||
},
|
||||
bearerExcludedUrls: ['/assets'],
|
||||
shouldUpdateToken(request) {
|
||||
return !request.headers.get('token-update') === false;
|
||||
},
|
||||
});
|
||||
logger.info(`+++>${authenticated}`);
|
||||
};
|
||||
}
|
||||
// export function initializeKeycloak1(keycloak: KeycloakService): () => Promise<void> {
|
||||
// return async () => {
|
||||
// const { url, realm, clientId } = environment.keycloak;
|
||||
// const adapter = customKeycloakAdapter(() => keycloak.getKeycloakInstance(), {});
|
||||
// if (window.location.search.length > 0) {
|
||||
// sessionStorage.setItem('SEARCH', window.location.search);
|
||||
// }
|
||||
// const { host, hostname, href, origin, pathname, port, protocol, search } = window.location;
|
||||
// await keycloak.init({
|
||||
// config: { url, realm, clientId },
|
||||
// initOptions: {
|
||||
// onLoad: 'check-sso',
|
||||
// silentCheckSsoRedirectUri: window.location.hostname === 'localhost' ? `${window.location.origin}/assets/silent-check-sso.html` : `${window.location.origin}/dealerweb/assets/silent-check-sso.html`,
|
||||
// adapter,
|
||||
// redirectUri: `${origin}${pathname}`,
|
||||
// },
|
||||
// });
|
||||
// };
|
||||
// }
|
||||
// function initializeKeycloak2(keycloak: KeycloakService) {
|
||||
// return async () => {
|
||||
// logger.info(`###>calling keycloakService init ...`);
|
||||
// const authenticated = await keycloak.init({
|
||||
// config: {
|
||||
// url: environment.keycloak.url,
|
||||
// realm: environment.keycloak.realm,
|
||||
// clientId: environment.keycloak.clientId,
|
||||
// },
|
||||
// initOptions: {
|
||||
// onLoad: 'check-sso',
|
||||
// silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||
// },
|
||||
// bearerExcludedUrls: ['/assets'],
|
||||
// shouldUpdateToken(request) {
|
||||
// return !request.headers.get('token-update') === false;
|
||||
// },
|
||||
// });
|
||||
// logger.info(`+++>${authenticated}`);
|
||||
// };
|
||||
// }
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
<div class="p-4 md:p-5">
|
||||
<form class="space-y-4" action="#">
|
||||
<div>
|
||||
<app-validated-input label="Your Email" name="email" [(ngModel)]="shareByEMail.email"></app-validated-input>
|
||||
<app-validated-input label="Your Email" name="yourEmail" [(ngModel)]="shareByEMail.yourEmail"></app-validated-input>
|
||||
</div>
|
||||
<div>
|
||||
<app-validated-input label="Your Name" name="name" [(ngModel)]="shareByEMail.name"></app-validated-input>
|
||||
<app-validated-input label="Your Name" name="yourName" [(ngModel)]="shareByEMail.yourName"></app-validated-input>
|
||||
</div>
|
||||
<div>
|
||||
<app-validated-input label="Your Friend's EMail" name="recipientEmail" [(ngModel)]="shareByEMail.recipientEmail"></app-validated-input>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div
|
||||
[id]="id"
|
||||
role="tooltip"
|
||||
class="max-w-72 w-max absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"
|
||||
class="max-w-72 w-max absolute z-50 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"
|
||||
>
|
||||
{{ text }}
|
||||
<div class="tooltip-arrow" data-popper-arrow></div>
|
||||
|
||||
@@ -110,7 +110,6 @@ export class DetailsBusinessListingComponent {
|
||||
this.mailinfo.listing = this.listing;
|
||||
await this.mailService.mail(this.mailinfo);
|
||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
} catch (error) {
|
||||
this.messageService.addMessage({
|
||||
severity: 'danger',
|
||||
@@ -121,6 +120,9 @@ export class DetailsBusinessListingComponent {
|
||||
this.validationMessagesService.updateMessages(error.error.message);
|
||||
}
|
||||
}
|
||||
if (this.user) {
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
}
|
||||
}
|
||||
get listingDetails() {
|
||||
let typeOfRealEstate = '';
|
||||
@@ -158,8 +160,8 @@ export class DetailsBusinessListingComponent {
|
||||
}
|
||||
async showShareByEMail() {
|
||||
const result = await this.emailService.showShareByEMail({
|
||||
email: this.user.email,
|
||||
name: `${this.user.firstname} ${this.user.lastname}`,
|
||||
yourEmail: this.user ? this.user.email : null,
|
||||
yourName: this.user ? `${this.user.firstname} ${this.user.lastname}` : null,
|
||||
url: environment.mailinfoUrl,
|
||||
listingTitle: this.listing.title,
|
||||
id: this.listing.id,
|
||||
|
||||
@@ -143,7 +143,6 @@ export class DetailsCommercialPropertyListingComponent {
|
||||
this.mailinfo.listing = this.listing;
|
||||
await this.mailService.mail(this.mailinfo);
|
||||
this.messageService.addMessage({ severity: 'success', text: 'Your message has been sent to the creator of the listing', duration: 3000 });
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
} catch (error) {
|
||||
this.messageService.addMessage({
|
||||
severity: 'danger',
|
||||
@@ -154,6 +153,9 @@ export class DetailsCommercialPropertyListingComponent {
|
||||
this.validationMessagesService.updateMessages(error.error.message);
|
||||
}
|
||||
}
|
||||
if (this.user) {
|
||||
this.mailinfo = createMailInfo(this.user);
|
||||
}
|
||||
}
|
||||
containsError(fieldname: string) {
|
||||
return this.errorResponse?.fields.map(f => f.fieldname).includes(fieldname);
|
||||
@@ -170,8 +172,8 @@ export class DetailsCommercialPropertyListingComponent {
|
||||
}
|
||||
async showShareByEMail() {
|
||||
const result = await this.emailService.showShareByEMail({
|
||||
email: this.user.email,
|
||||
name: `${this.user.firstname} ${this.user.lastname}`,
|
||||
yourEmail: this.user.email,
|
||||
yourName: `${this.user.firstname} ${this.user.lastname}`,
|
||||
url: environment.mailinfoUrl,
|
||||
listingTitle: this.listing.title,
|
||||
id: this.listing.id,
|
||||
|
||||
24
bizmatch/src/app/services/globalErrorHandler.ts
Normal file
24
bizmatch/src/app/services/globalErrorHandler.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { ErrorHandler, Injectable } from '@angular/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalErrorHandler implements ErrorHandler {
|
||||
constructor(private keycloakService: KeycloakService) {}
|
||||
|
||||
handleError(error: any): void {
|
||||
// Prüfe, ob es sich um einen HttpErrorResponse handelt
|
||||
if (error instanceof HttpErrorResponse) {
|
||||
// Prüfe, ob es ein 401 Unauthorized Fehler ist
|
||||
if (error.status === 401) {
|
||||
// Führe den Login-Prozess über Keycloak aus
|
||||
this.keycloakService.login({
|
||||
redirectUri: window.location.href, // oder eine benutzerdefinierte URL
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Weiterhin normale Fehlerbehandlung
|
||||
console.error('Ein Fehler ist aufgetreten:', error);
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,8 @@ export class KeycloakInitializerService {
|
||||
initOptions: {
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||
// flow: 'implicit',
|
||||
},
|
||||
bearerExcludedUrls: ['/assets'],
|
||||
});
|
||||
this.initialized = true;
|
||||
resolve(true);
|
||||
@@ -30,35 +30,5 @@ export class KeycloakInitializerService {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
// if (this.initialized) {
|
||||
// return;
|
||||
// }
|
||||
// logger.info(`###>calling keycloakService init ...`);
|
||||
// const authenticated = await this.keycloakService.init({
|
||||
// config: {
|
||||
// url: environment.keycloak.url,
|
||||
// realm: environment.keycloak.realm,
|
||||
// clientId: environment.keycloak.clientId,
|
||||
// },
|
||||
// initOptions: {
|
||||
// onLoad: 'check-sso',
|
||||
// silentCheckSsoRedirectUri: (<any>window).location.origin + '/assets/silent-check-sso.html',
|
||||
// // flow: 'implicit',
|
||||
// },
|
||||
// // initOptions: {
|
||||
// // pkceMethod: 'S256',
|
||||
// // redirectUri: environment.keycloak.redirectUri,
|
||||
// // checkLoginIframe: false,
|
||||
// // },
|
||||
// });
|
||||
// logger.info(`+++>authenticated: ${authenticated}`);
|
||||
// const token = await this.keycloakService.getToken();
|
||||
// logger.info(`--->${token}`);
|
||||
|
||||
// this.initialized = true;
|
||||
}
|
||||
|
||||
// isInitialized(): boolean {
|
||||
// return this.initialized;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ export class ListingsService {
|
||||
}
|
||||
}
|
||||
async deleteBusinessListing(id: string) {
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/business/${id}`));
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/business/listing/${id}`));
|
||||
}
|
||||
async deleteCommercialPropertyListing(id: string, imagePath: string) {
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/${id}/${imagePath}`));
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/commercialProperty/listing/${id}/${imagePath}`));
|
||||
}
|
||||
async removeFavorite(id: string, listingsCategory?: 'business' | 'commercialProperty') {
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorites/${id}`));
|
||||
await lastValueFrom(this.http.delete<ListingType>(`${this.apiBaseUrl}/bizmatch/listings/${listingsCategory}/favorite/${id}`));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user