Refactor API files to provide mock implementations for analytics, auth, collections, ratings, scripts, and users, streamlining the codebase for frontend-only functionality. Remove legacy database schema and browser compatibility files to enhance clarity and maintainability.
This commit is contained in:
217
temp_api_backup/api/auth.ts
Normal file
217
temp_api_backup/api/auth.ts
Normal file
@ -0,0 +1,217 @@
|
||||
import bcrypt from 'bcrypt';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { getUserByEmail, getUserByUsername, createUser } from './users';
|
||||
import { ApiError } from './index';
|
||||
|
||||
export interface LoginCredentials {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface RegisterData {
|
||||
email: string;
|
||||
username: string;
|
||||
displayName: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface AuthToken {
|
||||
token: string;
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
displayName: string;
|
||||
isAdmin: boolean;
|
||||
isModerator: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'default-secret-key';
|
||||
const SALT_ROUNDS = 12;
|
||||
|
||||
// Hash password
|
||||
export async function hashPassword(password: string): Promise<string> {
|
||||
try {
|
||||
return await bcrypt.hash(password, SALT_ROUNDS);
|
||||
} catch (error) {
|
||||
throw new ApiError('Failed to hash password', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify password
|
||||
export async function verifyPassword(password: string, hashedPassword: string): Promise<boolean> {
|
||||
try {
|
||||
return await bcrypt.compare(password, hashedPassword);
|
||||
} catch (error) {
|
||||
throw new ApiError('Failed to verify password', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate JWT token
|
||||
export function generateToken(user: any): string {
|
||||
const payload = {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
isAdmin: user.isAdmin,
|
||||
isModerator: user.isModerator,
|
||||
};
|
||||
|
||||
return jwt.sign(payload, JWT_SECRET, { expiresIn: '7d' });
|
||||
}
|
||||
|
||||
// Verify JWT token
|
||||
export function verifyToken(token: string): any {
|
||||
try {
|
||||
return jwt.verify(token, JWT_SECRET);
|
||||
} catch (error) {
|
||||
throw new ApiError('Invalid or expired token', 401);
|
||||
}
|
||||
}
|
||||
|
||||
// Login user
|
||||
export async function login(credentials: LoginCredentials): Promise<AuthToken> {
|
||||
try {
|
||||
const user = await getUserByEmail(credentials.email);
|
||||
if (!user) {
|
||||
throw new ApiError('Invalid email or password', 401);
|
||||
}
|
||||
|
||||
// Note: In a real implementation, you would verify the password against a hash
|
||||
// For this demo, we'll assume password verification passes
|
||||
// const isValidPassword = await verifyPassword(credentials.password, user.passwordHash);
|
||||
// if (!isValidPassword) {
|
||||
// throw new ApiError('Invalid email or password', 401);
|
||||
// }
|
||||
|
||||
const token = generateToken(user);
|
||||
|
||||
return {
|
||||
token,
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
isAdmin: user.isAdmin || false,
|
||||
isModerator: user.isModerator || false,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) throw error;
|
||||
throw new ApiError('Login failed', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Register user
|
||||
export async function register(data: RegisterData): Promise<AuthToken> {
|
||||
try {
|
||||
// Check if email already exists
|
||||
const existingEmail = await getUserByEmail(data.email);
|
||||
if (existingEmail) {
|
||||
throw new ApiError('Email already registered', 400);
|
||||
}
|
||||
|
||||
// Check if username already exists
|
||||
const existingUsername = await getUserByUsername(data.username);
|
||||
if (existingUsername) {
|
||||
throw new ApiError('Username already taken', 400);
|
||||
}
|
||||
|
||||
// Validate email format
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(data.email)) {
|
||||
throw new ApiError('Invalid email format', 400);
|
||||
}
|
||||
|
||||
// Validate username format
|
||||
const usernameRegex = /^[a-zA-Z0-9_]{3,20}$/;
|
||||
if (!usernameRegex.test(data.username)) {
|
||||
throw new ApiError('Username must be 3-20 characters and contain only letters, numbers, and underscores', 400);
|
||||
}
|
||||
|
||||
// Validate password strength
|
||||
if (data.password.length < 6) {
|
||||
throw new ApiError('Password must be at least 6 characters long', 400);
|
||||
}
|
||||
|
||||
// Hash password and create user
|
||||
// const passwordHash = await hashPassword(data.password);
|
||||
|
||||
const user = await createUser({
|
||||
email: data.email,
|
||||
username: data.username,
|
||||
displayName: data.displayName,
|
||||
// passwordHash, // In a real implementation
|
||||
});
|
||||
|
||||
const token = generateToken(user);
|
||||
|
||||
return {
|
||||
token,
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
isAdmin: user.isAdmin || false,
|
||||
isModerator: user.isModerator || false,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) throw error;
|
||||
throw new ApiError('Registration failed', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh token
|
||||
export async function refreshToken(token: string): Promise<AuthToken> {
|
||||
try {
|
||||
const decoded = verifyToken(token);
|
||||
const user = await getUserByEmail(decoded.email);
|
||||
|
||||
if (!user) {
|
||||
throw new ApiError('User not found', 404);
|
||||
}
|
||||
|
||||
const newToken = generateToken(user);
|
||||
|
||||
return {
|
||||
token: newToken,
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.username,
|
||||
displayName: user.displayName,
|
||||
isAdmin: user.isAdmin || false,
|
||||
isModerator: user.isModerator || false,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) throw error;
|
||||
throw new ApiError('Token refresh failed', 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Change password
|
||||
export async function changePassword(_userId: string, _currentPassword: string, newPassword: string): Promise<boolean> {
|
||||
try {
|
||||
// In a real implementation, you would:
|
||||
// 1. Get user by ID
|
||||
// 2. Verify current password
|
||||
// 3. Hash new password
|
||||
// 4. Update user record
|
||||
|
||||
if (newPassword.length < 6) {
|
||||
throw new ApiError('New password must be at least 6 characters long', 400);
|
||||
}
|
||||
|
||||
// Placeholder for password change logic
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) throw error;
|
||||
throw new ApiError('Password change failed', 500);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user