initial: server + shared
This commit is contained in:
+95
@@ -0,0 +1,95 @@
|
||||
import jwt from '@fastify/jwt'
|
||||
import Fastify from 'fastify'
|
||||
import { afterAll, beforeEach, beforeAll, describe, expect, it } from 'vitest'
|
||||
import { prisma } from '../../lib/prisma.js'
|
||||
import { registerAuthOAuthRoutes } from '../auth-oauth.js'
|
||||
|
||||
const JWT_SECRET = 'test-secret'
|
||||
|
||||
async function buildApp() {
|
||||
const app = Fastify({ logger: false })
|
||||
await app.register(jwt, { secret: JWT_SECRET })
|
||||
app.decorate('authenticate', async function (request, reply) {
|
||||
try {
|
||||
await request.jwtVerify()
|
||||
} catch {
|
||||
return reply.code(401).send({ error: 'Unauthorized' })
|
||||
}
|
||||
})
|
||||
app.decorate('eventBus', { emit: () => {} })
|
||||
await registerAuthOAuthRoutes(app)
|
||||
await app.ready()
|
||||
return app
|
||||
}
|
||||
|
||||
function signToken(app, userId, email) {
|
||||
return app.jwt.sign({ sub: userId, email })
|
||||
}
|
||||
|
||||
async function createUser(email) {
|
||||
const user = await prisma.user.create({
|
||||
data: { email, displayName: 'Test', avatar: null, avatarStyle: 'avataaars' },
|
||||
})
|
||||
await prisma.notificationPreference.create({ data: { userId: user.id, globalEnabled: true } })
|
||||
return user
|
||||
}
|
||||
|
||||
describe('DELETE /api/me/oauth/:provider', () => {
|
||||
let app, user, token
|
||||
const email = `test-unlink-${Date.now()}@example.com`
|
||||
|
||||
beforeAll(async () => {
|
||||
app = await buildApp()
|
||||
})
|
||||
afterAll(async () => {
|
||||
await prisma.oAuthAccount.deleteMany({ where: { user: { email } } })
|
||||
await prisma.notificationPreference.deleteMany({ where: { user: { email } } })
|
||||
await prisma.user.deleteMany({ where: { email } })
|
||||
await app.close()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await prisma.oAuthAccount.deleteMany({ where: { user: { email } } })
|
||||
await prisma.user.deleteMany({ where: { email } })
|
||||
user = await createUser(email)
|
||||
token = signToken(app, user.id, email)
|
||||
})
|
||||
|
||||
it('returns 404 for non-linked provider', async () => {
|
||||
const res = await app.inject({
|
||||
method: 'DELETE',
|
||||
url: '/api/me/oauth/vk',
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
})
|
||||
expect(res.statusCode).toBe(404)
|
||||
})
|
||||
|
||||
it('unlinks a provider', async () => {
|
||||
await prisma.user.update({ where: { id: user.id }, data: { passwordHash: 'hashed' } })
|
||||
await prisma.oAuthAccount.create({
|
||||
data: { provider: 'vk', providerUserId: '123', userId: user.id },
|
||||
})
|
||||
const res = await app.inject({
|
||||
method: 'DELETE',
|
||||
url: '/api/me/oauth/vk',
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
})
|
||||
expect(res.statusCode).toBe(200)
|
||||
|
||||
const count = await prisma.oAuthAccount.count({ where: { userId: user.id } })
|
||||
expect(count).toBe(0)
|
||||
})
|
||||
|
||||
it('rejects removing last method without password', async () => {
|
||||
await prisma.oAuthAccount.create({
|
||||
data: { provider: 'vk', providerUserId: '123', userId: user.id },
|
||||
})
|
||||
const res = await app.inject({
|
||||
method: 'DELETE',
|
||||
url: '/api/me/oauth/vk',
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
})
|
||||
expect(res.statusCode).toBe(400)
|
||||
expect(JSON.parse(res.body).error).toContain('последний метод')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user