import crypto from 'node:crypto' import { normalizeEmail } from '../lib/auth.js' import { prisma } from '../lib/prisma.js' import { mapUserForClient } from './auth.js' export async function registerAuthSessionRoutes(fastify) { fastify.get('/api/me', { preHandler: [fastify.authenticate] }, async (request) => { const userId = request.user.sub const user = await prisma.user.findUnique({ where: { id: userId } }) if (!user) return { user: null } return { user: mapUserForClient(user) } }) fastify.get('/api/me/auth-methods', { preHandler: [fastify.authenticate] }, async (request) => { const userId = request.user.sub const user = await prisma.user.findUnique({ where: { id: userId }, include: { oauthAccounts: { select: { provider: true } } }, }) if (!user) return { methods: [] } const providers = user.oauthAccounts.map((a) => a.provider) return { methods: [ { type: 'password', active: Boolean(user.passwordHash) }, { type: 'vk', active: providers.includes('vk') }, { type: 'yandex', active: providers.includes('yandex') }, ], } }) fastify.patch('/api/me/email', { preHandler: [fastify.authenticate] }, async (request, reply) => { const userId = request.user.sub const rawEmail = typeof request.body?.email === 'string' ? request.body.email.trim() : '' if (!rawEmail || !rawEmail.includes('@')) { return reply.code(400).send({ error: 'Некорректная почта' }) } const email = normalizeEmail(rawEmail) const existing = await prisma.user.findUnique({ where: { email } }) if (existing && existing.id !== userId) { return reply.code(409).send({ error: 'Эта почта уже используется' }) } await prisma.pendingEmail.deleteMany({ where: { userId } }) const token = crypto.randomUUID() const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000) await prisma.pendingEmail.create({ data: { userId, email, token, expiresAt }, }) return { verificationUrl: `/api/me/verify-email?token=${token}` } }) fastify.get('/api/me/verify-email', async (request, reply) => { const token = typeof request.query?.token === 'string' ? request.query.token : '' if (!token) { return reply.code(400).send({ error: 'Отсутствует токен подтверждения' }) } const pending = await prisma.pendingEmail.findUnique({ where: { token } }) if (!pending || pending.expiresAt < new Date()) { return reply.code(400).send({ error: 'Токен подтверждения недействителен или истёк' }) } await prisma.user.update({ where: { id: pending.userId }, data: { email: pending.email }, }) await prisma.pendingEmail.delete({ where: { id: pending.id } }) const clientUrl = (process.env.CLIENT_PUBLIC_URL || 'http://127.0.0.1:5173').replace(/\/$/, '') return reply.redirect(`${clientUrl}/me?emailVerified=1`) }) }