recoder-code
Version:
🚀 AI-powered development platform - Chat with 32+ models, build projects, automate workflows. Free models included!
176 lines (144 loc) • 5.4 kB
text/typescript
/**
* User Service for managing user operations
*/
import { User } from '../entities/User';
import { AppDataSource } from '../database';
import bcrypt from 'bcryptjs';
export class UserService {
private userRepository = AppDataSource.getRepository(User);
async findById(id: string): Promise<User | null> {
return this.userRepository.findOne({ where: { id } }) as Promise<User | null>;
}
async findByUsername(username: string): Promise<User | null> {
return this.userRepository.findOne({ where: { username } }) as Promise<User | null>;
}
async findByEmail(email: string): Promise<User | null> {
return this.userRepository.findOne({ where: { email } }) as Promise<User | null>;
}
async create(userData: Partial<User>): Promise<User> {
const user = this.userRepository.create(userData) as User;
return this.userRepository.save(user);
}
async update(id: string, updates: Partial<User>): Promise<User | null> {
await this.userRepository.update(id, updates);
return this.findById(id);
}
async validatePassword(user: User, password: string): Promise<boolean> {
return bcrypt.compare(password, user.password_hash);
}
async hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, 10);
}
async authenticate(email: string, password: string): Promise<{ success: boolean; user?: User }> {
const user = await this.findByEmail(email);
if (!user) {
return { success: false };
}
const isValid = await this.validatePassword(user, password);
if (!isValid) {
return { success: false };
}
return { success: true, user };
}
async updateUser(id: string, updates: Partial<User>): Promise<{ success: boolean; user?: User; error?: string }> {
try {
const user = await this.update(id, updates);
if (!user) {
return { success: false, error: 'User not found' };
}
return { success: true, user };
} catch (error) {
return { success: false, error: 'Failed to update user' };
}
}
async verifyEmail(token: string): Promise<{ success: boolean; user?: User; error?: string }> {
try {
const user = await this.userRepository.findOne({ where: { verification_token: token } }) as User | null;
if (!user) {
return { success: false, error: 'Invalid verification token' };
}
if (user.verification_expires && user.verification_expires < new Date()) {
return { success: false, error: 'Verification token expired' };
}
user.verifyEmail();
await this.userRepository.save(user);
return { success: true, user };
} catch (error) {
return { success: false, error: 'Failed to verify email' };
}
}
async requestPasswordReset(email: string): Promise<{ success: boolean; error?: string }> {
try {
const user = await this.findByEmail(email);
if (!user) {
// Don't reveal if email exists or not
return { success: true };
}
const token = user.generateResetToken();
await this.userRepository.save(user);
// In a real implementation, you would send an email here
// await emailService.sendPasswordResetEmail(user.email, token);
return { success: true };
} catch (error) {
return { success: false, error: 'Failed to process password reset request' };
}
}
async resetPassword(token: string, newPassword: string): Promise<{ success: boolean; user?: User; error?: string }> {
try {
const user = await this.userRepository.findOne({ where: { reset_token: token } }) as User | null;
if (!user) {
return { success: false, error: 'Invalid reset token' };
}
if (user.reset_expires && user.reset_expires < new Date()) {
return { success: false, error: 'Reset token expired' };
}
const hashedPassword = await this.hashPassword(newPassword);
user.password_hash = hashedPassword;
user.clearResetToken();
await this.userRepository.save(user);
return { success: true, user };
} catch (error) {
return { success: false, error: 'Failed to reset password' };
}
}
async getUserPackages(userId: string): Promise<any[]> {
try {
const user = await this.userRepository.findOne({
where: { id: userId },
relations: ['packages']
}) as User | null;
return user?.packages || [];
} catch (error) {
return [];
}
}
async getUserStats(userId: string): Promise<any> {
try {
const user = await this.findById(userId);
if (!user) {
return null;
}
return {
packagesPublished: user.stats?.packages_published || 0,
totalDownloads: user.stats?.total_downloads || 0,
followers: user.stats?.followers || 0,
following: user.stats?.following || 0,
packagesMaintained: user.stats?.packages_maintained || 0
};
} catch (error) {
return null;
}
}
async deleteUser(userId: string): Promise<{ success: boolean; error?: string }> {
try {
const user = await this.findById(userId);
if (!user) {
return { success: false, error: 'User not found' };
}
await this.userRepository.remove(user);
return { success: true };
} catch (error) {
return { success: false, error: 'Failed to delete user' };
}
}
}