Initial commit: SmoothSchedule multi-tenant scheduling platform

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>
This commit is contained in:
poduck
2025-11-27 01:43:20 -05:00
commit 2e111364a2
567 changed files with 96410 additions and 0 deletions

113
frontend/src/api/auth.ts Normal file
View File

@@ -0,0 +1,113 @@
/**
* 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;
};