DeutschLernen/german-app-frontend/src/lib/api/auth.ts
Lasse Rune Hansen 50f1b8a8dc feat(backend): Implement mandatory authentication and admin module
- Add Role property to User entity with migration
- Create BootstrapController for first admin user creation
- Remove [AllowAnonymous] from all learning content controllers
- Create AdminController with admin-only endpoints
- Create AdminService for user management
- Create UserReportService for progress reports
- Add UserRepository implementation
- Update AuthService with role support

feat(frontend): Implement authentication system
- Add AuthStore with React context for auth state management
- Create Login, Register, Landing, and Home pages
- Add ProtectedRoute and AdminRoute components
- Create Auth API types and client
- Configure Vite with @/ path alias
- Add comprehensive CSS styles for auth and landing pages

BREAKING CHANGE: All learning content now requires authentication.
Users must register and sign in before accessing lessons, quizzes, and stories.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-06-14 12:42:15 +02:00

152 lines
3.5 KiB
TypeScript

/**
* Auth API client for the DeutschLernen frontend
* Handles authentication requests to the backend
*/
import type {
RegisterRequest,
LoginRequest,
AuthResponse,
CurrentUser,
RefreshTokenRequest,
RefreshTokenResponse,
} from '@/types/api/auth';
// Base API URL - uses /api prefix for Docker proxy
const BASE_URL = import.meta.env.PROD
? '/api'
: import.meta.env.VITE_API_URL || 'http://localhost:5000/api';
/**
* Register a new user
*/
export async function register(request: RegisterRequest): Promise<AuthResponse> {
const response = await fetch(`${BASE_URL}/auth/register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Registration failed');
}
return response.json();
}
/**
* Login an existing user
*/
export async function login(request: LoginRequest): Promise<AuthResponse> {
const response = await fetch(`${BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Login failed');
}
return response.json();
}
/**
* Get current authenticated user info
*/
export async function getCurrentUser(token: string): Promise<CurrentUser> {
const response = await fetch(`${BASE_URL}/auth/me`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Failed to get current user');
}
return response.json();
}
/**
* Refresh access token using refresh token
*/
export async function refreshToken(request: RefreshTokenRequest): Promise<RefreshTokenResponse> {
const response = await fetch(`${BASE_URL}/auth/refresh`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request.refreshToken),
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Token refresh failed');
}
return response.json();
}
/**
* Revoke refresh token
*/
export async function revokeRefreshToken(refreshToken: string, accessToken: string): Promise<void> {
const response = await fetch(`${BASE_URL}/auth/revoke-refresh`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify(refreshToken),
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Failed to revoke refresh token');
}
}
/**
* Check if an admin user exists (for bootstrap)
*/
export async function checkAdminExists(): Promise<boolean> {
const response = await fetch(`${BASE_URL}/bootstrap/admin-exists`, {
method: 'GET',
});
if (!response.ok) {
return false;
}
return response.json();
}
/**
* Create first admin user (bootstrap endpoint)
*/
export async function createAdminUser(request: RegisterRequest): Promise<AuthResponse> {
const response = await fetch(`${BASE_URL}/bootstrap/admin`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(request),
});
if (!response.ok) {
const error = await response.text();
throw new Error(error || 'Failed to create admin user');
}
return response.json();
}