Skip to content

RBAC Этап 4: Миграция роутеров на require_permission #326

@ShaerWare

Description

@ShaerWare

Часть #322 (реализация RBAC). Зависит от: #325 (роли в БД). Следующий: Этап 5, Этап 6.

Цель

Заменить require_admin / require_not_guest / get_current_user + inline role checks на единый require_permission(module, level) во всех 21 роутерах (~332 эндпоинта).

Правила замены

Текущее Целевое Пример
Depends(require_admin) Depends(require_permission('module', 'manage')) backup, gsm, claude_code
Depends(require_not_guest) Depends(require_permission('module', 'edit')) faq create, wiki upload
Depends(get_current_user) (read) Depends(require_permission('module', 'view')) chat list, audit view
user.role == "admin" (owner bypass) user_level(user, 'module') >= 'manage' chat delete чужих, provider manage

Чеклист

Инфраструктура

  • auth_manager.py: require_permission(module: str, min_level: str) — FastAPI Depends factory
    • Возвращает User с добавленным permissions: Dict[str, str]
    • Проверяет: role → role_permissions → module exists → level >= min_level
    • 403 если нет доступа
  • auth_manager.py: кеширование permissions per user (in-memory, invalidate при revoke)
  • Удалить require_admin(), require_not_guest(), verify_ownership() после миграции всех роутеров

PR 4a — Модуль chat (21 эндпоинт)

  • app/routers/chat.py: все get_current_userrequire_permission('chat', 'view'|'edit')
  • _check_session_owner_or_admin() → проверка manage level вместо role == "admin"
  • _check_write_access() → проверка edit level + ownership
  • Тест: viewer видит свои сессии, не может создать; operator создаёт/редактирует свои; manage видит всё

PR 4b — Модуль llm (42 эндпоинта)

  • app/routers/llm.py: read → view, write → edit, vllm/proxy/presets → manage
  • Cloud providers: owner_id фильтрация для view/edit, bypass для manage
  • Тест: operator управляет своими провайдерами, manage — всеми

PR 4c — Модуль channels (45 эндпоинтов)

  • app/routers/telegram.py: read → view, write → edit, config → manage
  • app/routers/whatsapp.py: аналогично
  • app/routers/widget.py: аналогично
  • Тест: operator управляет своими ботами/виджетами

PR 4d — Модуль sales (70 эндпоинтов)

  • app/routers/bot_sales.py: read → view, write → edit
  • app/routers/amocrm.py: read → view, write → edit, OAuth/dataset → manage
  • Тест: viewer видит данные, operator редактирует

PR 4e — Модули faq + wiki (22 эндпоинта)

  • app/routers/faq.py: list/get → faq:view, create/update/delete → faq:edit
  • app/routers/wiki_rag.py: stats/search → wiki:view, upload/delete → wiki:edit, reindex → wiki:manage
  • Тест: viewer ищет, operator загружает документы

PR 4f — Модули system + speech (56 эндпоинтов)

  • app/routers/services.py: view → system:view, start/stop → system:manage
  • app/routers/monitor.py: all → system:view
  • app/routers/backup.py: all → system:manage
  • app/routers/gsm.py: all → gsm:manage
  • app/routers/tts.py: view/test → speech:view, presets → speech:edit
  • app/routers/stt.py: all → speech:view
  • Тест: operator видит мониторинг, manage делает бэкапы

PR 4g — Остальные модули (46 эндпоинтов)

  • app/routers/kanban.py: view → kanban:view, create/update → kanban:edit, delete → kanban:manage
  • app/routers/audit.py: all → audit:view, cleanup → audit:manage
  • app/routers/usage.py: view → usage:view, limits → usage:manage
  • app/routers/claude_code.py: all → claude_code:manage
  • app/routers/legal.py: public endpoints без изменений; admin → settings:manage
  • app/routers/auth.py: profile → любой аутентифицированный; users CRUD → users:manage
  • Тест: все эндпоинты отвечают корректно для каждого уровня

Финализация

  • Удалить require_admin, require_not_guest, verify_ownership из auth_manager.py
  • Grep по кодовой базе: нет упоминаний require_admin, require_not_guest, role == "admin", role != "guest"
  • ruff check . — lint проходит

Проверки (для каждого PR)

# Все эндпоинты мигрированного модуля отвечают
curl -s http://localhost:8002/admin/chat/sessions -H "Authorization: Bearer $ADMIN_TOKEN" | jq 'length'
curl -s http://localhost:8002/admin/chat/sessions -H "Authorization: Bearer $OPERATOR_TOKEN" | jq 'length'

# Уровень доступа: operator (edit) может создать
curl -s -X POST http://localhost:8002/admin/chat/sessions \
  -H "Authorization: Bearer $OPERATOR_TOKEN" \
  -H 'Content-Type: application/json' -d '{}'  # → 200

# Уровень доступа: viewer (view) не может создать
curl -s -X POST http://localhost:8002/admin/chat/sessions \
  -H "Authorization: Bearer $VIEWER_TOKEN" \
  -H 'Content-Type: application/json' -d '{}'  # → 403

# Без модуля → 403
# (пользователь с ролью без модуля chat)

# owner_id фильтрация: operator видит только свои, manage видит все

# Lint
ruff check app/routers/

# Health check
curl -s http://localhost:8002/health | jq .status

Файлы

  • auth_manager.pyrequire_permission(), удаление старых функций
  • app/routers/*.py — все 21 файл роутеров

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerabilities and hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions