py-learn / src /app /auth /auth.service.ts
Anupriya
Frontend update and image
f8794d4
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);
}
})
);
}
}