From a00863ef9e97c918f018862b897f29c7ec6cfe05 Mon Sep 17 00:00:00 2001 From: Chneemann Date: Mon, 24 Mar 2025 09:10:25 +0100 Subject: [PATCH] feat: created TokenService and moved logic from AuthService and ApiService --- .../components/board/task/task.component.html | 3 +- src/app/guards/authenticated.guard.ts | 9 +- .../guards/redirect-if-authenticated.guard.ts | 9 +- src/app/interfaces/task.interface.ts | 1 - src/app/services/api.service.ts | 27 ++++- src/app/services/auth.service.ts | 111 ++++++------------ src/app/services/token.service.ts | 45 +++++++ .../components/header/header.component.ts | 1 - .../task-overlay/task-overlay.component.html | 2 +- 9 files changed, 122 insertions(+), 86 deletions(-) create mode 100755 src/app/services/token.service.ts diff --git a/src/app/components/board/task/task.component.html b/src/app/components/board/task/task.component.html index c2f71a6..77159d8 100644 --- a/src/app/components/board/task/task.component.html +++ b/src/app/components/board/task/task.component.html @@ -51,8 +51,7 @@ [style.background-color]="user.color" >{{ user.initials }}} } @for (user of task.userData; track user) { @for (assigned of - task.assignees; track assigned.id) { @if (assigned.userId === user.id) - { + task.assignees; track assigned) { @if (assigned.userId === user.id) { | Promise | boolean { - const authToken = this.authService.checkAuthToken(); + const authToken = this.tokenService.getAuthToken(); if (!authToken) { this.router.navigate(['/login']); return false; diff --git a/src/app/guards/redirect-if-authenticated.guard.ts b/src/app/guards/redirect-if-authenticated.guard.ts index cd17092..25fbf1e 100644 --- a/src/app/guards/redirect-if-authenticated.guard.ts +++ b/src/app/guards/redirect-if-authenticated.guard.ts @@ -3,15 +3,20 @@ import { Router } from '@angular/router'; import { Observable, of } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; import { AuthService } from '../services/auth.service'; +import { TokenService } from '../services/token.service'; @Injectable({ providedIn: 'root', }) export class RedirectIfAuthenticatedGuard { - constructor(private authService: AuthService, private router: Router) {} + constructor( + private authService: AuthService, + private tokenService: TokenService, + private router: Router + ) {} canActivate(): Observable | Promise | boolean { - const authToken = this.authService.checkAuthToken(); + const authToken = this.tokenService.getAuthToken(); if (!authToken) { return true; } diff --git a/src/app/interfaces/task.interface.ts b/src/app/interfaces/task.interface.ts index b8cf6ae..c5b4694 100644 --- a/src/app/interfaces/task.interface.ts +++ b/src/app/interfaces/task.interface.ts @@ -24,6 +24,5 @@ export interface Subtask { } export interface Assignee { - id: string; userId: string; } diff --git a/src/app/services/api.service.ts b/src/app/services/api.service.ts index 1e23764..326d26d 100644 --- a/src/app/services/api.service.ts +++ b/src/app/services/api.service.ts @@ -1,9 +1,10 @@ import { Injectable, signal } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { apiConfig } from '../environments/config'; import { Task } from '../interfaces/task.interface'; import { User } from '../interfaces/user.interface'; +import { TokenService } from './token.service'; @Injectable({ providedIn: 'root', @@ -11,7 +12,7 @@ import { User } from '../interfaces/user.interface'; export class ApiService { private apiUrl = apiConfig.apiUrl; - constructor(private http: HttpClient) {} + constructor(private http: HttpClient, private tokenService: TokenService) {} // ------------- TASKS ------------- // @@ -43,4 +44,26 @@ export class ApiService { params: { ids: userIds.join(',') }, }); } + + // ------------- TOKEN ------------- // + + private addAuthHeaders(headers: HttpHeaders): HttpHeaders { + const token = this.tokenService.getAuthToken(); + if (token) { + return headers.set('Authorization', `Token ${token}`); + } + return headers; + } + + post(url: string, body: any): Observable { + let headers = new HttpHeaders(); + headers = this.addAuthHeaders(headers); + return this.http.post(url, body, { headers }); + } + + get(url: string): Observable { + let headers = new HttpHeaders(); + headers = this.addAuthHeaders(headers); + return this.http.get(url, { headers }); + } } diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index 04c9f5f..ffea3f6 100755 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -1,4 +1,3 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { BehaviorSubject, @@ -9,102 +8,64 @@ import { of, } from 'rxjs'; import { apiConfig } from '../environments/config'; +import { ApiService } from './api.service'; +import { TokenService } from './token.service'; @Injectable({ providedIn: 'root', }) export class AuthService { private apiUrl = apiConfig.apiUrl; + private currentUserIdSubject = new BehaviorSubject(null); - private currentUserIdSubject: BehaviorSubject = - new BehaviorSubject(null); - - constructor(private http: HttpClient) { - const storedUserId = - localStorage.getItem('currentUserId') || - sessionStorage.getItem('currentUserId'); - this.currentUserIdSubject = new BehaviorSubject( - storedUserId - ); + constructor( + private apiService: ApiService, + private tokenService: TokenService + ) { + this.currentUserIdSubject.next(this.tokenService.getUserId()); } async login(body: any, storage: boolean) { - const data = (await lastValueFrom( - this.http.post(`${this.apiUrl}/auth/login/`, body) - )) as { token: string; user_id: string }; - this.storeAuthToken(data.token, storage); - this.storeUserId(data.user_id, storage); - this.currentUserIdSubject.next(data.user_id); + try { + const data = await lastValueFrom( + this.apiService.post<{ token: string; userId: string }>( + `${this.apiUrl}/auth/login/`, + body + ) + ); + + this.tokenService.storeAuthToken(data.token, storage); + this.tokenService.storeUserId(data.userId, storage); + this.currentUserIdSubject.next(data.userId); + } catch (error) { + console.error('Login failed:', error); + throw error; + } } async logout() { - const token = this.checkAuthToken(); - if (!token) return; + try { + await lastValueFrom( + this.apiService.post(`${this.apiUrl}/auth/logout/`, {}) + ); - await lastValueFrom( - this.http.post( - `${this.apiUrl}/auth/logout/`, - {}, - { headers: { Authorization: `Token ${token}` } } - ) - ).catch((error) => console.error('Logout failed:', error)); + this.tokenService.deleteAuthToken(); + this.tokenService.deleteUserId(); + this.currentUserIdSubject.next(null); - this.deleteAuthToken(); - this.deleteUserId(); - window.location.href = '/login'; + window.location.href = '/login'; + } catch (error) { + console.error('Logout failed:', error); + } } checkAuthUser(): Observable { - const headers = this.getAuthHeaders(); - return this.http.get(`${this.apiUrl}/auth/`, { headers }).pipe( - map(() => { - return true; - }), + return this.apiService.get(`${this.apiUrl}/auth/`).pipe( + map(() => true), catchError(() => of(false)) ); } - private getAuthHeaders(): HttpHeaders { - let authToken = localStorage.getItem('authToken'); - if (!authToken) { - authToken = sessionStorage.getItem('authToken'); - } - return new HttpHeaders({ - Authorization: `Token ${authToken}`, - }); - } - - private storeAuthToken(data: any, storage: boolean) { - storage - ? localStorage.setItem('authToken', data.toString()) - : sessionStorage.setItem('authToken', data.toString()); - } - - private storeUserId(userId: string, storage: boolean) { - if (storage) { - localStorage.setItem('currentUserId', userId); - } else { - sessionStorage.setItem('currentUserId', userId); - } - } - - private deleteAuthToken() { - localStorage.removeItem('authToken'); - sessionStorage.removeItem('authToken'); - } - - private deleteUserId() { - localStorage.removeItem('currentUserId'); - sessionStorage.removeItem('currentUserId'); - this.currentUserIdSubject.next(null); - } - - checkAuthToken(): string | null { - return ( - localStorage.getItem('authToken') || sessionStorage.getItem('authToken') - ); - } - getCurrentUserId(): Observable { return this.currentUserIdSubject.asObservable(); } diff --git a/src/app/services/token.service.ts b/src/app/services/token.service.ts new file mode 100755 index 0000000..ffd3c11 --- /dev/null +++ b/src/app/services/token.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TokenService { + private TOKEN_KEY = 'authToken'; + private USER_ID_KEY = 'currentUserId'; + + storeAuthToken(token: string, persistent: boolean): void { + persistent + ? localStorage.setItem(this.TOKEN_KEY, token) + : sessionStorage.setItem(this.TOKEN_KEY, token); + } + + getAuthToken(): string | null { + return ( + localStorage.getItem(this.TOKEN_KEY) || + sessionStorage.getItem(this.TOKEN_KEY) + ); + } + + deleteAuthToken(): void { + localStorage.removeItem(this.TOKEN_KEY); + sessionStorage.removeItem(this.TOKEN_KEY); + } + + storeUserId(userId: string, persistent: boolean): void { + persistent + ? localStorage.setItem(this.USER_ID_KEY, userId) + : sessionStorage.setItem(this.USER_ID_KEY, userId); + } + + getUserId(): string | null { + return ( + localStorage.getItem(this.USER_ID_KEY) || + sessionStorage.getItem(this.USER_ID_KEY) + ); + } + + deleteUserId(): void { + localStorage.removeItem(this.USER_ID_KEY); + sessionStorage.removeItem(this.USER_ID_KEY); + } +} diff --git a/src/app/shared/components/header/header.component.ts b/src/app/shared/components/header/header.component.ts index 88d1d01..4b76346 100644 --- a/src/app/shared/components/header/header.component.ts +++ b/src/app/shared/components/header/header.component.ts @@ -4,7 +4,6 @@ import { NavbarComponent } from './navbar/navbar.component'; import { CommonModule } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { FirebaseService } from '../../../services/firebase.service'; -import { Observable } from 'rxjs'; import { AuthService } from '../../../services/auth.service'; import { ApiService } from '../../../services/api.service'; diff --git a/src/app/shared/components/overlay/task-overlay/task-overlay.component.html b/src/app/shared/components/overlay/task-overlay/task-overlay.component.html index 10a1803..5edf324 100644 --- a/src/app/shared/components/overlay/task-overlay/task-overlay.component.html +++ b/src/app/shared/components/overlay/task-overlay/task-overlay.component.html @@ -70,7 +70,7 @@ @if (task.assignees.length > 0) {

{{ "addTask.assigned" | translate }}:

- @for (assigned of task.assignees; track assigned.id) { @for (user of + @for (assigned of task.assignees; track assigned) { @for (user of task.userData; track user) { @if (assigned.userId === user.id) {