Files
thrilltrack-explorer/lib/services/auth/authService.ts

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,
};