From 50a83f784d328d9b819d1f72c68f759efced1d26 Mon Sep 17 00:00:00 2001
From: Erik Tiekstra
Date: Tue, 24 Aug 2021 13:43:03 +0200
Subject: [PATCH] feat(login): Now adding orgnr to all API requests. (TV-399)
Squashed commit of the following:
commit b0cc0cf07a4eeaf85c8fdfc111fee1898fa14185
Merge: be9d909 59ce393
Author: Erik Tiekstra
Date: Tue Aug 24 13:42:09 2021 +0200
Merged develop and fixed conflicts
commit be9d909232326eb06221336a966fc40c7c88289d
Author: Erik Tiekstra
Date: Tue Aug 24 08:02:12 2021 +0200
Updated auth guard to remove localstorage data when user is not logged in
commit a4a182f565689a44e612b9353ae46514c1b439c7
Author: Erik Tiekstra
Date: Mon Aug 23 15:08:00 2021 +0200
Updated organization functionality to check if organization matches users organizations
commit c170245c2799118bbf7961e95d507885a0571de6
Author: Erik Tiekstra
Date: Fri Aug 20 14:34:33 2021 +0200
Now saving organization instead of organization number
commit 7c19600f712f48c9c56ba797e4e281a82adcf72f
Author: Erik Tiekstra
Date: Fri Aug 20 13:43:27 2021 +0200
Removed all headers from API requests from services
commit 7c243bafc63f0544e11f1fa8729a139615cb14c0
Author: Erik Tiekstra
Date: Fri Aug 20 13:18:19 2021 +0200
Dynamically adding orgnr to interceptor
---
.../src/app/app-routing.module.ts | 2 +
apps/mina-sidor-fa/src/app/app.module.ts | 4 +-
.../organization-picker.component.html | 6 +-
.../organization-picker.component.ts | 43 ++---
.../components/layout/layout.component.ts | 4 +-
.../shared/constants/local-storage-keys.ts | 10 +-
.../src/app/shared/guards/auth.guard.ts | 26 +--
.../shared/interceptors/auth.interceptor.ts | 31 ++++
.../shared/services/api/auth.interceptor.ts | 23 ---
.../services/api/authentication.service.ts | 33 ++--
.../services/api/authorizations.service.ts | 6 +-
.../shared/services/api/avrop-api.service.ts | 24 +--
.../shared/services/api/deltagare.service.ts | 159 ++++++++----------
.../shared/services/api/employee.service.ts | 52 +++---
.../services/api/participants.service.ts | 8 +-
.../shared/services/api/service.service.ts | 6 +-
.../app/shared/services/api/tjanst.service.ts | 6 +-
.../app/shared/services/api/user.service.ts | 69 ++++----
.../src/environments/environment.api.ts | 4 +-
19 files changed, 242 insertions(+), 274 deletions(-)
create mode 100644 apps/mina-sidor-fa/src/app/shared/interceptors/auth.interceptor.ts
delete mode 100644 apps/mina-sidor-fa/src/app/shared/services/api/auth.interceptor.ts
diff --git a/apps/mina-sidor-fa/src/app/app-routing.module.ts b/apps/mina-sidor-fa/src/app/app-routing.module.ts
index d8e9134..061437f 100644
--- a/apps/mina-sidor-fa/src/app/app-routing.module.ts
+++ b/apps/mina-sidor-fa/src/app/app-routing.module.ts
@@ -56,6 +56,7 @@ const routes: Routes = [
path: 'logga-ut',
data: { title: 'Logga ut' },
loadChildren: () => import('./pages/logout/logout.module').then(m => m.LogoutModule),
+ canActivate: [AuthGuard],
},
{
path: 'organization-picker',
@@ -66,6 +67,7 @@ const routes: Routes = [
path: 'mitt-konto',
data: { title: 'Mitt konto' },
loadChildren: () => import('./pages/my-account/my-account.module').then(m => m.MyAccountModule),
+ canActivate: [AuthGuard],
},
];
diff --git a/apps/mina-sidor-fa/src/app/app.module.ts b/apps/mina-sidor-fa/src/app/app.module.ts
index 1dd9ff5..02e7667 100644
--- a/apps/mina-sidor-fa/src/app/app.module.ts
+++ b/apps/mina-sidor-fa/src/app/app.module.ts
@@ -1,9 +1,8 @@
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { ErrorHandler, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
-import { AuthGuard } from '@msfa-guards/auth.guard';
+import { AuthInterceptor } from '@msfa-interceptors/auth.interceptor';
import { CustomErrorHandler } from '@msfa-interceptors/custom-error-handler.module';
-import { AuthInterceptor } from '@msfa-services/api/auth.interceptor';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ToastListModule } from './components/toast-list/toast-list.module';
@@ -18,7 +17,6 @@ import { AvropModule } from './pages/avrop/avrop.module';
useClass: CustomErrorHandler,
},
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
- AuthGuard,
],
bootstrap: [AppComponent],
})
diff --git a/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.html b/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.html
index 9b2b951..d4db8d5 100644
--- a/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.html
+++ b/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.html
@@ -6,11 +6,11 @@
att logga ut applikationen och logga in på nytt.
-
+
diff --git a/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.ts b/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.ts
index 4014a53..0281035 100644
--- a/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.ts
+++ b/apps/mina-sidor-fa/src/app/pages/organization-picker/organization-picker.component.ts
@@ -1,10 +1,10 @@
-import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
-import { ActivatedRoute, Router } from '@angular/router';
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { Router } from '@angular/router';
import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
import { Organization } from '@msfa-models/organization.model';
import { UserService } from '@msfa-services/api/user.service';
-
-export const redirectUriQueryParam = 'redirect_uri';
+import { Observable } from 'rxjs';
+import { filter, map } from 'rxjs/operators';
@Component({
selector: 'msfa-organization-picker',
@@ -12,38 +12,25 @@ export const redirectUriQueryParam = 'redirect_uri';
styleUrls: ['./organization-picker.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class OrganizationPickerComponent extends UnsubscribeDirective implements OnInit {
- user$ = this.userService.user$;
+export class OrganizationPickerComponent extends UnsubscribeDirective {
+ organizations$: Observable = this.userService.user$.pipe(
+ filter(user => !!(user && user.organizations?.length)),
+ map(({ organizations }) => organizations)
+ );
- private redirectUri: string | null = null;
-
- constructor(private userService: UserService, private router: Router, private route: ActivatedRoute) {
+ constructor(private userService: UserService, private router: Router) {
super();
super.unsubscribeOnDestroy(
- this.user$.subscribe(user => {
- if (user?.organizations?.length === 1) {
- this.loginWithOrganization(user.organizations[0]);
+ this.organizations$.subscribe(organizations => {
+ if (organizations.length === 1) {
+ this.loginWithOrganization(organizations[0]);
}
})
);
}
- ngOnInit(): void {
- super.unsubscribeOnDestroy(
- this.route.queryParams.subscribe(params => {
- this.redirectUri = params[redirectUriQueryParam] ? decodeURI(params[redirectUriQueryParam]) : null;
- })
- );
- }
-
loginWithOrganization(organization: Organization): void {
- this.userService.setSelectedUserOrganization(organization);
-
- if (this.redirectUri) {
- location.href = this.redirectUri;
- return;
- }
-
- this.router.navigateByUrl('/');
+ this.userService.setSelectedOrganization(organization);
+ void this.router.navigateByUrl('/');
}
}
diff --git a/apps/mina-sidor-fa/src/app/shared/components/layout/layout.component.ts b/apps/mina-sidor-fa/src/app/shared/components/layout/layout.component.ts
index 4094e4e..da2710d 100644
--- a/apps/mina-sidor-fa/src/app/shared/components/layout/layout.component.ts
+++ b/apps/mina-sidor-fa/src/app/shared/components/layout/layout.component.ts
@@ -21,7 +21,7 @@ export class LayoutComponent extends UnsubscribeDirective {
routerLink: '/',
};
private _breadcrumbsItems$ = new BehaviorSubject([this.startBreadcrumb]);
- isLoggedIn$: Observable = this.authService.isLoggedIn$;
+ isLoggedIn$: Observable = this.authenticationService.isLoggedIn$;
user$: Observable = this.isLoggedIn$.pipe(
filter(loggedIn => !!loggedIn),
switchMap(() => this.userService.user$)
@@ -34,7 +34,7 @@ export class LayoutComponent extends UnsubscribeDirective {
constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
- private authService: AuthenticationService,
+ private authenticationService: AuthenticationService,
private userService: UserService
) {
super();
diff --git a/apps/mina-sidor-fa/src/app/shared/constants/local-storage-keys.ts b/apps/mina-sidor-fa/src/app/shared/constants/local-storage-keys.ts
index 06c9479..e79912c 100644
--- a/apps/mina-sidor-fa/src/app/shared/constants/local-storage-keys.ts
+++ b/apps/mina-sidor-fa/src/app/shared/constants/local-storage-keys.ts
@@ -1 +1,9 @@
-export const selectedUserOrganizationNumberKey = 'selectedOrganizationId';
+export const AUTH_TOKEN_KEY = 'id_token';
+export const AUTH_TOKEN_EXPIRE_KEY = 'expires_at';
+export const SELECTED_ORGANIZATION_NUMBER_KEY = 'selected_orgnr';
+
+export const ALL_LOCAL_STORAGE_KEYS = {
+ AUTH_TOKEN_KEY,
+ AUTH_TOKEN_EXPIRE_KEY,
+ SELECTED_ORGANIZATION_NUMBER_KEY,
+};
diff --git a/apps/mina-sidor-fa/src/app/shared/guards/auth.guard.ts b/apps/mina-sidor-fa/src/app/shared/guards/auth.guard.ts
index 96f4d9d..0a9dfa5 100644
--- a/apps/mina-sidor-fa/src/app/shared/guards/auth.guard.ts
+++ b/apps/mina-sidor-fa/src/app/shared/guards/auth.guard.ts
@@ -1,33 +1,39 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
-import { UserService } from '@msfa-services/api/user.service';
import { environment } from '@msfa-environment';
import { AuthenticationService } from '@msfa-services/api/authentication.service';
+import { UserService } from '@msfa-services/api/user.service';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
-import { redirectUriQueryParam } from '../../pages/organization-picker/organization-picker.component';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class AuthGuard implements CanActivate {
constructor(
private authenticationService: AuthenticationService,
- private userService: UserService,
- private router: Router
+ private router: Router,
+ private userService: UserService
) {}
canActivate(route: ActivatedRouteSnapshot): Observable {
return this.authenticationService.isLoggedIn$.pipe(
switchMap(loggedIn => {
if (loggedIn) {
- if (!this.authenticationService.hasSelectedUserOrganization()) {
- this.router.navigateByUrl(`/organization-picker?${redirectUriQueryParam}=${encodeURI(location.href)}`);
- }
-
- return of(true);
+ return this.userService.selectedOrganization$.pipe(
+ map(organization => {
+ if (!organization) {
+ void this.router.navigateByUrl(`/organization-picker`);
+ }
+ return true;
+ })
+ );
} else if (route.queryParams.code) {
return this.authenticationService.login$(route.queryParams.code).pipe(map(result => !!result));
}
+ void this.authenticationService.removeLocalStorageData();
+
if (environment.environment === 'local') {
void this.router.navigateByUrl(environment.loginUrl);
} else {
diff --git a/apps/mina-sidor-fa/src/app/shared/interceptors/auth.interceptor.ts b/apps/mina-sidor-fa/src/app/shared/interceptors/auth.interceptor.ts
new file mode 100644
index 0000000..bf172f5
--- /dev/null
+++ b/apps/mina-sidor-fa/src/app/shared/interceptors/auth.interceptor.ts
@@ -0,0 +1,31 @@
+import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { SELECTED_ORGANIZATION_NUMBER_KEY } from '@msfa-constants/local-storage-keys';
+import { environment } from '@msfa-environment';
+import { AuthenticationService } from '@msfa-services/api/authentication.service';
+import { Observable } from 'rxjs';
+
+@Injectable()
+export class AuthInterceptor implements HttpInterceptor {
+ constructor(private authenticationService: AuthenticationService) {}
+
+ private get authorizationToken(): { Authorization: string } | null {
+ const bearerToken = this.authenticationService.currentAuthorizationToken;
+
+ return bearerToken ? { Authorization: `Bearer ${bearerToken}` } : null;
+ }
+
+ private get selectedOrganizationNumber(): { orgnr: string } | null {
+ const orgnr = localStorage.getItem(SELECTED_ORGANIZATION_NUMBER_KEY);
+
+ return orgnr ? { orgnr } : null;
+ }
+
+ intercept(req: HttpRequest, next: HttpHandler): Observable> {
+ const clonedRequest: HttpRequest = req.clone({
+ setHeaders: { ...environment.api.headers, ...this.authorizationToken, ...this.selectedOrganizationNumber },
+ });
+
+ return next.handle(clonedRequest);
+ }
+}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/auth.interceptor.ts b/apps/mina-sidor-fa/src/app/shared/services/api/auth.interceptor.ts
deleted file mode 100644
index 6ad5095..0000000
--- a/apps/mina-sidor-fa/src/app/shared/services/api/auth.interceptor.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
-import { Injectable } from '@angular/core';
-import { Observable } from 'rxjs';
-import { AuthenticationService } from './authentication.service';
-
-@Injectable()
-export class AuthInterceptor implements HttpInterceptor {
- constructor(private auth: AuthenticationService) {}
-
- intercept(req: HttpRequest, next: HttpHandler): Observable> {
- const idToken = this.auth.currentAuthorizationToken;
-
- if (idToken) {
- const cloned = req.clone({
- headers: req.headers.set('Authorization', 'Bearer ' + idToken),
- });
-
- return next.handle(cloned);
- } else {
- return next.handle(req);
- }
- }
-}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
index 0f20361..2cb39fd 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/authentication.service.ts
@@ -1,7 +1,7 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
-import { selectedUserOrganizationNumberKey } from '@msfa-constants/local-storage-keys';
+import { ALL_LOCAL_STORAGE_KEYS, AUTH_TOKEN_EXPIRE_KEY, AUTH_TOKEN_KEY } from '@msfa-constants/local-storage-keys';
import { environment } from '@msfa-environment';
import { AuthenticationResponse } from '@msfa-models/api/authentication.response.model';
import { Authentication, mapAuthApiResponseToAuthenticationResult } from '@msfa-models/authentication.model';
@@ -9,8 +9,6 @@ import { add, isBefore } from 'date-fns';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
@@ -36,17 +34,16 @@ export class AuthenticationService {
const expiresAt = add(new Date(), { seconds: authenticationResult.expiresIn });
this._token$.next(authenticationResult.idToken);
- localStorage.setItem('id_token', authenticationResult.idToken);
+ localStorage.setItem(AUTH_TOKEN_KEY, authenticationResult.idToken);
this._expiration$.next(expiresAt.valueOf());
- localStorage.setItem('expires_at', JSON.stringify(expiresAt.valueOf()));
+ localStorage.setItem(AUTH_TOKEN_EXPIRE_KEY, JSON.stringify(expiresAt.valueOf()));
}
login$(authorizationCodeFromCiam: string): Observable {
+ this.removeLocalStorageData();
+
return this.httpClient
- .get<{ data: AuthenticationResponse }>(
- AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam),
- API_HEADERS
- )
+ .get<{ data: AuthenticationResponse }>(AuthenticationService._authTokenApiUrl(authorizationCodeFromCiam))
.pipe(
map(({ data }) => mapAuthApiResponseToAuthenticationResult(data)),
tap(authenticationResult => {
@@ -56,8 +53,8 @@ export class AuthenticationService {
}
private _getLocalStorageData(): { id_token: string; expires_at: number } {
- const id_token = localStorage.getItem('id_token');
- const expiration = localStorage.getItem('expires_at');
+ const id_token = localStorage.getItem(AUTH_TOKEN_KEY);
+ const expiration = localStorage.getItem(AUTH_TOKEN_EXPIRE_KEY);
return id_token && expiration
? {
@@ -67,6 +64,12 @@ export class AuthenticationService {
: null;
}
+ public removeLocalStorageData(): void {
+ Object.values(ALL_LOCAL_STORAGE_KEYS).forEach(value => {
+ localStorage.removeItem(value);
+ });
+ }
+
get currentAuthorizationToken(): string {
return this._token$.getValue();
}
@@ -81,9 +84,7 @@ export class AuthenticationService {
}
logout(): void {
- localStorage.removeItem('id_token');
- localStorage.removeItem('expires_at');
- localStorage.removeItem(selectedUserOrganizationNumberKey);
+ this.removeLocalStorageData();
if (environment.environment === 'local') {
void this.router.navigateByUrl(environment.logoutUrl);
@@ -91,8 +92,4 @@ export class AuthenticationService {
document.location.href = environment.logoutUrl;
}
}
-
- hasSelectedUserOrganization(): boolean {
- return !!localStorage.getItem(selectedUserOrganizationNumberKey);
- }
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts
index 54f9f7d..62679bf 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/authorizations.service.ts
@@ -9,15 +9,13 @@ import {
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
export class AuthorizationService {
- private _authorizationsApiUrl = `${environment.api.url}/authorizations`;
+ private _apiBaseUrl = `${environment.api.url}/authorizations`;
public authorizations$: Observable = this.httpClient
- .get(this._authorizationsApiUrl, API_HEADERS)
+ .get(this._apiBaseUrl)
.pipe(map(({ data }) => data.map(authorization => mapAuthorizationApiResponseToAuthorization(authorization))));
constructor(private httpClient: HttpClient) {}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
index 82f7647..1b40a9a 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/avrop-api.service.ts
@@ -14,8 +14,6 @@ import { Observable, of } from 'rxjs';
import { delay, filter, map } from 'rxjs/operators';
import { HandledareAvrop } from '../../../pages/avrop/models/handledare-avrop';
-const API_HEADERS = { headers: environment.api.headers };
-
const tempHandledareMock: HandledareAvrop[] = [
{ id: '1', fullName: 'Göran Persson' },
{ id: '2', fullName: 'Stefan Löfven' },
@@ -38,12 +36,10 @@ export class AvropApiService {
offset = 0,
limit = 20
): Observable {
- return this.httpClient
- .get<{ data: AvropResponse[] }>(`${this._apiBaseUrl}`, { ...API_HEADERS })
- .pipe(
- filter(response => !!response?.data),
- map(({ data }) => data.map(avrop => mapAvropResponseToAvrop(avrop)))
- );
+ return this.httpClient.get<{ data: AvropResponse[] }>(`${this._apiBaseUrl}`).pipe(
+ filter(response => !!response?.data),
+ map(({ data }) => data.map(avrop => mapAvropResponseToAvrop(avrop)))
+ );
}
getSelectableHandledare$(deltagare: Avrop[]): Observable {
@@ -67,7 +63,7 @@ export class AvropApiService {
selectedKommuner: MultiselectFilterOption[]
): Observable {
return this.httpClient
- .get<{ data: UtforandeVerksamhetResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`, { ...API_HEADERS })
+ .get<{ data: UtforandeVerksamhetResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`)
.pipe(
filter(response => !!response?.data),
map(({ data }) =>
@@ -82,12 +78,10 @@ export class AvropApiService {
selectedTjanster: MultiselectFilterOption[],
selectedUtforandeVerksamheter: MultiselectFilterOption[]
): Observable {
- return this.httpClient
- .get<{ data: KommunResponse[] }>(`${this._apiBaseUrl}/kommuner`, { ...API_HEADERS })
- .pipe(
- filter(response => !!response?.data),
- map(({ data }) => data.map(kommun => ({ label: mapKommunResponseToKommun(kommun).name })))
- );
+ return this.httpClient.get<{ data: KommunResponse[] }>(`${this._apiBaseUrl}/kommuner`).pipe(
+ filter(response => !!response?.data),
+ map(({ data }) => data.map(kommun => ({ label: mapKommunResponseToKommun(kommun).name })))
+ );
}
async tilldelaHandledare(deltagare: Avrop[], handledare: HandledareAvrop): Promise {
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.service.ts
index a534322..fd020f0 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/deltagare.service.ts
@@ -33,8 +33,6 @@ import { sortFromToDates } from '@msfa-utils/sort.util';
import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { catchError, filter, map, switchMap } from 'rxjs/operators';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
@@ -96,7 +94,6 @@ export class DeltagareService extends UnsubscribeDirective {
console.log(params);
return this.httpClient
.get(this._apiBaseUrl, {
- ...API_HEADERS,
params,
})
.pipe(
@@ -112,32 +109,28 @@ export class DeltagareService extends UnsubscribeDirective {
}
private _fetchContactInformation$(id: string): Observable> {
- return this.httpClient
- .get<{ data: ContactInformationResponse }>(`${this._apiBaseUrl}/${id}/contact`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => mapResponseToContactInformation(data)),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of({});
- })
- );
+ return this.httpClient.get<{ data: ContactInformationResponse }>(`${this._apiBaseUrl}/${id}/contact`).pipe(
+ map(({ data }) => mapResponseToContactInformation(data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
private _fetchDriversLicense$(id: string): Observable> {
- return this.httpClient
- .get<{ data: DriversLicenseResponse }>(`${this._apiBaseUrl}/${id}/driverlicense`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => mapResponseToDriversLicense(data)),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of({});
- })
- );
+ return this.httpClient.get<{ data: DriversLicenseResponse }>(`${this._apiBaseUrl}/${id}/driverlicense`).pipe(
+ map(({ data }) => mapResponseToDriversLicense(data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
private _fetchHighestEducation$(id: string): Observable> {
return this.httpClient
- .get<{ data: HighestEducationResponse }>(`${this._apiBaseUrl}/${id}/educationlevels/highest`, { ...API_HEADERS })
+ .get<{ data: HighestEducationResponse }>(`${this._apiBaseUrl}/${id}/educationlevels/highest`)
.pipe(
map(({ data }) => mapResponseToHighestEducation(data)),
catchError(error => {
@@ -148,88 +141,76 @@ export class DeltagareService extends UnsubscribeDirective {
}
private _fetchEducations$(id: string): Observable {
- return this.httpClient
- .get<{ data: EducationsResponse }>(`${this._apiBaseUrl}/${id}/educations`, { ...API_HEADERS })
- .pipe(
- map(({ data }) =>
- data.utbildningar
- ? data.utbildningar.sort((a, b) =>
- sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
- )
- : []
- ),
- map(educations => educations.map(utbildning => mapResponseToEducation(utbildning))),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of([]);
- })
- );
+ return this.httpClient.get<{ data: EducationsResponse }>(`${this._apiBaseUrl}/${id}/educations`).pipe(
+ map(({ data }) =>
+ data.utbildningar
+ ? data.utbildningar.sort((a, b) =>
+ sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
+ )
+ : []
+ ),
+ map(educations => educations.map(utbildning => mapResponseToEducation(utbildning))),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ );
}
private _fetchTranslator$(id: string): Observable {
- return this.httpClient
- .get<{ data: TranslatorResponse }>(`${this._apiBaseUrl}/${id}/translator`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => data.sprak?.beskrivning || null),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of('');
- })
- );
+ return this.httpClient.get<{ data: TranslatorResponse }>(`${this._apiBaseUrl}/${id}/translator`).pipe(
+ map(({ data }) => data.sprak?.beskrivning || null),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of('');
+ })
+ );
}
private _fetchWorkLanguages$(id: string): Observable {
- return this.httpClient
- .get<{ data: WorkLanguagesResponse }>(`${this._apiBaseUrl}/${id}/work/languages`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => data?.sprak?.map(sprak => sprak.beskrivning) || []),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of([]);
- })
- );
+ return this.httpClient.get<{ data: WorkLanguagesResponse }>(`${this._apiBaseUrl}/${id}/work/languages`).pipe(
+ map(({ data }) => data?.sprak?.map(sprak => sprak.beskrivning) || []),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ );
}
private _fetchDisabilities$(id: string): Observable {
- return this.httpClient
- .get<{ data: DisabilityResponse[] }>(`${this._apiBaseUrl}/${id}/work/disabilities`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => data?.map(funktionsnedsattning => mapResponseToDisability(funktionsnedsattning)) || []),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of([]);
- })
- );
+ return this.httpClient.get<{ data: DisabilityResponse[] }>(`${this._apiBaseUrl}/${id}/work/disabilities`).pipe(
+ map(({ data }) => data?.map(funktionsnedsattning => mapResponseToDisability(funktionsnedsattning)) || []),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ );
}
private _fetchWorkExperiences$(id: string): Observable {
- return this.httpClient
- .get<{ data: WorkExperiencesResponse }>(`${this._apiBaseUrl}/${id}/work/experiences`, { ...API_HEADERS })
- .pipe(
- map(
- ({ data }) =>
- data?.arbetslivserfarenheter?.sort((a, b) =>
- sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
- ) || []
- ),
- map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of([]);
- })
- );
+ return this.httpClient.get<{ data: WorkExperiencesResponse }>(`${this._apiBaseUrl}/${id}/work/experiences`).pipe(
+ map(
+ ({ data }) =>
+ data?.arbetslivserfarenheter?.sort((a, b) =>
+ sortFromToDates({ from: a.period_from, to: a.period_tom }, { from: b.period_from, to: b.period_tom })
+ ) || []
+ ),
+ map(workExperiences => workExperiences.map(erfarenhet => mapResponseToWorkExperience(erfarenhet))),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of([]);
+ })
+ );
}
private _fetchAvropInformation$(id: string): Observable> {
- return this.httpClient
- .get<{ data: AvropResponse }>(`${this._apiBaseUrl}/${id}/avrop`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => (data ? mapAvropResponseToAvrop(data) : {})),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of({});
- })
- );
+ return this.httpClient.get<{ data: AvropResponse }>(`${this._apiBaseUrl}/${id}/avrop`).pipe(
+ map(({ data }) => (data ? mapAvropResponseToAvrop(data) : {})),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
// As TypeScript has some limitations regarding combining Observables this way,
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
index c2bc232..16856c4 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/employee.service.ts
@@ -26,13 +26,11 @@ import { BehaviorSubject, combineLatest, Observable, of, throwError } from 'rxjs
import { catchError, filter, map, switchMap, take } from 'rxjs/operators';
import { TjanstService } from './tjanst.service';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
export class EmployeeService extends UnsubscribeDirective {
- private _apiUrl = `${environment.api.url}/users`;
+ private _apiBaseUrl = `${environment.api.url}/users`;
private _currentEmployeeId$ = new BehaviorSubject(null);
private _limit$ = new BehaviorSubject(20);
private _page$ = new BehaviorSubject(1);
@@ -43,6 +41,7 @@ export class EmployeeService extends UnsubscribeDirective {
private _employee$ = new BehaviorSubject(null);
public employee$: Observable = this._employee$.asObservable();
+
constructor(
private httpClient: HttpClient,
private errorService: ErrorService,
@@ -118,10 +117,7 @@ export class EmployeeService extends UnsubscribeDirective {
}
return this.httpClient
- .get(this._apiUrl, {
- ...API_HEADERS,
- params,
- })
+ .get(this._apiBaseUrl, { params })
.pipe(
map(({ data, meta }) => {
return { data: data.map(employee => mapResponseToEmployeeCompact(employee)), meta };
@@ -130,15 +126,13 @@ export class EmployeeService extends UnsubscribeDirective {
}
private _fetchEmployee$(id: string): Observable> {
- return this.httpClient
- .get<{ data: EmployeeResponse }>(`${this._apiUrl}/${id}`, { ...API_HEADERS })
- .pipe(
- map(({ data }) => mapResponseToEmployee(data)),
- catchError(error => {
- this.errorService.add(errorToCustomError(error));
- return of({});
- })
- );
+ return this.httpClient.get<{ data: EmployeeResponse }>(`${this._apiBaseUrl}/${id}`).pipe(
+ map(({ data }) => mapResponseToEmployee(data)),
+ catchError(error => {
+ this.errorService.add(errorToCustomError(error));
+ return of({});
+ })
+ );
}
public setSearchFilter(value: string): void {
@@ -151,18 +145,16 @@ export class EmployeeService extends UnsubscribeDirective {
// Not done, waiting for delete api http response
public deleteEmployee(id: string): Observable {
- return this.httpClient
- .delete(`${this._apiUrl}/${id}`, { ...API_HEADERS })
- .pipe(
- take(1),
- map(response => {
- return {
- status: response.status || 200, // mockresponse
- message: response.message || 'deleted succeeded', // mockresponse
- };
- }),
- catchError(error => throwError({ message: error as string, type: ErrorType.API }))
- );
+ return this.httpClient.delete(`${this._apiBaseUrl}/${id}`).pipe(
+ take(1),
+ map(response => {
+ return {
+ status: response.status || 200, // mockresponse
+ message: response.message || 'deleted succeeded', // mockresponse
+ };
+ }),
+ catchError(error => throwError({ message: error as string, type: ErrorType.API }))
+ );
}
public setSort(newSortKey: keyof EmployeeCompactResponse): void {
@@ -178,7 +170,7 @@ export class EmployeeService extends UnsubscribeDirective {
}
public postNewEmployee(employeeData: Employee): Observable {
- return this.httpClient.post<{ id: string }>(this._apiUrl, mapEmployeeToRequestData(employeeData), API_HEADERS).pipe(
+ return this.httpClient.post<{ id: string }>(this._apiBaseUrl, mapEmployeeToRequestData(employeeData)).pipe(
map(({ id }) => id),
catchError(error => throwError({ message: error as string, type: ErrorType.API }))
);
@@ -186,7 +178,7 @@ export class EmployeeService extends UnsubscribeDirective {
public postEmployeeInvitation(email: string): Observable {
return this.httpClient
- .post<{ data: EmployeeInviteMockApiResponse }>(`${this._apiUrl}/invite`, { email }, API_HEADERS)
+ .post<{ data: EmployeeInviteMockApiResponse }>(`${this._apiBaseUrl}/invite`, { email })
.pipe(
take(1),
map(res => res.data),
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/participants.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/participants.service.ts
index f531913..b757ac6 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/participants.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/participants.service.ts
@@ -23,15 +23,13 @@ function filterParticipants(participants: Participant[], searchFilter: string):
});
}
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
export class ParticipantsService {
- private _apiUrl = `${environment.api.url}/participants`;
+ private _apiBaseUrl = `${environment.api.url}/participants`;
private _allParticipants$: Observable = this.httpClient
- .get(this._apiUrl)
+ .get(this._apiBaseUrl)
.pipe(map(response => response.data.map(participant => mapParticipantApiResponseToParticipant(participant))));
private _activeParticipantsSortBy$ = new BehaviorSubject | null>({
key: 'handleBefore',
@@ -79,7 +77,7 @@ export class ParticipantsService {
public fetchDetailedParticipantData$(id: string): Observable {
return this.httpClient
- .get(`${this._apiUrl}/${id}`, { ...API_HEADERS })
+ .get(`${this._apiBaseUrl}/${id}`)
.pipe(map(result => mapParticipantApiResponseToParticipant(result.data)));
}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/service.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/service.service.ts
index 7b8d2f9..9c607f8 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/service.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/service.service.ts
@@ -5,15 +5,13 @@ import { mapServiceApiResponseToService, Service, ServiceApiResponse } from '@ms
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
export class ServiceService {
- private _servicesApiUrl = `${environment.api.url}/services`;
+ private _apiBaseUrl = `${environment.api.url}/services`;
public services$: Observable = this.httpClient
- .get(this._servicesApiUrl, API_HEADERS)
+ .get(this._apiBaseUrl)
.pipe(map(response => response.data.map(service => mapServiceApiResponseToService(service))));
constructor(private httpClient: HttpClient) {}
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts
index 14d79cf..afdeb15 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/tjanst.service.ts
@@ -7,13 +7,11 @@ import { mapResponseToTjanst, Tjanst } from '@msfa-models/tjanst.model';
import { BehaviorSubject, Observable } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
-const API_HEADERS = { headers: environment.api.headers };
-
@Injectable({
providedIn: 'root',
})
export class TjanstService extends UnsubscribeDirective {
- private _apiUrl = `${environment.api.url}/tjanster`;
+ private _apiBaseUrl = `${environment.api.url}/tjanster`;
private _tjanster$ = new BehaviorSubject(null);
public tjanster$: Observable = this._tjanster$.asObservable();
@@ -22,7 +20,7 @@ export class TjanstService extends UnsubscribeDirective {
filter(tjanster => !tjanster?.length),
switchMap(() =>
this.httpClient
- .get<{ data: TjanstResponse[] }>(this._apiUrl, API_HEADERS)
+ .get<{ data: TjanstResponse[] }>(this._apiBaseUrl)
.pipe(map(({ data }) => data.map(tjanst => mapResponseToTjanst(tjanst))))
)
);
diff --git a/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts b/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
index ede2eb7..0955969 100644
--- a/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
+++ b/apps/mina-sidor-fa/src/app/shared/services/api/user.service.ts
@@ -1,6 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
-import { selectedUserOrganizationNumberKey } from '@msfa-constants/local-storage-keys';
+import { SELECTED_ORGANIZATION_NUMBER_KEY } from '@msfa-constants/local-storage-keys';
import { UnsubscribeDirective } from '@msfa-directives/unsubscribe.directive';
import { environment } from '@msfa-environment';
import { OrganizationResponse } from '@msfa-models/api/organization.response.model';
@@ -9,59 +9,64 @@ import { mapResponseToOrganization, Organization } from '@msfa-models/organizati
import { mapResponseToUserInfo, UserInfo } from '@msfa-models/user-info.model';
import { User } from '@msfa-models/user.model';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
-import { filter, map } from 'rxjs/operators';
-
-const API_HEADERS = { headers: environment.api.headers };
+import { filter, map, switchMap } from 'rxjs/operators';
+import { AuthenticationService } from './authentication.service';
@Injectable({
providedIn: 'root',
})
export class UserService extends UnsubscribeDirective {
- private readonly selectedUserOrganizationNumberKey = 'selectedOrganizationId';
-
- private _authApiUrl = `${environment.api.url}/auth`;
+ private _apiBaseUrl = `${environment.api.url}/auth`;
private _user$ = new BehaviorSubject(null);
-
public user$: Observable = this._user$.asObservable();
+ private _selectedOrganizationNumber$ = new BehaviorSubject(null);
- constructor(private httpClient: HttpClient) {
+ constructor(private httpClient: HttpClient, private authenticationService: AuthenticationService) {
super();
super.unsubscribeOnDestroy(
- combineLatest([this._fetchUserInfo$(), this._fetchOrganizations$()]).subscribe(([userInfo, organizations]) => {
- this._user$.next({ ...userInfo, organizations });
- })
+ this.authenticationService.isLoggedIn$
+ .pipe(
+ filter(loggedIn => !!loggedIn),
+ switchMap(() => combineLatest([this._fetchUserInfo$(), this._fetchOrganizations$()]))
+ )
+ .subscribe(([userInfo, organizations]) => {
+ this._user$.next({ ...userInfo, organizations });
+ })
);
- }
-
- getSelectedUserOrganization(user: User): Organization {
- if (!user) {
- return null;
- }
-
- return user.organizations.find(
- organization => organization.organizationNumber === localStorage.getItem(selectedUserOrganizationNumberKey)
- );
- }
-
- setSelectedUserOrganization(organization: Organization): void {
- if (!organization) {
- return;
- }
-
- localStorage.setItem(selectedUserOrganizationNumberKey, organization?.organizationNumber);
+ this._selectedOrganizationNumber$.next(this._selectedOrganizationNumber);
}
private _fetchOrganizations$(): Observable {
- return this.httpClient.get<{ data: OrganizationResponse[] }>(`${this._authApiUrl}/organizations`, API_HEADERS).pipe(
+ return this.httpClient.get<{ data: OrganizationResponse[] }>(`${this._apiBaseUrl}/organizations`).pipe(
filter(response => !!response?.data),
map(({ data }) => data.map(organization => mapResponseToOrganization(organization)))
);
}
private _fetchUserInfo$(): Observable {
- return this.httpClient.get<{ data: UserInfoResponse }>(`${this._authApiUrl}/userinfo`, API_HEADERS).pipe(
+ return this.httpClient.get<{ data: UserInfoResponse }>(`${this._apiBaseUrl}/userinfo`).pipe(
filter(response => !!response?.data),
map(({ data }) => mapResponseToUserInfo(data))
);
}
+
+ private get _selectedOrganizationNumber(): string | null {
+ return localStorage.getItem(SELECTED_ORGANIZATION_NUMBER_KEY);
+ }
+
+ public get selectedOrganization$(): Observable {
+ return combineLatest([this._selectedOrganizationNumber$, this._user$]).pipe(
+ filter(([, user]) => !!user),
+ map(([organizationNumber, user]) => {
+ return organizationNumber
+ ? user.organizations.find(organization => organization.organizationNumber === organizationNumber)
+ : null;
+ })
+ );
+ }
+
+ public setSelectedOrganization(organization: Organization): void {
+ localStorage.setItem(SELECTED_ORGANIZATION_NUMBER_KEY, organization.organizationNumber);
+ this._selectedOrganizationNumber$.next(organization.organizationNumber);
+ }
}
diff --git a/apps/mina-sidor-fa/src/environments/environment.api.ts b/apps/mina-sidor-fa/src/environments/environment.api.ts
index 5a1f163..0264465 100644
--- a/apps/mina-sidor-fa/src/environments/environment.api.ts
+++ b/apps/mina-sidor-fa/src/environments/environment.api.ts
@@ -8,8 +8,6 @@ export const environment: Environment = {
production: false,
api: {
url: '/api',
- headers: {
- orgnr: '5564673381', // Until we have an organisation-selector
- },
+ headers: {},
},
};