import { storage } from '../storage'; import { hashPassword, verifyPassword } from '../utils/password'; import { generateSuperAdminToken, generateResetToken } from '../utils/jwt'; import { emailService } from './email.service'; export interface SuperAdminLoginResult { success: boolean; token?: string; superAdmin?: { id: number; email: string; name: string }; error?: string; } interface ResetTokenEntry { superAdminId: number; expiresAt: number; } const resetTokenStore = new Map(); const RESET_TOKEN_TTL_MS = 60 * 60 * 1000; export class SuperAdminService { async login(email: string, password: string): Promise { try { const superAdmin = await storage.getSuperAdminByEmail(email); if (!superAdmin) { return { success: false, error: 'Неверный email или пароль' }; } const isValid = await verifyPassword(password, superAdmin.passwordHash); if (!isValid) { return { success: false, error: 'Неверный email или пароль' }; } await storage.updateSuperAdminLastLogin(superAdmin.id); const token = generateSuperAdminToken({ superAdminId: superAdmin.id, email: superAdmin.email, isSuperAdmin: true, }); return { success: true, token, superAdmin: { id: superAdmin.id, email: superAdmin.email, name: superAdmin.name }, }; } catch (error) { console.error('SuperAdmin login error:', error); return { success: false, error: 'Ошибка при входе' }; } } async seedFirstSuperAdmin(email: string, password: string, name: string): Promise<{ success: boolean; error?: string }> { try { const count = await storage.getSuperAdminCount(); if (count > 0) { return { success: false, error: 'Суперадмин уже существует' }; } const passwordHash = await hashPassword(password); await storage.createSuperAdmin({ email, passwordHash, name }); return { success: true }; } catch (error) { console.error('SuperAdmin seed error:', error); return { success: false, error: 'Ошибка при создании суперадмина' }; } } async createAdditionalSuperAdmin(email: string, password: string, name: string): Promise<{ success: boolean; superAdmin?: { id: number; email: string; name: string }; error?: string }> { try { const existing = await storage.getSuperAdminByEmail(email); if (existing) { return { success: false, error: 'Суперадмин с таким email уже существует' }; } const passwordHash = await hashPassword(password); const created = await storage.createSuperAdmin({ email, passwordHash, name }); return { success: true, superAdmin: { id: created.id, email: created.email, name: created.name } }; } catch (error) { console.error('SuperAdmin create error:', error); return { success: false, error: 'Ошибка при создании суперадмина' }; } } async deleteSuperAdmin(idToDelete: number, currentAdminId: number): Promise<{ success: boolean; error?: string }> { try { if (idToDelete === currentAdminId) { return { success: false, error: 'Нельзя удалить собственный аккаунт' }; } const target = await storage.getSuperAdminById(idToDelete); if (!target) { return { success: false, error: 'Суперадмин не найден' }; } const count = await storage.getSuperAdminCount(); if (count <= 1) { return { success: false, error: 'Нельзя удалить последнего суперадмина' }; } await storage.deleteSuperAdmin(idToDelete); return { success: true }; } catch (error) { console.error('SuperAdmin delete error:', error); return { success: false, error: 'Ошибка при удалении суперадмина' }; } } async requestPasswordReset(email: string): Promise<{ success: boolean; error?: string }> { try { const superAdmin = await storage.getSuperAdminByEmail(email); if (!superAdmin) { return { success: true }; } const token = generateResetToken(); resetTokenStore.set(token, { superAdminId: superAdmin.id, expiresAt: Date.now() + RESET_TOKEN_TTL_MS, }); const sent = await emailService.sendSuperAdminPasswordResetEmail( superAdmin.email, superAdmin.name, token ); if (!sent) { resetTokenStore.delete(token); console.error(`SuperAdmin password reset: email delivery failed for ${superAdmin.email}`); return { success: false, error: 'Не удалось отправить письмо. Попробуйте позже.' }; } return { success: true }; } catch (error) { console.error('SuperAdmin requestPasswordReset error:', error); return { success: false, error: 'Ошибка при отправке письма' }; } } async confirmPasswordReset(token: string, newPassword: string): Promise<{ success: boolean; error?: string }> { try { const entry = resetTokenStore.get(token); if (!entry) { return { success: false, error: 'Неверная или устаревшая ссылка для сброса пароля' }; } if (Date.now() > entry.expiresAt) { resetTokenStore.delete(token); return { success: false, error: 'Срок действия ссылки истёк. Запросите новую.' }; } const passwordHash = await hashPassword(newPassword); await storage.updateSuperAdminPassword(entry.superAdminId, passwordHash); resetTokenStore.delete(token); return { success: true }; } catch (error: any) { console.error('SuperAdmin confirmPasswordReset error:', error); const msg = error?.message?.includes('Пароль') ? error.message : 'Ошибка при смене пароля'; return { success: false, error: msg }; } } } export const superAdminService = new SuperAdminService();