mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 14:31:12 -05:00
238 lines
5.7 KiB
TypeScript
238 lines
5.7 KiB
TypeScript
/**
|
|
* Authentication Service
|
|
*
|
|
* Core authentication service that handles login, registration, logout,
|
|
* token refresh, and user profile management with the Django backend.
|
|
*/
|
|
|
|
import { apiClient } from '@/lib/api/client';
|
|
import {
|
|
LoginCredentials,
|
|
RegisterData,
|
|
AuthResponse,
|
|
User,
|
|
ChangePasswordData,
|
|
UpdateProfileData,
|
|
UpdatePreferencesData,
|
|
UserPreferences,
|
|
UserRole,
|
|
UserPermissions,
|
|
UserStats,
|
|
} from '@/lib/types/auth';
|
|
import { tokenStorage } from './tokenStorage';
|
|
|
|
/**
|
|
* Login with email and password
|
|
*/
|
|
export async function login(credentials: LoginCredentials): Promise<AuthResponse> {
|
|
const response = await apiClient.post<AuthResponse>('/api/v1/auth/login', credentials);
|
|
|
|
// Store tokens
|
|
tokenStorage.setAccessToken(response.data.access);
|
|
tokenStorage.setRefreshToken(response.data.refresh);
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Register a new user account
|
|
*/
|
|
export async function register(data: RegisterData): Promise<User> {
|
|
const response = await apiClient.post<User>('/api/v1/auth/register', data);
|
|
|
|
// Note: Django returns 201 and user profile, but doesn't auto-login
|
|
// The frontend should prompt to login after successful registration
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Logout and clear tokens
|
|
*/
|
|
export async function logout(): Promise<void> {
|
|
try {
|
|
// Call logout endpoint (blacklists refresh token on server)
|
|
await apiClient.post('/api/v1/auth/logout');
|
|
} catch (error) {
|
|
// Continue with local logout even if server call fails
|
|
console.error('Logout API call failed:', error);
|
|
} finally {
|
|
// Always clear local tokens
|
|
tokenStorage.clearTokens();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refresh access token using refresh token
|
|
*/
|
|
export async function refreshAccessToken(): Promise<AuthResponse> {
|
|
const refreshToken = tokenStorage.getRefreshToken();
|
|
|
|
if (!refreshToken) {
|
|
throw new Error('No refresh token available');
|
|
}
|
|
|
|
const response = await apiClient.post<AuthResponse>('/api/v1/auth/token/refresh', {
|
|
refresh: refreshToken,
|
|
});
|
|
|
|
// Store new tokens
|
|
tokenStorage.setAccessToken(response.data.access);
|
|
tokenStorage.setRefreshToken(response.data.refresh);
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get current user profile
|
|
*/
|
|
export async function getCurrentUser(): Promise<User> {
|
|
const response = await apiClient.get<User>('/api/v1/auth/me');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Update current user profile
|
|
*/
|
|
export async function updateProfile(data: UpdateProfileData): Promise<User> {
|
|
const response = await apiClient.patch<User>('/api/v1/auth/me', data);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get current user's role
|
|
*/
|
|
export async function getUserRole(): Promise<UserRole> {
|
|
const response = await apiClient.get<UserRole>('/api/v1/auth/me/role');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get current user's permissions
|
|
*/
|
|
export async function getUserPermissions(): Promise<UserPermissions> {
|
|
const response = await apiClient.get<UserPermissions>('/api/v1/auth/me/permissions');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get current user's statistics
|
|
*/
|
|
export async function getUserStats(): Promise<UserStats> {
|
|
const response = await apiClient.get<UserStats>('/api/v1/auth/me/stats');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get current user's preferences
|
|
*/
|
|
export async function getUserPreferences(): Promise<UserPreferences> {
|
|
const response = await apiClient.get<UserPreferences>('/api/v1/auth/me/preferences');
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Update current user's preferences
|
|
*/
|
|
export async function updatePreferences(data: UpdatePreferencesData): Promise<UserPreferences> {
|
|
const response = await apiClient.patch<UserPreferences>('/api/v1/auth/me/preferences', data);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Change password for current user
|
|
*/
|
|
export async function changePassword(data: ChangePasswordData): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/password/change', data);
|
|
}
|
|
|
|
/**
|
|
* Request password reset email
|
|
*/
|
|
export async function requestPasswordReset(email: string): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/password/reset', { email });
|
|
}
|
|
|
|
/**
|
|
* Confirm password reset with token
|
|
*/
|
|
export async function confirmPasswordReset(
|
|
token: string,
|
|
password: string,
|
|
passwordConfirm: string
|
|
): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/password/reset/confirm', {
|
|
token,
|
|
password,
|
|
password_confirm: passwordConfirm,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Verify email with token
|
|
*/
|
|
export async function verifyEmail(token: string): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/verify-email', { token });
|
|
}
|
|
|
|
/**
|
|
* Resend email verification
|
|
*/
|
|
export async function resendVerification(): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/verify-email/resend');
|
|
}
|
|
|
|
/**
|
|
* Request email change
|
|
*/
|
|
export async function requestEmailChange(newEmail: string): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/change-email', {
|
|
new_email: newEmail,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Confirm email change with token
|
|
*/
|
|
export async function confirmEmailChange(token: string): Promise<void> {
|
|
await apiClient.post('/api/v1/auth/change-email/confirm', { token });
|
|
}
|
|
|
|
/**
|
|
* Check if user is authenticated
|
|
*/
|
|
export function isAuthenticated(): boolean {
|
|
return tokenStorage.hasValidAccessToken();
|
|
}
|
|
|
|
/**
|
|
* Get access token
|
|
*/
|
|
export function getAccessToken(): string | null {
|
|
return tokenStorage.getAccessToken();
|
|
}
|
|
|
|
// Export all functions as a service object for convenience
|
|
export const authService = {
|
|
login,
|
|
register,
|
|
logout,
|
|
refreshAccessToken,
|
|
getCurrentUser,
|
|
updateProfile,
|
|
getUserRole,
|
|
getUserPermissions,
|
|
getUserStats,
|
|
getUserPreferences,
|
|
updatePreferences,
|
|
changePassword,
|
|
requestPasswordReset,
|
|
confirmPasswordReset,
|
|
verifyEmail,
|
|
resendVerification,
|
|
requestEmailChange,
|
|
confirmEmailChange,
|
|
isAuthenticated,
|
|
getAccessToken,
|
|
};
|