This commit includes: - Django backend with multi-tenancy (django-tenants) - React + TypeScript frontend with Vite - Platform administration API with role-based access control - Authentication system with token-based auth - Quick login dev tools for testing different user roles - CORS and CSRF configuration for local development - Docker development environment setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
114 lines
2.4 KiB
TypeScript
114 lines
2.4 KiB
TypeScript
/**
|
|
* Authentication API
|
|
*/
|
|
|
|
import apiClient from './client';
|
|
|
|
export interface LoginCredentials {
|
|
username: string;
|
|
password: string;
|
|
}
|
|
|
|
import { UserRole } from '../types';
|
|
|
|
export interface MasqueradeStackEntry {
|
|
user_id: number;
|
|
username: string;
|
|
role: UserRole;
|
|
business_id?: number;
|
|
business_subdomain?: string;
|
|
}
|
|
|
|
export interface LoginResponse {
|
|
access: string;
|
|
refresh: string;
|
|
user: {
|
|
id: number;
|
|
username: string;
|
|
email: string;
|
|
name: string;
|
|
role: UserRole;
|
|
avatar_url?: string;
|
|
email_verified?: boolean;
|
|
is_staff: boolean;
|
|
is_superuser: boolean;
|
|
business?: number;
|
|
business_name?: string;
|
|
business_subdomain?: string;
|
|
};
|
|
masquerade_stack?: MasqueradeStackEntry[];
|
|
}
|
|
|
|
export interface User {
|
|
id: number;
|
|
username: string;
|
|
email: string;
|
|
name: string;
|
|
role: UserRole;
|
|
avatar_url?: string;
|
|
email_verified?: boolean;
|
|
is_staff: boolean;
|
|
is_superuser: boolean;
|
|
business?: number;
|
|
business_name?: string;
|
|
business_subdomain?: string;
|
|
}
|
|
|
|
/**
|
|
* Login user
|
|
*/
|
|
export const login = async (credentials: LoginCredentials): Promise<LoginResponse> => {
|
|
const response = await apiClient.post<LoginResponse>('/api/auth/login/', credentials);
|
|
return response.data;
|
|
};
|
|
|
|
/**
|
|
* Logout user
|
|
*/
|
|
export const logout = async (): Promise<void> => {
|
|
await apiClient.post('/api/auth/logout/');
|
|
};
|
|
|
|
/**
|
|
* Get current user
|
|
*/
|
|
export const getCurrentUser = async (): Promise<User> => {
|
|
const response = await apiClient.get<User>('/api/auth/me/');
|
|
return response.data;
|
|
};
|
|
|
|
/**
|
|
* Refresh access token
|
|
*/
|
|
export const refreshToken = async (refresh: string): Promise<{ access: string }> => {
|
|
const response = await apiClient.post('/api/auth/refresh/', { refresh });
|
|
return response.data;
|
|
};
|
|
|
|
/**
|
|
* Masquerade as another user
|
|
*/
|
|
export const masquerade = async (
|
|
username: string,
|
|
masquerade_stack?: MasqueradeStackEntry[]
|
|
): Promise<LoginResponse> => {
|
|
const response = await apiClient.post<LoginResponse>(
|
|
`/api/users/${username}/masquerade/`,
|
|
{ masquerade_stack }
|
|
);
|
|
return response.data;
|
|
};
|
|
|
|
/**
|
|
* Stop masquerading and return to previous user
|
|
*/
|
|
export const stopMasquerade = async (
|
|
masquerade_stack: MasqueradeStackEntry[]
|
|
): Promise<LoginResponse> => {
|
|
const response = await apiClient.post<LoginResponse>(
|
|
'/api/users/stop_masquerade/',
|
|
{ masquerade_stack }
|
|
);
|
|
return response.data;
|
|
};
|