added tenant code to url
This commit is contained in:
parent
db25687dd5
commit
a4df13a051
|
@ -3,12 +3,11 @@ import { RouterModule, Routes } from '@angular/router';
|
|||
import { AppPermission } from './core/common/enum/permission.enum';
|
||||
import { BreadcrumbService } from './ui/misc/breadcrumb/breadcrumb.service';
|
||||
import { ReloadHelperComponent } from './ui/misc/reload-helper/reload-helper.component';
|
||||
import { DepositOauth2DialogComponent } from './ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo:'home',
|
||||
redirectTo: 'home',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
|
@ -35,7 +34,7 @@ const appRoutes: Routes = [
|
|||
},
|
||||
{
|
||||
path: 'explore-descriptions',
|
||||
loadChildren: () => import('./ui/description/description.module').then(m => m.DescriptionModule),
|
||||
loadChildren: () => import('./ui/description/description.module').then(m => m.PublicDescriptionModule),
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -60,7 +59,7 @@ const appRoutes: Routes = [
|
|||
},
|
||||
{
|
||||
path: 'explore-plans',
|
||||
loadChildren: () => import('./ui/dmp/dmp.module').then(m => m.DmpModule),
|
||||
loadChildren: () => import('./ui/dmp/dmp.module').then(m => m.PublicDmpModule),
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -183,14 +182,6 @@ const appRoutes: Routes = [
|
|||
title: 'GENERAL.TITLES.COOKIES-POLICY'
|
||||
}
|
||||
},
|
||||
|
||||
// {
|
||||
// path: 'splash',
|
||||
// loadChildren: () => import('./ui/splash/splash.module').then(m => m.SplashModule),
|
||||
// data: {
|
||||
// breadcrumb: true
|
||||
// }
|
||||
// },
|
||||
{
|
||||
path: 'unauthorized',
|
||||
loadChildren: () => import('./ui/misc/unauthorized/unauthorized.module').then(m => m.UnauthorizedModule),
|
||||
|
@ -387,8 +378,18 @@ const appRoutes: Routes = [
|
|||
}
|
||||
];
|
||||
|
||||
const tenantEnrichedRoutes: Routes = [
|
||||
{
|
||||
path: 't/:tenant_code',
|
||||
children: [
|
||||
...appRoutes
|
||||
]
|
||||
},
|
||||
...appRoutes
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(appRoutes, {})],
|
||||
imports: [RouterModule.forRoot(tenantEnrichedRoutes, {})],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
|
|
|
@ -3,7 +3,7 @@ import { of as observableOf, Subscription } from 'rxjs';
|
|||
|
||||
import { switchMap, filter, map, takeUntil } from 'rxjs/operators';
|
||||
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { AuthService, LoginStatus } from './core/services/auth/auth.service';
|
||||
import { CultureService } from './core/services/culture/culture-service';
|
||||
|
@ -23,6 +23,7 @@ import { TenantConfigurationService } from './core/services/tenant-configuration
|
|||
import { TenantConfigurationType } from './core/common/enum/tenant-configuration-type';
|
||||
import { CssColorsTenantConfiguration, TenantConfiguration } from './core/model/tenant-configuaration/tenant-configuration';
|
||||
import { nameof } from 'ts-simple-nameof';
|
||||
import { TenantHandlingService } from './core/services/tenant/tenant-handling.service';
|
||||
|
||||
|
||||
declare const gapi: any;
|
||||
|
@ -43,7 +44,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
onlySplash = true;
|
||||
showOnlyRouterOutlet = false;
|
||||
|
||||
@ViewChild('sidenav') sidenav:MatSidenav;
|
||||
@ViewChild('sidenav') sidenav: MatSidenav;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
|
@ -61,7 +62,8 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
private location: Location,
|
||||
private matomoService: MatomoService,
|
||||
private tenantConfigurationService: TenantConfigurationService,
|
||||
private sidenavService: SideNavService
|
||||
private sidenavService: SideNavService,
|
||||
private tenantHandlingService: TenantHandlingService
|
||||
) {
|
||||
this.initializeServices();
|
||||
this.matomoService.init();
|
||||
|
@ -69,30 +71,30 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
ngAfterViewInit(): void {
|
||||
setTimeout(() => {
|
||||
this.sideNavSubscription = this.sidenavService.status().subscribe(isopen=>{
|
||||
this.sideNavSubscription = this.sidenavService.status().subscribe(isopen => {
|
||||
const hamburger = document.getElementById('hamburger');
|
||||
if(isopen){
|
||||
if (isopen) {
|
||||
//update value of hamburfer
|
||||
if(!hamburger){//try later
|
||||
if (!hamburger) {//try later
|
||||
setTimeout(() => {
|
||||
const hamburger = document.getElementById('hamburger');
|
||||
if(hamburger){
|
||||
if (hamburger) {
|
||||
hamburger.classList.add('change');
|
||||
}
|
||||
}, 300);
|
||||
}else{
|
||||
} else {
|
||||
hamburger.classList.add('change');
|
||||
}
|
||||
this.sidenav.open()
|
||||
}else{//closed
|
||||
if(!hamburger){//try later
|
||||
} else {//closed
|
||||
if (!hamburger) {//try later
|
||||
setTimeout(() => {
|
||||
const hamburger = document.getElementById('hamburger');
|
||||
if(hamburger){
|
||||
if (hamburger) {
|
||||
hamburger.classList.remove('change');
|
||||
}
|
||||
}, 300);
|
||||
}else{
|
||||
} else {
|
||||
hamburger.classList.remove('change');
|
||||
}
|
||||
this.sidenav.close();
|
||||
|
@ -114,7 +116,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
if (this.location.path() === '') {
|
||||
if (!this.configurationService.useSplash) {
|
||||
this.onlySplash = false;
|
||||
this.router.navigate(['/reload']).then(() => this.router.navigate(['/home']));
|
||||
this.router.navigate(['/home']);
|
||||
} else {
|
||||
this.onlySplash = true;
|
||||
this.router.navigate(['/reload']).then(() => this.router.navigate(['/splash']));
|
||||
|
@ -126,7 +128,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
}
|
||||
if (!this.cookieService.check("cookiesConsent")) {
|
||||
// this.cookieService.set("cookiesConsent", "false", 356);
|
||||
this.cookieService.set("cookiesConsent", "false", 356,null,null,false, 'Lax');
|
||||
this.cookieService.set("cookiesConsent", "false", 356, null, null, false, 'Lax');
|
||||
|
||||
}
|
||||
|
||||
|
@ -171,17 +173,32 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
return { title: child.snapshot.data['title'], usePrefix: usePrefix };
|
||||
}
|
||||
}
|
||||
return { title: appTitle, usePrefix: true};
|
||||
return { title: appTitle, usePrefix: true };
|
||||
})
|
||||
).subscribe((titleOptions: { title: string, usePrefix: boolean}) => {
|
||||
).subscribe((titleOptions: { title: string, usePrefix: boolean }) => {
|
||||
this.translateTitle(titleOptions.title, titleOptions.usePrefix);
|
||||
this.translate.onLangChange.subscribe(() => this.translateTitle(titleOptions.title, titleOptions.usePrefix));
|
||||
});
|
||||
|
||||
|
||||
this.router
|
||||
.events.pipe(
|
||||
filter(event => event instanceof NavigationEnd)
|
||||
)
|
||||
.subscribe((event: NavigationStart) => {
|
||||
const enrichedUrl = this.tenantHandlingService.getUrlEnrichedWithTenantCode(event.url, this.authentication.selectedTenant() ?? 'default');
|
||||
if (event.url != enrichedUrl) {
|
||||
this.router.navigate([enrichedUrl]);
|
||||
console.log('enriched')
|
||||
console.log(event.url)
|
||||
console.log(enrichedUrl)
|
||||
}
|
||||
});
|
||||
|
||||
this.statusChangeSubscription = this.ccService.statusChange$.subscribe((event: NgcStatusChangeEvent) => {
|
||||
if (event.status == "dismiss") {
|
||||
// this.cookieService.set("cookiesConsent", "true", 365);
|
||||
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
|
||||
this.cookieService.set("cookiesConsent", "true", 356, null, null, false, 'Lax');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -226,7 +243,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
|||
|
||||
ngOnDestroy() {
|
||||
this.statusChangeSubscription.unsubscribe();
|
||||
if(this.sideNavSubscription){
|
||||
if (this.sideNavSubscription) {
|
||||
this.sideNavSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import { CoreAnnotationServiceModule } from 'annotation-service/services/core-se
|
|||
import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module';
|
||||
import { DepositOauth2DialogModule } from './ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module';
|
||||
import { AnalyticsService } from './core/services/matomo/analytics-service';
|
||||
import { TenantHandlingService } from './core/services/tenant/tenant-handling.service';
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
export function HttpLoaderFactory(languageHttpService: LanguageHttpService) {
|
||||
|
@ -82,7 +83,7 @@ const appearance: MatFormFieldDefaultOptions = {
|
|||
// appearance: 'standard'
|
||||
};
|
||||
|
||||
export function InstallationConfigurationFactory(appConfig: ConfigurationService, keycloak: KeycloakService, authService: AuthService, languageService: LanguageService) {
|
||||
export function InstallationConfigurationFactory(appConfig: ConfigurationService, keycloak: KeycloakService, authService: AuthService, languageService: LanguageService, tenantHandlingService:TenantHandlingService) {
|
||||
return () => appConfig.loadConfiguration().then(() => {
|
||||
return languageService.loadAvailableLanguages().toPromise();
|
||||
}).then(x => keycloak.init({
|
||||
|
@ -109,8 +110,10 @@ export function InstallationConfigurationFactory(appConfig: ConfigurationService
|
|||
InterceptorType.UnauthorizedResponse,
|
||||
]
|
||||
};
|
||||
|
||||
const tenantCode = tenantHandlingService.extractTenantCodeFromUrlPath(window.location.pathname) ?? authService.selectedTenant() ?? 'default';
|
||||
const tokenPromise = keycloak.getToken();
|
||||
return authService.prepareAuthRequest(from(tokenPromise), { params }).toPromise().catch(error => authService.onAuthenticateError(error));
|
||||
return authService.prepareAuthRequest(from(tokenPromise), tenantCode, { params }).toPromise().catch(error => authService.onAuthenticateError(error));
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ import { VisibilityRulesService } from '@app/ui/description/editor/description-f
|
|||
import { StorageFileService } from './services/storage-file/storage-file.service';
|
||||
import { TenantConfigurationService } from './services/tenant-configuration/tenant-configuration.service';
|
||||
import { DefaultUserLocaleService } from './services/default-user-locale/default-user-locale.service';
|
||||
import { TenantHandlingService } from './services/tenant/tenant-handling.service';
|
||||
//
|
||||
//
|
||||
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
||||
|
@ -109,7 +110,8 @@ export class CoreServiceModule {
|
|||
PrefillingSourceService,
|
||||
VisibilityRulesService,
|
||||
TenantConfigurationService,
|
||||
StorageFileService
|
||||
StorageFileService,
|
||||
TenantHandlingService
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -154,11 +154,11 @@ export class AuthService extends BaseService {
|
|||
public isLoggedIn(): boolean {
|
||||
return this.authState();
|
||||
}
|
||||
public prepareAuthRequest(observable: Observable<string>, httpParams?: Object): Observable<boolean> {
|
||||
public prepareAuthRequest(observable: Observable<string>, tenantCode: string, httpParams?: Object): Observable<boolean> {
|
||||
return observable.pipe(
|
||||
map((x) => this.currentAuthenticationToken(x)),
|
||||
exhaustMap(() => forkJoin([
|
||||
this.accessToken ? this.ensureTenant() : of(false),
|
||||
this.accessToken ? this.ensureTenant(tenantCode ?? this.selectedTenant() ?? 'default') : of(false),
|
||||
this.accessToken ? this.principalService.me(httpParams) : of(null),
|
||||
])),
|
||||
map((item) => {
|
||||
|
@ -176,10 +176,10 @@ export class AuthService extends BaseService {
|
|||
);
|
||||
}
|
||||
|
||||
public ensureTenant(): Observable<string> {
|
||||
if (!this.selectedTenant()) {
|
||||
this.selectedTenant('default');
|
||||
}
|
||||
private ensureTenant(tenantCode: string): Observable<string> {
|
||||
// if (!this.selectedTenant()) {
|
||||
// this.selectedTenant('default');
|
||||
// }
|
||||
const params = new BaseHttpParams();
|
||||
params.interceptorContext = {
|
||||
excludedInterceptors: [InterceptorType.TenantHeaderInterceptor]
|
||||
|
@ -188,16 +188,21 @@ export class AuthService extends BaseService {
|
|||
map(
|
||||
(myTenants) => {
|
||||
if (myTenants) {
|
||||
if (this.selectedTenant()) {
|
||||
if (myTenants.findIndex(x => x.code.toLocaleLowerCase() == this.selectedTenant().toLocaleLowerCase()) < 0) {
|
||||
if (myTenants.some(x => x.code.toLocaleLowerCase() == tenantCode.toLocaleLowerCase())) {
|
||||
this.selectedTenant(tenantCode);
|
||||
} else {
|
||||
this.selectedTenant(null);
|
||||
}
|
||||
}
|
||||
if (!this.selectedTenant()) {
|
||||
if (myTenants.length > 0) {
|
||||
this.selectedTenant(myTenants[0]?.code);
|
||||
}
|
||||
}
|
||||
// if (this.selectedTenant()) {
|
||||
// if (myTenants.findIndex(x => x.code.toLocaleLowerCase() == this.selectedTenant().toLocaleLowerCase()) < 0) {
|
||||
// this.selectedTenant(null);
|
||||
// }
|
||||
// }
|
||||
// if (!this.selectedTenant()) {
|
||||
// if (myTenants.length > 0) {
|
||||
// this.selectedTenant(myTenants[0]?.code);
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
this.selectedTenant(null);
|
||||
}
|
||||
|
@ -326,6 +331,7 @@ export class AuthService extends BaseService {
|
|||
|
||||
return this.prepareAuthRequest(
|
||||
from(this.keycloakService.getToken()),
|
||||
this.selectedTenant(),
|
||||
httpParams
|
||||
)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
|
|
|
@ -57,21 +57,34 @@ export class CultureService {
|
|||
// Set angular locale based on user selection.
|
||||
// This is a very hacky way to map cultures with angular cultures, since there is no mapping. We first try to
|
||||
// use the culture with the specialization (ex en-US), and if not exists we import the base culture (first part).
|
||||
let locale = newCulture.name;
|
||||
import(`/node_modules/@angular/common/locales/${locale}.mjs`).catch(reason => {
|
||||
this.logger.error('Could not load locale: ' + locale);
|
||||
}).then(selectedLocale => {
|
||||
if (selectedLocale) {
|
||||
registerLocaleData(selectedLocale.default);
|
||||
} else {
|
||||
locale = newCulture.name.split('-')[0];
|
||||
import(`/node_modules/@angular/common/locales/${locale}.mjs`).catch(reason => {
|
||||
this.logger.error('Could not load locale: ' + locale);
|
||||
}).then(selectedDefaultLocale => {
|
||||
registerLocaleData(selectedDefaultLocale.default);
|
||||
});
|
||||
}
|
||||
});
|
||||
// let locale = newCulture.name;
|
||||
// const base = import(
|
||||
// /* webpackExclude: /\.d\.ts$/ */
|
||||
// /* webpackMode: "lazy-once" */
|
||||
// /* webpackChunkName: "i18n-base" */
|
||||
// `@angular/common/locales/${locale}.mjs`)//.then(m => m[basePkg]);
|
||||
|
||||
// const extra = import(
|
||||
// /* webpackExclude: /\.d\.ts$/ */
|
||||
// /* webpackMode: "lazy-once" */
|
||||
// /* webpackChunkName: "i18n-extra" */
|
||||
// `@angular/common/locales/extra/${locale.split('-')[0]}.mjs`)//.then(m => m[extraPkg]);
|
||||
|
||||
|
||||
// import(`/node_modules/ @angular/common/locales/${locale}.mjs`).catch(reason => {
|
||||
// this.logger.error('Could not load locale: ' + locale);
|
||||
// }).then(selectedLocale => {
|
||||
// if (selectedLocale) {
|
||||
// registerLocaleData(selectedLocale.default);
|
||||
// } else {
|
||||
// locale = newCulture.name.split('-')[0];
|
||||
// import(`/node_modules/@angular/common/locales/${locale}.mjs`).catch(reason => {
|
||||
// this.logger.error('Could not load locale: ' + locale);
|
||||
// }).then(selectedDefaultLocale => {
|
||||
// registerLocaleData(selectedDefaultLocale.default);
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
getCultureChangeObservable(): Observable<CultureInfo> {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import { DOCUMENT, LocationStrategy } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { PRIMARY_OUTLET, Router, UrlSegment, UrlSegmentGroup, UrlTree } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class TenantHandlingService {
|
||||
|
||||
constructor(
|
||||
@Inject(DOCUMENT) private readonly document: Document,
|
||||
private readonly locationStrategy: LocationStrategy,
|
||||
private readonly router: Router,
|
||||
) {
|
||||
}
|
||||
|
||||
extractTenantCodeFromUrlPath(path: string): string {
|
||||
//Searches for "/t/<tenant_code>/" in a url;
|
||||
const tenantRegex = new RegExp("\/t\/([^\/]+)");
|
||||
const regexResult = tenantRegex.exec(path);
|
||||
let tenantCode = null;
|
||||
if (Array.isArray(regexResult) && regexResult.length > 0) {
|
||||
tenantCode = regexResult[1];
|
||||
}
|
||||
return tenantCode;
|
||||
}
|
||||
|
||||
getCurrentUrlEnrichedWithTenantCode(tenantCode: string, withOrigin: boolean) {
|
||||
const path = this.getUrlEnrichedWithTenantCode(this.router.routerState.snapshot.url, tenantCode)
|
||||
return withOrigin ? this.getBaseUrl() + path.substring(1) : path;
|
||||
}
|
||||
|
||||
getUrlEnrichedWithTenantCode(url: string, tenantCode: string) {
|
||||
|
||||
const urlTree: UrlTree = this.router.parseUrl(url);
|
||||
const urlSegmentGroup: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET];
|
||||
const urlSegments: UrlSegment[] = urlSegmentGroup.segments;
|
||||
|
||||
const tenantParamIndex = urlSegments.findIndex(x => x.path == 't');
|
||||
if (tenantParamIndex >= 0) {
|
||||
|
||||
if (tenantCode == 'default') {
|
||||
urlSegments.splice(tenantParamIndex, 2);
|
||||
} else {
|
||||
const tenantCodeSegment = urlSegments.at(tenantParamIndex + 1);
|
||||
tenantCodeSegment.path = tenantCode;
|
||||
}
|
||||
} else {
|
||||
if (tenantCode != 'default') {
|
||||
urlTree.root.children[PRIMARY_OUTLET].segments = [new UrlSegment('t', {}), new UrlSegment(tenantCode, {}), ...urlSegments];
|
||||
}
|
||||
}
|
||||
|
||||
return urlTree.toString();
|
||||
}
|
||||
|
||||
getBaseUrl(): string {
|
||||
return this.document.location.origin + this.locationStrategy.getBaseHref();
|
||||
}
|
||||
}
|
|
@ -31,13 +31,13 @@
|
|||
<div style="position: relative;" class="col-12" *ngIf="hasFocus" [@fade-in]>
|
||||
<div *ngIf="showDescription" class="mb-4">
|
||||
<h5 style="font-weight: bold" class="row">{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}}</h5>
|
||||
<rich-text-editor-component [form]="form.get('description')" [id]="'editor1'" [placeholder]="'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION'" [wrapperClasses]="'row'" [editable]="!viewOnly">
|
||||
<rich-text-editor-component [form]="form.get('description')" [placeholder]="'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION'" [wrapperClasses]="'row'" [editable]="!viewOnly">
|
||||
</rich-text-editor-component>
|
||||
<mat-error *ngIf="this.form.get('description').hasError('backendError')">{{form.get('description').getError('backendError').message}}</mat-error>
|
||||
</div>
|
||||
<div *ngIf="showExtendedDescription" class="mb-4">
|
||||
<h5 style="font-weight: bold" class="row">{{'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}}</h5>
|
||||
<rich-text-editor-component [form]="form.get('extendedDescription')" [id]="'editor2'" [placeholder]="'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION'" [wrapperClasses]="'row'" [editable]="!viewOnly">
|
||||
<rich-text-editor-component [form]="form.get('extendedDescription')" [placeholder]="'DESCRIPTION-TEMPLATE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION'" [wrapperClasses]="'row'" [editable]="!viewOnly">
|
||||
</rich-text-editor-component>
|
||||
<mat-error *ngIf="this.form.get('extendedDescription').hasError('backendError')">{{form.get('extendedDescription').getError('backendError').message}}</mat-error>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { Component, Input, NgZone, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||
import { PrincipalService } from '@app/core/services/http/principal.service';
|
||||
import { TenantHandlingService } from '@app/core/services/tenant/tenant-handling.service';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { BaseHttpParams } from '@common/http/base-http-params';
|
||||
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { from } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
@ -27,7 +25,7 @@ export class LoginComponent extends BaseComponent implements OnInit {
|
|||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private route: ActivatedRoute,
|
||||
private principalService: PrincipalService,
|
||||
private tenantHandlingService: TenantHandlingService,
|
||||
private keycloakService: KeycloakService
|
||||
) { super(); }
|
||||
|
||||
|
@ -36,7 +34,8 @@ export class LoginComponent extends BaseComponent implements OnInit {
|
|||
if (!this.keycloakService.isLoggedIn()) {
|
||||
this.authService.authenticate(this.returnUrl);
|
||||
} else {
|
||||
this.authService.prepareAuthRequest(from(this.keycloakService.getToken())).pipe(takeUntil(this._destroyed)).subscribe(
|
||||
const tenantCode = this.tenantHandlingService.extractTenantCodeFromUrlPath(this.returnUrl) ?? this.authService.selectedTenant() ?? 'default';
|
||||
this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), tenantCode).pipe(takeUntil(this._destroyed)).subscribe(
|
||||
() => {
|
||||
let returnUrL = this.returnUrl;
|
||||
this.zone.run(() => this.router.navigateByUrl(returnUrL));
|
||||
|
|
|
@ -15,13 +15,10 @@ export class LogoutComponent implements OnInit {
|
|||
|
||||
ngOnInit() {
|
||||
this.authService.clear();
|
||||
debugger;
|
||||
this.keycloak.logout(location.origin).then(() => {
|
||||
localStorage.clear();
|
||||
// this.router.navigate(['./'], { replaceUrl: true });
|
||||
});
|
||||
// this.tokenService.logout(() => {
|
||||
// localStorage.clear();
|
||||
// this.router.navigate(["./"], { replaceUrl: true });
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { FormattingModule } from '@app/core/formatting.module';
|
||||
import { DescriptionRoutingModule } from '@app/ui/description/description.routing';
|
||||
import { DescriptionRoutingModule, PublicDescriptionRoutingModule } from '@app/ui/description/description.routing';
|
||||
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
|
||||
|
@ -17,3 +17,17 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
|
|||
]
|
||||
})
|
||||
export class DescriptionModule { }
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonUiModule,
|
||||
CommonFormsModule,
|
||||
FormattingModule,
|
||||
PublicDescriptionRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
],
|
||||
exports: [
|
||||
]
|
||||
})
|
||||
export class PublicDescriptionModule { }
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '@app/core/auth-guard.service';
|
||||
import { BreadcrumbService } from '../misc/breadcrumb/breadcrumb.service';
|
||||
// import { DescriptionWizardComponent } from './description-wizard/description-wizard.component';
|
||||
// import { DescriptionOverviewComponent } from './overview/description-overview.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'overview',
|
||||
loadChildren: () => import('./overview/description-overview.module').then(m => m.DescriptionOverviewModule),
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -18,6 +18,28 @@ const routes: Routes = [
|
|||
{
|
||||
path: 'edit',
|
||||
loadChildren: () => import('./editor/description-editor.module').then(m => m.DescriptionEditorModule),
|
||||
canActivate: [AuthGuard],
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
hideNavigationItem: true
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
canActivate: [AuthGuard],
|
||||
loadChildren: () => import('./listing/description-listing.module').then(m => m.DescriptionListingModule),
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const publicRoutes: Routes = [
|
||||
{
|
||||
path: 'overview',
|
||||
loadChildren: () => import('./overview/description-overview.module').then(m => m.DescriptionOverviewModule),
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -40,3 +62,10 @@ const routes: Routes = [
|
|||
providers: []
|
||||
})
|
||||
export class DescriptionRoutingModule { }
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(publicRoutes)],
|
||||
exports: [RouterModule],
|
||||
providers: []
|
||||
})
|
||||
export class PublicDescriptionRoutingModule { }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { FormattingModule } from '@app/core/formatting.module';
|
||||
import { DmpRoutingModule } from '@app/ui/dmp/dmp.routing';
|
||||
import { DmpRoutingModule, PublicDmpRoutingModule } from '@app/ui/dmp/dmp.routing';
|
||||
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
|
||||
|
@ -17,3 +17,17 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
|
|||
]
|
||||
})
|
||||
export class DmpModule { }
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonUiModule,
|
||||
CommonFormsModule,
|
||||
FormattingModule,
|
||||
PublicDmpRoutingModule,
|
||||
],
|
||||
declarations: [
|
||||
],
|
||||
exports: [
|
||||
]
|
||||
})
|
||||
export class PublicDmpModule { }
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { BreadcrumbService } from '../misc/breadcrumb/breadcrumb.service';
|
||||
import { AuthGuard } from '@app/core/auth-guard.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'overview',
|
||||
loadChildren: () => import('./overview/dmp-overview.module').then(m => m.DmpOverviewModule),
|
||||
canActivate:[AuthGuard],
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -16,6 +18,7 @@ const routes: Routes = [
|
|||
{
|
||||
path: 'new',
|
||||
loadChildren: () => import('./dmp-editor-blueprint/dmp-editor.module').then(m => m.DmpEditorModule),
|
||||
canActivate:[AuthGuard],
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -27,6 +30,7 @@ const routes: Routes = [
|
|||
{
|
||||
path: 'edit',
|
||||
loadChildren: () => import('./dmp-editor-blueprint/dmp-editor.module').then(m => m.DmpEditorModule),
|
||||
canActivate:[AuthGuard],
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
|
@ -37,80 +41,32 @@ const routes: Routes = [
|
|||
},
|
||||
{
|
||||
path: '',
|
||||
canActivate:[AuthGuard],
|
||||
loadChildren: () => import('./listing/dmp-listing.module').then(m => m.DmpListingModule),
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
// {
|
||||
// path: 'publicEdit/:publicId',
|
||||
// component: DmpEditorComponent,
|
||||
// data: {
|
||||
// breadcrumb: true,
|
||||
// title: 'GENERAL.TITLES.DMP-PUBLIC-EDIT'
|
||||
// },
|
||||
// canDeactivate: [CanDeactivateGuard]
|
||||
// },
|
||||
|
||||
// {
|
||||
// path: 'publicOverview/:publicId',
|
||||
// component: DmpOverviewComponent,
|
||||
// data: {
|
||||
// breadcrumb: true,
|
||||
// title: 'GENERAL.TITLES.DMP-OVERVIEW'
|
||||
// },
|
||||
// },
|
||||
|
||||
|
||||
|
||||
|
||||
// {
|
||||
// path: 'new/dataset',
|
||||
// component: DmpEditorComponent,
|
||||
// canActivate: [AuthGuard],
|
||||
// data: {
|
||||
// breadcrumbs: 'new/dataset',
|
||||
// title: 'GENERAL.TITLES.DATASET-NEW'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// path: 'new/dataset/:dmpId',
|
||||
// component: DmpEditorComponent,
|
||||
// canActivate: [AuthGuard],
|
||||
// data: {
|
||||
// breadcrumbs: 'new/dataset',
|
||||
// title: 'GENERAL.TITLES.DATASET-NEW'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// path: 'new_version/:id',
|
||||
// // component: DmpWizardComponent,
|
||||
// component: DmpCloneComponent,
|
||||
// data: {
|
||||
// clone: false,
|
||||
// breadcrumb: true,
|
||||
// title: 'GENERAL.TITLES.DMP-NEW-VERSION'
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// path: 'clone/:id',
|
||||
// component: DmpCloneComponent,
|
||||
// data: {
|
||||
// clone: false,
|
||||
// breadcrumb: true,
|
||||
// title: 'GENERAL.TITLES.DMP-CLONE'
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// path: 'invitation/:id',
|
||||
// component: InvitationAcceptedComponent,
|
||||
// data: {
|
||||
// breadcrumb: true
|
||||
// },
|
||||
// }
|
||||
const publicRoutes: Routes = [
|
||||
{
|
||||
path: 'overview',
|
||||
loadChildren: () => import('./overview/dmp-overview.module').then(m => m.DmpOverviewModule),
|
||||
data: {
|
||||
breadcrumb: true,
|
||||
...BreadcrumbService.generateRouteDataConfiguration({
|
||||
hideNavigationItem: true
|
||||
}),
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
loadChildren: () => import('./listing/dmp-listing.module').then(m => m.DmpListingModule),
|
||||
data: {
|
||||
breadcrumb: true
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -118,3 +74,9 @@ const routes: Routes = [
|
|||
exports: [RouterModule]
|
||||
})
|
||||
export class DmpRoutingModule { }
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(publicRoutes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PublicDmpRoutingModule { }
|
||||
|
|
|
@ -90,15 +90,21 @@ export class NavbarComponent extends BaseComponent implements OnInit {
|
|||
this.authentication.getAuthenticationStateObservable().subscribe(authenticationState => {
|
||||
if (authenticationState.loginStatus === LoginStatus.LoggedIn) {
|
||||
this.loadLogo();
|
||||
this.loadUser();
|
||||
}
|
||||
});
|
||||
this.loadLogo();
|
||||
this.loadUser();
|
||||
}
|
||||
|
||||
private loadUser() {
|
||||
if (this.authentication.currentAccountIsAuthenticated() && this.authentication.userId()) {
|
||||
this.userService.getSingle(this.authentication.userId(), [
|
||||
nameof<User>(x => x.id),
|
||||
nameof<User>(x => x.name)
|
||||
]).subscribe(u => this.userName = u.name); //TODO HANDLE-ERRORS
|
||||
}
|
||||
}
|
||||
|
||||
private loadLogo() {
|
||||
if (this.authentication.currentAccountIsAuthenticated() && this.authentication.selectedTenant()) {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { Component, EventEmitter, OnInit, Output } from "@angular/core";
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { MatButtonToggleChange } from "@angular/material/button-toggle";
|
||||
import { Router } from "@angular/router";
|
||||
import { Tenant } from "@app/core/model/tenant/tenant";
|
||||
import { AuthService } from "@app/core/services/auth/auth.service";
|
||||
import { PrincipalService } from "@app/core/services/http/principal.service";
|
||||
import { TenantHandlingService } from "@app/core/services/tenant/tenant-handling.service";
|
||||
import { BaseComponent } from "@common/base/base.component";
|
||||
import { BaseHttpParams } from "@common/http/base-http-params";
|
||||
import { InterceptorType } from "@common/http/interceptors/interceptor-type";
|
||||
import { KeycloakService } from "keycloak-angular";
|
||||
import { Observable, from } from "rxjs";
|
||||
import { takeUntil } from "rxjs/operators";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
@Component({
|
||||
selector: 'app-tenant-switch',
|
||||
|
@ -20,10 +18,9 @@ export class TenantSwitchComponent extends BaseComponent implements OnInit {
|
|||
tenants: Observable<Array<Tenant>>;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private keycloakService: KeycloakService,
|
||||
private principalService: PrincipalService,
|
||||
private authService: AuthService,
|
||||
private tenantHandlingService: TenantHandlingService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -34,7 +31,6 @@ export class TenantSwitchComponent extends BaseComponent implements OnInit {
|
|||
|
||||
ngOnInit() {
|
||||
this.tenants = this.loadUserTenants(); //TODO
|
||||
//this.tenantChange.emit(this.getCurrentLanguage())
|
||||
}
|
||||
|
||||
loadUserTenants(): Observable<Array<Tenant>> {
|
||||
|
@ -48,22 +44,7 @@ export class TenantSwitchComponent extends BaseComponent implements OnInit {
|
|||
onTenantSelected(selectedTenant: MatButtonToggleChange) {
|
||||
if (selectedTenant.value === undefined || selectedTenant.value === '') return;
|
||||
|
||||
this.formSubmit(selectedTenant.value);
|
||||
this.loadUser();
|
||||
}
|
||||
|
||||
formSubmit(selectedTenant: string): void {
|
||||
this.authService.selectedTenant(selectedTenant);
|
||||
}
|
||||
|
||||
loadUser(): void {
|
||||
this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), {})
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
() => {
|
||||
this.authService.onAuthenticateSuccessReload();
|
||||
},
|
||||
(error) => this.authService.onAuthenticateError(error)
|
||||
);
|
||||
this.authService.selectedTenant(selectedTenant.value);
|
||||
window.location.href = this.tenantHandlingService.getCurrentUrlEnrichedWithTenantCode(selectedTenant.value, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
@ -18,6 +17,7 @@ import { AnalyticsService } from '@app/core/services/matomo/analytics-service';
|
|||
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||
import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service';
|
||||
import { ReferenceService } from '@app/core/services/reference/reference.service';
|
||||
import { TenantHandlingService } from '@app/core/services/tenant/tenant-handling.service';
|
||||
import { UserService } from '@app/core/services/user/user.service';
|
||||
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||
|
@ -28,16 +28,15 @@ import { FormValidationErrorsDialogComponent } from '@common/forms/form-validati
|
|||
import { BaseHttpParams } from '@common/http/base-http-params';
|
||||
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
|
||||
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
|
||||
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||
import { Guid } from '@common/types/guid';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import * as moment from 'moment-timezone';
|
||||
import { Observable, from, of } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, takeUntil } from 'rxjs/operators';
|
||||
import { nameof } from 'ts-simple-nameof';
|
||||
import { AddAccountDialogComponent } from './add-account/add-account-dialog.component';
|
||||
import { UserProfileEditorModel } from './user-profile-editor.model';
|
||||
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-profile',
|
||||
|
@ -81,7 +80,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
|||
private dialog: MatDialog,
|
||||
public enumUtils: EnumUtils,
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private keycloakService: KeycloakService,
|
||||
private tenantHandlingService: TenantHandlingService,
|
||||
private principalService: PrincipalService,
|
||||
private formService: FormService,
|
||||
private referenceService: ReferenceService,
|
||||
|
@ -367,17 +366,9 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
|||
if (this.tenantFormGroup.valid === false) return;
|
||||
|
||||
const selectedTenant = this.tenantFormGroup.get('tenantCode').value;
|
||||
this.formSubmit(selectedTenant);
|
||||
this.loadUser();
|
||||
}
|
||||
|
||||
formSubmit(selectedTenant: string): void {
|
||||
this.authService.selectedTenant(selectedTenant);
|
||||
}
|
||||
|
||||
loadUser(): void {
|
||||
const returnUrl = '/profile';
|
||||
this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), {}).pipe(takeUntil(this._destroyed)).subscribe(() => this.authService.onAuthenticateSuccess(returnUrl), (error) => this.authService.onAuthenticateError(error));
|
||||
this.authService.selectedTenant(selectedTenant.value);
|
||||
window.location.href = this.tenantHandlingService.getCurrentUrlEnrichedWithTenantCode(selectedTenant.value, true);
|
||||
}
|
||||
|
||||
//Preferences
|
||||
|
|
|
@ -43,13 +43,13 @@ export class UnauthorizedResponseInterceptor extends BaseInterceptor {
|
|||
this.authService.refreshToken().then((isRefreshed) => {
|
||||
this.accountRefresh$ = null;
|
||||
if (!isRefreshed) {
|
||||
this.logoutUser();
|
||||
this.handleUnauthorized();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).catch(x => {
|
||||
this.logoutUser();
|
||||
this.handleUnauthorized();
|
||||
return false;
|
||||
})
|
||||
).pipe(filter((x) => x));
|
||||
|
@ -67,10 +67,10 @@ export class UnauthorizedResponseInterceptor extends BaseInterceptor {
|
|||
return next.handle(newRequest);
|
||||
}
|
||||
|
||||
private logoutUser() {
|
||||
private handleUnauthorized() {
|
||||
if (!this.isLoginRoute() && !this.isSignupRoute()) {
|
||||
this.authService.clear();
|
||||
this.router.navigate(['/unauthorized']);
|
||||
this.router.navigate(['/unauthorized', { queryParams: { returnUrl: this.router.url } }]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue