Skip to content

Commit efe97bb

Browse files
committed
Created login service
1 parent 00649f4 commit efe97bb

19 files changed

Lines changed: 239 additions & 212 deletions

src/app/authentication/guard/logged-in.guard.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { HttpClientTestingModule } from '@angular/common/http/testing';
21
import { TestBed } from '@angular/core/testing';
32
import { RouterTestingModule } from '@angular/router/testing';
43
import { LoggedInGuard } from './logged-in.guard';
@@ -9,7 +8,6 @@ describe('LoggedInGuard', () => {
98
beforeEach(() => {
109
TestBed.configureTestingModule({
1110
imports: [
12-
HttpClientTestingModule,
1311
RouterTestingModule
1412
]
1513
});

src/app/authentication/guard/logged-in.guard.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable } from '@angular/core';
22
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
33
import { Observable } from 'rxjs';
4-
import { AuthenticationService } from '../service/authentication.service';
4+
import { AuthenticationContainer } from '../service/authentication-container.service';
55

66
/**
77
* Logged in guard. Allows access only if the user in session is logged in. Otherwise redirects
@@ -16,13 +16,13 @@ export class LoggedInGuard implements CanActivate {
1616

1717
constructor(
1818
private router: Router,
19-
private authenticationService: AuthenticationService
19+
private authenticationContainer: AuthenticationContainer
2020
) { }
2121

2222
canActivate(
2323
route: ActivatedRouteSnapshot,
2424
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
25-
const logged = this.authenticationService.getUser().logged;
25+
const logged = this.authenticationContainer.getLoginDetails().logged;
2626
let active;
2727

2828
if (logged) {

src/app/authentication/guard/logged-out.guard.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { HttpClientTestingModule } from '@angular/common/http/testing';
21
import { TestBed } from '@angular/core/testing';
32
import { RouterTestingModule } from '@angular/router/testing';
43

@@ -10,7 +9,6 @@ describe('LoggedOutGuard', () => {
109
beforeEach(() => {
1110
TestBed.configureTestingModule({
1211
imports: [
13-
HttpClientTestingModule,
1412
RouterTestingModule
1513
]
1614
});

src/app/authentication/guard/logged-out.guard.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable } from '@angular/core';
22
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
33
import { Observable } from 'rxjs';
4-
import { AuthenticationService } from '../service/authentication.service';
4+
import { AuthenticationContainer } from '../service/authentication-container.service';
55

66
/**
77
* Logged out guard. Allows access only if the user in session is logged out. Otherwise redirects
@@ -16,13 +16,13 @@ export class LoggedOutGuard implements CanActivate {
1616

1717
constructor(
1818
private router: Router,
19-
private authenticationService: AuthenticationService
19+
private authenticationContainer: AuthenticationContainer
2020
) { }
2121

2222
canActivate(
2323
route: ActivatedRouteSnapshot,
2424
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
25-
const logged = this.authenticationService.getUser().logged;
25+
const logged = this.authenticationContainer.getLoginDetails().logged;
2626
let active;
2727

2828
if (logged) {

src/app/authentication/interceptor/basic-authentication.interceptor.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { HttpClientTestingModule } from '@angular/common/http/testing';
21
import { TestBed } from '@angular/core/testing';
32

43
import { BasicAuthenticationInterceptor } from './basic-authentication.interceptor';
54

65
describe('BasicAuthenticationInterceptor', () => {
76
beforeEach(() => TestBed.configureTestingModule({
8-
imports: [
9-
HttpClientTestingModule
10-
],
117
providers: [
128
BasicAuthenticationInterceptor
139
]

src/app/authentication/interceptor/basic-authentication.interceptor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/c
22
import { Injectable } from '@angular/core';
33
import { environment } from '@environments/environment';
44
import { Observable } from 'rxjs';
5-
import { AuthenticationService } from '../service/authentication.service';
5+
import { AuthenticationContainer } from '../service/authentication-container.service';
66

77
/**
88
* Basic HTTP authentication interceptor. Adds the basic authentication token to all request to
@@ -16,7 +16,7 @@ export class BasicAuthenticationInterceptor implements HttpInterceptor {
1616
private tokenHeaderIdentifier = 'Basic'
1717

1818
constructor(
19-
private authenticationService: AuthenticationService
19+
private authenticationContainer: AuthenticationContainer
2020
) { }
2121

2222
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
@@ -28,8 +28,8 @@ export class BasicAuthenticationInterceptor implements HttpInterceptor {
2828
// It is a request to our API
2929

3030
// Acquire the current user token
31-
const logged = this.authenticationService.getUser().logged;
32-
const token = this.authenticationService.getUser().token;
31+
const logged = this.authenticationContainer.getLoginDetails().logged;
32+
const token = this.authenticationContainer.getLoginDetails().token;
3333

3434
if ((logged) && (token)) {
3535
// Has token

src/app/authentication/interceptor/unauthorized.interceptor.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import { HttpClientTestingModule } from '@angular/common/http/testing';
21
import { TestBed } from '@angular/core/testing';
32

43
import { UnauthorizedErrorInterceptor } from './unauthorized.interceptor';
54

65
describe('UnauthorizedErrorInterceptor', () => {
76
beforeEach(() => TestBed.configureTestingModule({
8-
imports: [
9-
HttpClientTestingModule
10-
],
117
providers: [
128
UnauthorizedErrorInterceptor
139
]

src/app/authentication/interceptor/unauthorized.interceptor.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/c
22
import { Injectable } from '@angular/core';
33
import { environment } from '@environments/environment';
44
import { catchError, Observable, throwError } from 'rxjs';
5-
import { AuthenticationService } from '../service/authentication.service';
5+
import { AuthenticationContainer } from '../service/authentication-container.service';
66

77
/**
88
* Unauthorized error interceptor. Logs out the user in session on an authorization error.
@@ -11,7 +11,7 @@ import { AuthenticationService } from '../service/authentication.service';
1111
export class UnauthorizedErrorInterceptor implements HttpInterceptor {
1212

1313
constructor(
14-
private authenticationService: AuthenticationService
14+
private authenticationContainer: AuthenticationContainer
1515
) { }
1616

1717
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
@@ -25,7 +25,7 @@ export class UnauthorizedErrorInterceptor implements HttpInterceptor {
2525
if (error.status === 401) {
2626
// Unauthenticated
2727
// Logs out
28-
this.authenticationService.logout();
28+
this.authenticationContainer.reset();
2929
location.reload();
3030
}
3131

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TestBed } from '@angular/core/testing';
2+
3+
import { AuthenticationContainer } from './authentication-container.service';
4+
5+
describe('AuthenticationContainer', () => {
6+
let service: AuthenticationContainer;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(AuthenticationContainer);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { Injectable } from '@angular/core';
2+
import { BehaviorSubject, Observable } from 'rxjs';
3+
import { LoginDetails } from '../model/login-details';
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class AuthenticationContainer {
9+
10+
private userKey = 'user';
11+
12+
private loginDetailsSubject: BehaviorSubject<LoginDetails>;
13+
14+
private loginDetails: Observable<LoginDetails>;
15+
16+
constructor(
17+
) {
18+
this.loginDetailsSubject = this.readUserFromLocal();
19+
this.loginDetails = this.loginDetailsSubject.asObservable();
20+
}
21+
22+
/**
23+
* Reads the login status from the local storage. This allows recovering users stored as part of
24+
* the 'remember me' functionality.
25+
*
26+
* @returns the user stored in the local storage as part of the 'remember me'
27+
*/
28+
private readUserFromLocal(): BehaviorSubject<LoginDetails> {
29+
let subject: BehaviorSubject<LoginDetails>;
30+
31+
// If the user was stored, load it
32+
const localUser = localStorage.getItem(this.userKey);
33+
if (localUser) {
34+
// User found in local storage
35+
const readUser = JSON.parse(localUser);
36+
subject = new BehaviorSubject<LoginDetails>(readUser);
37+
} else {
38+
// User not found
39+
// Use default user
40+
subject = new BehaviorSubject<LoginDetails>(new LoginDetails());
41+
}
42+
43+
return subject;
44+
}
45+
46+
/**
47+
* Logs out the current user.
48+
*/
49+
public reset() {
50+
// Replace local data with empty login details
51+
this.loginDetailsSubject.next(new LoginDetails());
52+
53+
// Clear local storage
54+
localStorage.removeItem(this.userKey);
55+
}
56+
57+
/**
58+
* Returns the login details for the user currently in session.
59+
* @returns the user currently in session
60+
*/
61+
public getLoginDetails(): LoginDetails {
62+
return this.loginDetailsSubject.value;
63+
}
64+
65+
/**
66+
* Returns the login details for the user currently in session as an observable. This allows reacting to new logins or logouts.
67+
*
68+
* @returns the login details for the user currently in session as an observable
69+
*/
70+
public getUserObservable(): Observable<LoginDetails> {
71+
return this.loginDetails;
72+
}
73+
74+
/**
75+
* Stores the received login details. This takes two steps, first it is stored in the local
76+
* subject. Then, if the 'remember me' option is enabled, it will be stored in the local storage.
77+
*
78+
* @param loginDetails login details to store
79+
*/
80+
public setLoginDetails(loginDetails: LoginDetails, rememberMe: Boolean) {
81+
this.loginDetailsSubject.next(loginDetails);
82+
83+
if (rememberMe) {
84+
// Store login details in the local storage
85+
// This allows getting them back on a page reload
86+
localStorage.setItem(this.userKey, JSON.stringify(loginDetails));
87+
}
88+
}
89+
90+
}

0 commit comments

Comments
 (0)