Skip to content
NaMiK0Public

About

🗂️ Async Kanban board API on FastAPI: role-based access control, O(1) drag-and-drop via fractional indexing, non-blocking email notifications, layered architecture and pytest with full transactional isolation.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Flowboard — Micro-Kanban (Trello-clone) API

Асинхронный бэкенд для Kanban-доски продакшен-уровня. Проект демонстрирует реальные задачи бэкенд-разработки: проектирование реляционных связей, контроль доступа (RBAC), потокобезопасное переупорядочивание карточек (drag-and-drop) и неблокирующую фоновую обработку задач.

Технологический стек

Задача Решение
Фреймворк FastAPI (Python 3.12)
База данных PostgreSQL 16
ORM / драйвер SQLAlchemy 2.0 (async) + asyncpg
Миграции Alembic (асинхронный env.py)
Аутентификация JWT: access + refresh токены
Фоновые задачи FastAPI BackgroundTasks + aiosmtplib
Тесты pytest + pytest-asyncio + httpx.AsyncClient
Инфраструктура Docker (multi-stage) + Docker Compose

Архитектура (Clean Architecture / DDD-lite)

app/
├── api/            Презентационный слой (роутеры, DTO-схемы, зависимости)
│   ├── v1/         auth.py · boards.py · cards.py
│   └── schemas/    Pydantic V2 модели запросов/ответов
├── core/           config · security (JWT/хеши) · tasks (email) · exceptions
├── database/       async движок/сессия · декларативный Base
├── models/         ORM-модели SQLAlchemy 2.0
├── repositories/   Паттерн Репозиторий (доступ к данным)
├── services/       Бизнес-логика, RBAC, drag-and-drop
└── main.py         Точка входа + lifespan

Направление зависимостей: api -> services -> repositories -> models. Сервисы бросают доменные исключения (app/core/exceptions.py), а единый обработчик в main.py превращает их в HTTP-ответы. Благодаря этому бизнес-логика не зависит от FastAPI.

Модель предметной области

  • User — владеет множеством досок (1-N); назначается на множество карточек (M-N через таблицу card_assignees).
  • Board — публичная/приватная; содержит колонки (1-N) и участников с ролями (таблица board_members).
  • Column — упорядоченные карточки (1-N).
  • Card — дробная позиция position; содержит комментарии (1-N) и исполнителей.
  • Comment — комментарий пользователя к карточке.

RBAC (контроль доступа)

Роли: viewer < editor < admin. Владелец доски — неявный admin. На публичной доске любой аутентифицированный пользователь получает неявный viewer.

  • Просмотр доски/карточек, комментирование -> viewer
  • Создание/перенос/редактирование/удаление карточек, создание колонок -> editor
  • Управление участниками, редактирование доски -> admin
  • Удаление доски -> только владелец

Drag-and-drop (дробная индексация)

Карточки хранят позицию с плавающей точкой position. При переносе карточки между двумя соседями вычисляется середина (prev + next) / 2, поэтому переупорядочивание — это обновление одной строки (O(1)) вместо перенумерации всей колонки. Когда повторные вставки в середину исчерпывают точность float, колонка назначения прозрачно перераспределяется (CardService._rebalance).

Эндпоинт POST /api/v1/cards/{card_id}/move принимает { "column_id", "target_position" } (target_position опционален -> карточка добавляется в конец колонки).

Асинхронные уведомления

Когда пользователя впервые назначают на карточку, BackgroundTasks ставит в очередь отправку письма через aiosmtplib уже после возврата HTTP-ответа — клиент не ждёт SMTP. В Docker Compose почту перехватывает MailHog (веб-интерфейс на :8025).

Запуск

Docker (всё одной командой)

cp .env.example .env       # при необходимости поменяйте секреты
docker compose up --build

Сервисы: API :8000 (документация на /docs), Postgres :5432, Redis :6379, PgAdmin :5050, MailHog :8025. Контейнер API при старте выполняет alembic upgrade head.

Локальная разработка

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Укажите POSTGRES_HOST=localhost в .env, затем:
alembic upgrade head
uvicorn app.main:app --reload

Тесты

pytest

Тесты выполняются на in-memory SQLite. Каждый тест работает внутри внешней транзакции с join_transaction_mode="create_savepoint": даже вызовы session.commit() внутри сервисов превращаются в release точки сохранения (SAVEPOINT), а вся транзакция откатывается на teardown — полная изоляция, без утечек данных между тестами (tests/conftest.py).

Основные эндпоинты

POST   /api/v1/auth/register
POST   /api/v1/auth/login            (OAuth2 form: username = email)
POST   /api/v1/auth/refresh
GET    /api/v1/auth/me

GET    /api/v1/boards
POST   /api/v1/boards                (создаёт колонки To Do / In Progress / Done)
GET    /api/v1/boards/{id}
PATCH  /api/v1/boards/{id}
DELETE /api/v1/boards/{id}
POST   /api/v1/boards/{id}/members
DELETE /api/v1/boards/{id}/members/{user_id}
POST   /api/v1/boards/{id}/columns

POST   /api/v1/cards
GET    /api/v1/cards/{id}
PATCH  /api/v1/cards/{id}            (изменение исполнителей запускает письмо)
POST   /api/v1/cards/{id}/move       (drag-and-drop)
DELETE /api/v1/cards/{id}
POST   /api/v1/cards/{id}/comments

About

🗂️ Async Kanban board API on FastAPI: role-based access control, O(1) drag-and-drop via fractional indexing, non-blocking email notifications, layered architecture and pytest with full transactional isolation.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages