feat: синхронизация бэкенда с документацией (AGENT_TASK_BACKEND_SYNC)

- Добвлен @fastify/cookie и настройку httpOnly cookie для refresh token
- Добавлен префикс /api/v1 для auth, profile, tests, admin
- Скорректировано в Login: возвращать user (id, nickname, avatarUrl, role, emailVerified),
  ставить refreshToken в Set-Cookie
- Скорректировано в Logout: Bearer + cookie, пустое тело, 200 + { message }, очищать cookie
- Скорректировано в Refresh: token из cookie, пустое тело, 200 + { accessToken }, Set-Cookie
- Добавлено в getPrivateProfile: поля role и plan
- Скорректировано в Tests: score = количество правильных, ответ { score, totalQuestions, percentage }
- Добавлено в question_cache_meta: поля valid, retryCount, questionsGenerated
- Обновлены тесты
This commit is contained in:
Anton
2026-03-06 13:58:34 +03:00
parent 99a2686532
commit 223feed0e0
21 changed files with 2244 additions and 62 deletions

View File

@@ -1,9 +1,17 @@
import Fastify, { FastifyInstance } from 'fastify';
import cookie from '@fastify/cookie';
import fp from 'fastify-plugin';
import { AppError } from '../../src/utils/errors.js';
import authPlugin from '../../src/plugins/auth.js';
import { authRoutes } from '../../src/routes/auth.js';
import type { MockDb } from '../test-utils.js';
import { createMockDb } from '../test-utils.js';
const mockDatabasePlugin = (db: MockDb) =>
fp(async (app) => {
app.decorate('db', db);
}, { name: 'database' });
/** Mock Redis for login lockout in auth tests. Implements ttl, setex, del, eval. */
const mockRedis = {
async ttl(_key: string): Promise<number> {
@@ -50,7 +58,6 @@ export async function buildAuthTestApp(mockDb?: MockDb): Promise<FastifyInstance
return reply.status(500).send({ error: { code: 'INTERNAL_ERROR', message: error.message } });
});
app.decorate('db', db);
app.decorate('redis', mockRedis);
app.decorate('rateLimitOptions', {
register: { max: 100, timeWindow: '1 hour' },
@@ -60,7 +67,10 @@ export async function buildAuthTestApp(mockDb?: MockDb): Promise<FastifyInstance
apiGuest: { max: 100, timeWindow: '1 minute' },
});
await app.register(authRoutes, { prefix: '/auth' });
await app.register(mockDatabasePlugin(db));
await app.register(cookie, { secret: 'test-secret-at-least-32-characters-long' });
await app.register(authPlugin);
await app.register(authRoutes, { prefix: '/api/v1/auth' });
return app;
}