File size: 5,977 Bytes
e4ab6d0 e664319 e4ab6d0 f8794d4 e4ab6d0 f8794d4 e4ab6d0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = location.hostname.endsWith('hf.space')
? 'https://pykara-py-learn-backend.hf.space'
: 'http://localhost:5000'; // Your Flask API base URL
private loggedInSubject = new BehaviorSubject<boolean>(false); // Shared state
public isLoggedIn$ = this.loggedInSubject.asObservable();
private refreshIntervalId: any;
constructor(private http: HttpClient, private router: Router) { }
// β
Called to check current status
isLoggedIn(): boolean {
return this.loggedInSubject.value;
}
// β
Set login status manually
setLoggedIn(status: boolean): void {
this.loggedInSubject.next(status);
}
// β
Login Method
login(username: string, password: string): Observable<any> {
return this.http.post(`${this.apiUrl}/login`, { username, password }, { withCredentials: true });
}
startAutoRefresh(): void {
if (this.refreshIntervalId) return;
this.refreshIntervalId = setInterval(() => {
this.refreshAccessToken();
}, 12 * 60 * 1000);
}
clearAutoRefresh(): void {
clearInterval(this.refreshIntervalId);
this.refreshIntervalId = null;
}
refreshAccessToken(): void {
this.http.post(`${this.apiUrl}/refresh`, {}, { withCredentials: true }).subscribe(
(response: any) => {
console.log("β
Access token refreshed:", response.access_token);
//alert("π Access token has been refreshed!");
},
(error) => {
console.error("β Refresh failed:", error);
if (
error.status === 401 &&
error.error &&
(error.error.message === 'Refresh token has expired' || error.error.message === 'Invalid refresh token')
) {
//alert("β οΈ Your session has expired. Please log in again.");
// Clear cookies manually (if needed)
this.clearTokens();
// Redirect to login
this.router.navigate(['/auth']);
}
}
);
}
logout(): Observable<any> {
console.log("π§ Sending logout request with credentials");
return this.http.post(`${this.apiUrl}/logout`, {}, { withCredentials: true }).pipe(
tap(response => {
console.log('π Response from backend:', response);
this.clearTokens();
this.clearAutoRefresh(); // β
Stop auto-refresh
this.setLoggedIn(false); // β
Reflect logout in UI
}),
catchError(error => {
console.error('β Error from backend:', error);
// Still ensure local state reflects logout
this.clearTokens();
this.clearAutoRefresh();
this.setLoggedIn(false);
return throwError(() => error);
})
);
}
clearTokens(): void {
document.cookie = 'access_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
document.cookie = 'refresh_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
this.clearAutoRefresh(); // β
}
//// β
Check if user is logged in (check for presence of cookies)
//isLoggedIn(): boolean {
// // Check cookies directly (this will happen automatically when the browser sends cookies)
// // Check if the cookies are present (you can do it manually using a service or via backend)
// return document.cookie.includes('access_token');
//}
// β
Get access token (using cookies)
getAccessToken(): string | null {
const cookies = document.cookie.split('; ');
for (let cookie of cookies) {
if (cookie.startsWith('access_token=')) {
return cookie.split('=')[1];
}
}
return null;
}
// β
Save tokens (Not necessary, as tokens are managed via cookies)
saveTokens(accessToken: string, refreshToken: string): void {
// No need for this if you're using cookies, but if you want to persist in localStorage, use:
localStorage.setItem('access_token', accessToken);
localStorage.setItem('refresh_token', refreshToken);
}
//checkSession(): Observable<boolean> {
// return this.http.get(`${this.apiUrl}/check-auth`, { withCredentials: true }).pipe(
// tap((res: any) => {
// console.log('β
Session valid:', res);
// this.setLoggedIn(true);
// }),
// catchError((err) => {
// console.warn('β Session check failed:', err);
// this.setLoggedIn(false);
// return [false]; // Return false on error
// })
// );
//}
checkSession(): Observable<boolean> {
return this.http.get(`${this.apiUrl}/check-auth`, { withCredentials: true }).pipe(
tap((res: any) => {
console.log('β
Session valid:', res);
this.setLoggedIn(true);
this.startAutoRefresh();
return true; // β
Important!
}),
catchError((err) => {
if (err.status === 401) {
// Access token may be expired. Try refresh
console.warn('π Access token expired. Trying to refresh...');
return this.http.post(`${this.apiUrl}/refresh`, {}, { withCredentials: true }).pipe(
tap((refreshRes: any) => {
console.log("β
Token refreshed during checkSession.");
//alert("β
Token refreshed during checkSession.");
this.setLoggedIn(true);
this.startAutoRefresh();
}),
catchError((refreshErr) => {
console.error("β Refresh token failed during checkSession.", refreshErr);
this.setLoggedIn(false);
return of(false);
})
);
} else {
console.error("β Unknown error during checkSession", err);
this.setLoggedIn(false);
return of(false);
}
})
);
}
}
|