feat(server): add auth-methods, set-password, unlink-oauth endpoints
This commit is contained in:
@@ -145,6 +145,75 @@ export async function registerAuthRoutes(fastify) {
|
||||
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.post('/api/me/password', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||
const userId = request.user.sub
|
||||
if (isAdminEmail(request.user.email)) {
|
||||
return reply.code(403).send({ error: 'Администратор не может устанавливать пароль' })
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { id: userId } })
|
||||
if (!user) return reply.code(404).send({ error: 'Пользователь не найден' })
|
||||
if (user.passwordHash) return reply.code(409).send({ error: 'Пароль уже установлен' })
|
||||
|
||||
const password = String(request.body?.password || '')
|
||||
const passwordErr = validatePassword(password)
|
||||
if (passwordErr) return reply.code(400).send({ error: passwordErr })
|
||||
|
||||
const passwordHash = await hashPassword(password)
|
||||
await prisma.user.update({ where: { id: userId }, data: { passwordHash } })
|
||||
|
||||
return { ok: true }
|
||||
})
|
||||
|
||||
fastify.delete('/api/me/oauth/:provider', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||
const userId = request.user.sub
|
||||
const provider = request.params?.provider
|
||||
|
||||
if (isAdminEmail(request.user.email)) {
|
||||
return reply.code(403).send({ error: 'Администратор не может отвязывать OAuth' })
|
||||
}
|
||||
if (provider !== 'vk' && provider !== 'yandex') {
|
||||
return reply.code(400).send({ error: 'Неизвестный провайдер' })
|
||||
}
|
||||
|
||||
const oauth = await prisma.oAuthAccount.findFirst({
|
||||
where: { userId, provider },
|
||||
})
|
||||
if (!oauth) return reply.code(404).send({ error: 'Аккаунт не привязан' })
|
||||
|
||||
const remainingOAuth = await prisma.oAuthAccount.count({
|
||||
where: { userId, provider: { not: provider } },
|
||||
})
|
||||
const currentUser = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { passwordHash: true },
|
||||
})
|
||||
if (!currentUser?.passwordHash && remainingOAuth === 0) {
|
||||
return reply.code(400).send({ error: 'Нельзя удалить последний метод входа' })
|
||||
}
|
||||
|
||||
await prisma.oAuthAccount.delete({ where: { id: oauth.id } })
|
||||
return { ok: true }
|
||||
})
|
||||
|
||||
fastify.post('/api/me/change-email/request-code', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||
const userId = request.user.sub
|
||||
const newEmail = normalizeEmail(request.body?.newEmail)
|
||||
|
||||
Reference in New Issue
Block a user