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) }
|
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) => {
|
fastify.post('/api/me/change-email/request-code', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
const userId = request.user.sub
|
const userId = request.user.sub
|
||||||
const newEmail = normalizeEmail(request.body?.newEmail)
|
const newEmail = normalizeEmail(request.body?.newEmail)
|
||||||
|
|||||||
Reference in New Issue
Block a user