213 lines
7.0 KiB
TypeScript
213 lines
7.0 KiB
TypeScript
import { createContext, useContext, useEffect, useState } from 'react';
|
|
import { generateId } from '@/lib/utils';
|
|
import { AdminUser, createSuperUser, createAdminUser, hasPermission } from '@/lib/admin';
|
|
|
|
interface User extends AdminUser {}
|
|
|
|
interface AuthContextType {
|
|
user: User | null;
|
|
isLoading: boolean;
|
|
login: (email: string, password: string) => Promise<boolean>;
|
|
register: (email: string, username: string, displayName: string, password: string) => Promise<boolean>;
|
|
logout: () => void;
|
|
updateProfile: (updates: Partial<User>) => Promise<boolean>;
|
|
createSuperUser: (userData: { email: string; username: string; displayName: string; password: string; bio?: string; avatarUrl?: string }) => Promise<boolean>;
|
|
createAdminUser: (userData: { email: string; username: string; displayName: string; password: string; bio?: string; avatarUrl?: string }) => Promise<boolean>;
|
|
hasPermission: (permission: string) => boolean;
|
|
}
|
|
|
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
|
|
|
interface AuthProviderProps {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function AuthProvider({ children }: AuthProviderProps) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
// Check for existing session on mount
|
|
const checkAuth = async () => {
|
|
try {
|
|
const token = localStorage.getItem('scriptshare-auth-token');
|
|
if (token) {
|
|
// In a real app, you'd validate the token with your backend
|
|
// For now, we'll just check if it exists
|
|
const userData = localStorage.getItem('scriptshare-user-data');
|
|
if (userData) {
|
|
setUser(JSON.parse(userData));
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Auth check failed:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
checkAuth();
|
|
}, []);
|
|
|
|
const login = async (email: string, _password: string): Promise<boolean> => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
// In a real app, you'd make an API call to your backend
|
|
// For now, we'll simulate a successful login
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
// Simulate user data
|
|
const mockUser: User = {
|
|
id: generateId(),
|
|
email,
|
|
username: email.split('@')[0],
|
|
displayName: email.split('@')[0],
|
|
isAdmin: false,
|
|
isModerator: false,
|
|
isSuperUser: false,
|
|
permissions: [],
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
const token = generateId();
|
|
localStorage.setItem('scriptshare-auth-token', token);
|
|
localStorage.setItem('scriptshare-user-data', JSON.stringify(mockUser));
|
|
|
|
setUser(mockUser);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Login failed:', error);
|
|
return false;
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const register = async (email: string, username: string, displayName: string, _password: string): Promise<boolean> => {
|
|
try {
|
|
setIsLoading(true);
|
|
|
|
// In a real app, you'd make an API call to your backend
|
|
// For now, we'll simulate a successful registration
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
const mockUser: User = {
|
|
id: generateId(),
|
|
email,
|
|
username,
|
|
displayName,
|
|
isAdmin: false,
|
|
isModerator: false,
|
|
isSuperUser: false,
|
|
permissions: [],
|
|
createdAt: new Date().toISOString(),
|
|
updatedAt: new Date().toISOString(),
|
|
};
|
|
|
|
const token = generateId();
|
|
localStorage.setItem('scriptshare-auth-token', token);
|
|
localStorage.setItem('scriptshare-user-data', JSON.stringify(mockUser));
|
|
|
|
setUser(mockUser);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Registration failed:', error);
|
|
return false;
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const logout = () => {
|
|
localStorage.removeItem('scriptshare-auth-token');
|
|
localStorage.removeItem('scriptshare-user-data');
|
|
setUser(null);
|
|
};
|
|
|
|
const updateProfile = async (updates: Partial<User>): Promise<boolean> => {
|
|
try {
|
|
if (!user) return false;
|
|
|
|
const updatedUser = { ...user, ...updates, updatedAt: new Date().toISOString() };
|
|
localStorage.setItem('scriptshare-user-data', JSON.stringify(updatedUser));
|
|
setUser(updatedUser);
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Profile update failed:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const createSuperUserLocal = async (userData: { email: string; username: string; displayName: string; password: string; bio?: string; avatarUrl?: string }): Promise<boolean> => {
|
|
try {
|
|
// In a real app, you'd make an API call to your backend
|
|
// For now, we'll simulate creating a superuser
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
const newSuperUser = createSuperUser(userData);
|
|
|
|
// Store in localStorage for demo purposes
|
|
const existingUsers = JSON.parse(localStorage.getItem('scriptshare-admin-users') || '[]');
|
|
existingUsers.push(newSuperUser);
|
|
localStorage.setItem('scriptshare-admin-users', JSON.stringify(existingUsers));
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Super user creation failed:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const createAdminUserLocal = async (userData: { email: string; username: string; displayName: string; password: string; bio?: string; avatarUrl?: string }): Promise<boolean> => {
|
|
try {
|
|
// In a real app, you'd make an API call to your backend
|
|
// For now, we'll simulate creating an admin user
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
const newAdminUser = createAdminUser(userData);
|
|
|
|
// Store in localStorage for demo purposes
|
|
const existingUsers = JSON.parse(localStorage.getItem('scriptshare-admin-users') || '[]');
|
|
existingUsers.push(newAdminUser);
|
|
localStorage.setItem('scriptshare-admin-users', JSON.stringify(existingUsers));
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Admin user creation failed:', error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const hasPermission = (permission: string): boolean => {
|
|
return hasPermission(user, permission);
|
|
};
|
|
|
|
const value = {
|
|
user,
|
|
isLoading,
|
|
login,
|
|
register,
|
|
logout,
|
|
updateProfile,
|
|
createSuperUser: createSuperUserLocal,
|
|
createAdminUser: createAdminUserLocal,
|
|
hasPermission,
|
|
};
|
|
|
|
return (
|
|
<AuthContext.Provider value={value}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext);
|
|
if (context === undefined) {
|
|
throw new Error('useAuth must be used within an AuthProvider');
|
|
}
|
|
return context;
|
|
}
|