typecode
AngularAuth Service/auth.service.ts
1import { Injectable } from "@angular/core"
2import { HttpClient, HttpHeaders } from "@angular/common/http"
3import { BehaviorSubject, Observable, throwError } from "rxjs"
4import { catchError, map, tap } from "rxjs/operators"
5import { Router } from "@angular/router"
6
7interface User {
8 id: string
9 email: string
10 name: string
11 role: "admin" | "user"
12}
13
14interface AuthResponse {
15 user: User
16 token: string
17 refreshToken: string
18}
19
20@Injectable({ providedIn: "root" })
21export class AuthService {
22 private currentUserSubject = new BehaviorSubject<User | null>(null)
23 private tokenKey = "auth_token"
24
25 currentUser$ = this.currentUserSubject.asObservable()
26 isAuthenticated$ = this.currentUser$.pipe(map((user) => !!user))
27
28 constructor(
29 private http: HttpClient,
30 private router: Router
31 ) {
32 this.loadStoredUser()
33 }
34
35 private loadStoredUser(): void {
36 const token = localStorage.getItem(this.tokenKey)
37 if (token && !this.isTokenExpired(token)) {
38 this.fetchCurrentUser().subscribe()
39 }
40 }
41
42 private isTokenExpired(token: string): boolean {
43 try {
44 const payload = JSON.parse(atob(token.split(".")[1]))
45 return payload.exp * 1000 < Date.now()
46 } catch {
47 return true
48 }
49 }
50
51 login(email: string, password: string): Observable<User> {
52 return this.http
53 .post<AuthResponse>("/api/auth/login", { email, password })
54 .pipe(
55 tap((response) => {
56 localStorage.setItem(this.tokenKey, response.token)
57 this.currentUserSubject.next(response.user)
58 }),
59 map((response) => response.user),
60 catchError((error) => {
61 const message = error.error?.message || "Login failed"
62 return throwError(() => new Error(message))
63 })
64 )
65 }
66
67 logout(): void {
68 localStorage.removeItem(this.tokenKey)
69 this.currentUserSubject.next(null)
70 this.router.navigate(["/login"])
71 }
72
73 private fetchCurrentUser(): Observable<User> {
74 return this.http.get<User>("/api/auth/me").pipe(
75 tap((user) => this.currentUserSubject.next(user)),
76 catchError((error) => {
77 this.logout()
78 return throwError(() => error)
79 })
80 )
81 }
82
83 getAuthHeaders(): HttpHeaders {
84 const token = localStorage.getItem(this.tokenKey)
85 return new HttpHeaders({
86 Authorization: token ? `Bearer ${token}` : "",
87 "Content-Type": "application/json",
88 })
89 }
90
91 hasRole(role: string): Observable<boolean> {
92 return this.currentUser$.pipe(
93 map((user) => user?.role === role)
94 )
95 }
96}
0WPM
100%Accuracy
00:00Time
0%
Progress