139 lines
3.3 KiB
TypeScript
139 lines
3.3 KiB
TypeScript
import { writable } from 'svelte/store';
|
|
import type { Writable } from 'svelte/store';
|
|
|
|
// Types
|
|
export interface User {
|
|
id: string;
|
|
email: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
tenant_id: string;
|
|
role: 'CLIENT_ADMIN' | 'CLIENT_USER';
|
|
is_active: boolean;
|
|
is_two_factor_enabled: boolean;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface AuthState {
|
|
user: User | null;
|
|
token: string | null;
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
}
|
|
|
|
export interface LoginRequest {
|
|
email: string;
|
|
password: string;
|
|
tenant_slug: string;
|
|
totp_code?: string;
|
|
}
|
|
|
|
export interface LoginResponse {
|
|
access_token: string;
|
|
token_type: string;
|
|
expires_in: number;
|
|
user: User;
|
|
}
|
|
|
|
// Initial state
|
|
const initialState: AuthState = {
|
|
user: null,
|
|
token: null,
|
|
isAuthenticated: false,
|
|
isLoading: false
|
|
};
|
|
|
|
// Create auth store
|
|
function createAuthStore() {
|
|
const { subscribe, set, update }: Writable<AuthState> = writable(initialState);
|
|
|
|
return {
|
|
subscribe,
|
|
|
|
// Initialize auth from localStorage
|
|
init: () => {
|
|
if (typeof window !== 'undefined') {
|
|
const token = localStorage.getItem('auth_token');
|
|
const user = localStorage.getItem('auth_user');
|
|
|
|
if (token && user) {
|
|
try {
|
|
const parsedUser = JSON.parse(user);
|
|
set({
|
|
user: parsedUser,
|
|
token,
|
|
isAuthenticated: true,
|
|
isLoading: false
|
|
});
|
|
} catch (error) {
|
|
console.error('Error parsing stored auth data:', error);
|
|
localStorage.removeItem('auth_token');
|
|
localStorage.removeItem('auth_user');
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// Login
|
|
login: async (credentials: LoginRequest): Promise<void> => {
|
|
update(state => ({ ...state, isLoading: true }));
|
|
|
|
try {
|
|
const response = await fetch('/api/v1/auth/login', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(credentials)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const error = await response.json();
|
|
throw new Error(error.detail || 'Login failed');
|
|
}
|
|
|
|
const data: LoginResponse = await response.json();
|
|
|
|
// Store auth data
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_token', data.access_token);
|
|
localStorage.setItem('auth_user', JSON.stringify(data.user));
|
|
}
|
|
|
|
set({
|
|
user: data.user,
|
|
token: data.access_token,
|
|
isAuthenticated: true,
|
|
isLoading: false
|
|
});
|
|
} catch (error) {
|
|
update(state => ({ ...state, isLoading: false }));
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
// Logout
|
|
logout: () => {
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.removeItem('auth_token');
|
|
localStorage.removeItem('auth_user');
|
|
}
|
|
set(initialState);
|
|
},
|
|
|
|
// Update user data
|
|
updateUser: (user: User) => {
|
|
update(state => ({ ...state, user }));
|
|
if (typeof window !== 'undefined') {
|
|
localStorage.setItem('auth_user', JSON.stringify(user));
|
|
}
|
|
},
|
|
|
|
// Set loading state
|
|
setLoading: (isLoading: boolean) => {
|
|
update(state => ({ ...state, isLoading }));
|
|
}
|
|
};
|
|
}
|
|
|
|
export const auth = createAuthStore(); |