пва
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import crypto from 'node:crypto'
|
||||
import { normalizeEmail } from '../lib/auth.js'
|
||||
import { prisma } from '../lib/prisma.js'
|
||||
import { mapUserForClient } from './auth.js'
|
||||
|
||||
@@ -26,4 +28,54 @@ export async function registerAuthSessionRoutes(fastify) {
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
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`)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ async function findOrCreateUserFromOAuth({ provider, providerUserId, accessToken
|
||||
const norm = trimmed ? normalizeEmail(trimmed) : null
|
||||
|
||||
if (linkToUserId) {
|
||||
if (!norm) return null
|
||||
await prisma.oAuthAccount.create({
|
||||
data: { provider, providerUserId: String(providerUserId), userId: linkToUserId, accessToken },
|
||||
})
|
||||
@@ -84,13 +83,13 @@ async function findOrCreateUserFromOAuth({ provider, providerUserId, accessToken
|
||||
return user
|
||||
}
|
||||
|
||||
if (!norm) return null
|
||||
const email = norm || `${provider}_${providerUserId}@vk.local`
|
||||
|
||||
user = await prisma.user.create({
|
||||
data: {
|
||||
email: norm,
|
||||
displayName: norm.split('@')[0],
|
||||
avatar: await generateAvatar(norm),
|
||||
email,
|
||||
displayName: norm ? norm.split('@')[0] : 'Пользователь',
|
||||
avatar: await generateAvatar(email),
|
||||
avatarStyle: 'avataaars',
|
||||
},
|
||||
})
|
||||
@@ -206,7 +205,6 @@ export async function registerOAuthSocialRoutes(fastify) {
|
||||
const emailSuggestion = claims?.email ?? tokenBody?.email ?? null
|
||||
|
||||
if (!vkUserId) return oauthErrorRedirect(reply, 'no_user_id')
|
||||
if (!emailSuggestion) return oauthErrorRedirect(reply, 'no_email')
|
||||
|
||||
const linkToUserId = pkceEntry.meta?.action === 'link' ? pkceEntry.meta.userId : undefined
|
||||
|
||||
@@ -218,8 +216,6 @@ export async function registerOAuthSocialRoutes(fastify) {
|
||||
linkToUserId,
|
||||
})
|
||||
|
||||
if (!user) return oauthErrorRedirect(reply, 'Не удалось получить email от VK')
|
||||
|
||||
if (linkToUserId) {
|
||||
const base = process.env.CLIENT_PUBLIC_URL || 'http://127.0.0.1:5173'
|
||||
return reply.redirect(`${base.replace(/\/$/, '')}/me?linked=vk`)
|
||||
|
||||
Reference in New Issue
Block a user