jze9 c1bfb5f40e fix(api): security, caching, atomic rate limits, url obfuscation
Redis:
- Singleton ConnectionPool (redis.asyncio), 50 connections — не создаём
  новое TCP-соединение на каждый HTTP-запрос

Rate limiter:
- Полностью переписан на async/await
- Lua-скрипт _LUA_CHECK_AND_INCR — атомарная проверка+инкремент без race condition
- Lua-скрипт _LUA_ACQUIRE_CONCURRENT — атомарный захват слота задачи
- Старый паттерн INCR→check→DECR удалён (race condition при конкурентных запросах)

Security:
- get_current_user кэширует пользователя в Redis на 5 минут (TTL)
  Раньше: SELECT users на каждый HTTP-запрос
  Теперь: Redis GET (кэш) → SELECT users (только при промахе)
- hashed_password НЕ кладётся в кэш
- invalidate_user_cache() для сброса при смене тарифа/пароля
- get_ws_user() для WebSocket через ?token=JWT (браузеры не могут
  передавать Authorization header при WS-handshake)

WebSocket:
- Добавлена аутентификация (Depends(get_ws_user))
- Проверка ownership задачи ДО accept() соединения
- Чужой task_id → закрытие с кодом 4004

URL obfuscation:
- Task.public_id = secrets.token_urlsafe(16) = 22 случайных base64url символа
- Клиент работает только с public_id, внутренний UUID не раскрывается
- Все роутеры переключены на public_id в WHERE условиях
- TaskResponse больше не возвращает input_data (там minio_key и т.д.)
- Миграция 002_add_task_public_id.py

MinIO:
- Singleton клиент (не создаём новый на каждый upload)
- ensure_bucket() вызывается один раз при старте (lifespan), не на каждый запрос
- Путь uploads/{doc_uuid}{ext} — user_id убран из пути

CORS:
- Убраны wildcard allow_methods/allow_headers (несовместимы с credentials=True)
- Явный список: methods=[GET,POST,DELETE,OPTIONS], headers=[Authorization,Content-Type,Accept]
- Swagger/OpenAPI доступны только в ENVIRONMENT=development

Documents:
- Content-Length проверяется ДО чтения тела (ранняя отбивка больших файлов)
- Повторная проверка реального размера после чтения (защита от поддельного заголовка)
- Используем get_current_verified_user вместо get_current_user (требуем подтверждённый email)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 19:51:51 +05:00

Академический помощник

Микросервисная система антиплагиата и поиска академических источников.

Студент вводит тему → система ищет источники → проверяет плагиат → форматирует ГОСТ-библиографию. Всё асинхронно: студент закрыл браузер, получил email когда готово.

Архитектура

                    ┌─────────────────┐
                    │   Frontend       │  React + Vite + TypeScript
                    │  (React SPA)     │
                    └────────┬────────┘
                             │ HTTPS
                    ┌────────▼────────┐
                    │   API Gateway    │  FastAPI, порт 8000
                    │  (FastAPI)       │  JWT, Rate Limit, WebSocket
                    └──┬─────────┬───┘
                       │ RabbitMQ│ Celery задачи
          ┌────────────▼──┐  ┌──▼──────────────┐
          │  worker-gpu    │  │ worker-indexer   │
          │  (CUDA/FAISS)  │  │ (PDF/DOCX parse) │
          │  Sem. search   │  │ Winnowing/MinHash │
          │  LLM paraphrase│  └──────────────────┘
          └────────────────┘
                    │
          ┌─────────▼──────────┐  ┌────────────────────┐
          │  worker-notifier    │  │  worker-gost        │
          │  (SMTP email)       │  │  (ГОСТ 7.1/7.0.5)  │
          └────────────────────┘  └────────────────────┘

Инфраструктура:
  PostgreSQL 16 · Redis 7 · RabbitMQ 3 · Elasticsearch 8
  MinIO (4TB) · Ollama (llama3:8b) · NVIDIA RTX 2060

Быстрый старт

# 1. Клонировать репозиторий
git clone https://github.com/jze9/anti-plagiarism.git
cd anti-plagiarism

# 2. Создать файл конфигурации
cp .env.example .env
# Отредактировать .env — сменить пароли и ключи!

# 3. Запустить в режиме разработки
make dev

# 4. Применить миграции базы данных
make migrate-dev

# 5. Создать ES индекс
make es-init

# 6. Открыть браузер
# Frontend: http://localhost:5173
# API docs: http://localhost:8000/api/docs
# RabbitMQ: http://localhost:15672 (guest/guest)
# Flower:   http://localhost:5555
# MinIO:    http://localhost:9001

Команды

make dev          # Запуск в dev режиме (hot reload)
make build        # Сборка Docker образов
make up           # Запуск в продакшн режиме
make down         # Остановить все сервисы
make migrate      # Применить Alembic миграции
make logs         # Логи всех сервисов
make shell-api    # Shell в контейнере API
make shell-gpu    # Shell в контейнере GPU воркера
make lint         # Запустить линтер
make test         # Запустить тесты
make clean        # Удалить контейнеры и volumes

Стек технологий

Компонент Технологии
API Gateway FastAPI 0.111, Python 3.11, SQLAlchemy 2.0, Alembic
GPU Worker sentence-transformers, FAISS-GPU (IVFFlat), Ollama (llama3:8b)
Indexer PyMuPDF, python-docx, Winnowing, MinHash LSH
Очереди RabbitMQ (брокер) + Celery 5 (воркеры) + Redis (результаты)
База данных PostgreSQL 16
Поиск Elasticsearch 8 (BM25) + FAISS GPU (cosine)
Хранилище MinIO (S3-совместимый)
Frontend React 18, Vite, TypeScript, TailwindCSS, Zustand, React Query v5

Проверка плагиата (4 уровня)

  1. Winnowing + MinHash (~мс) — точное совпадение по fingerprints
  2. n-граммы + Jaccard (~сек) — нечёткое совпадение
  3. FAISS GPU cosine (~мс) — семантическое сходство (порог 0.75)
  4. Ollama Llama3 (~2сек) — LLM анализ парафраза (confidence > 0.7)

Тарифные планы

Тариф Цена Поиск/день Изложений/мес Плагиат/мес Одновременно
Бесплатный 0₽ 10 3 1 1
Студенческий 199₽ безлимит 30 10 2
Премиум 499₽ безлимит безлимит 50 5
Научный 999₽ безлимит безлимит безлимит 10

Парсеры источников

# Запарсить OpenAlex
python scripts/run_parser.py openalex \
    --query "машинное обучение" \
    --limit 10000 \
    --output /data/processed

# КиберЛенинка
python scripts/run_parser.py cyberleninka \
    --query "нейронные сети" \
    --limit 1000

# arXiv
python scripts/run_parser.py arxiv \
    --query "deep learning" \
    --categories cs.AI cs.LG \
    --limit 5000

Переменные окружения

Смотри .env.example для полного списка переменных. Обязательно смените SECRET_KEY, POSTGRES_PASSWORD, MINIO_SECRET_KEY.

Продакшн деплой

# На сервере
cp .env.example .env
nano .env  # Настроить все пароли и ключи

make build
make up
make migrate

# SSL сертификат (Let's Encrypt)
certbot --nginx -d academic.jze9.ru

Лицензия

MIT

Description
No description provided
Readme 382 KiB
Languages
Python 63.4%
TypeScript 32.7%
Makefile 1.5%
Shell 1.3%
Dockerfile 0.7%
Other 0.3%