Files
blog.pyaqa.ru/pyproject.toml
Sergey Vanyushkin 184b95969c
Some checks failed
ci/woodpecker/pr/lint Pipeline failed
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/type Pipeline was successful
feat(auth): implement Keycloak authentication with RBAC and pagination
Major changes:
- Add Keycloak integration via token introspection endpoint
- Implement RBAC system with roles: admin, user, guest
- Add role-based permissions for post operations
- Add pagination support (default limit: 10) to list endpoints
- Add published_only filter with admin-only override for unpublished posts

Security improvements:
- Remove hardcoded default secrets (SECRET_KEY, KEYCLOAK_CLIENT_SECRET)
- Update .env.example with proper security placeholders
- Add comprehensive RBAC unit tests

Infrastructure:
- Add httpx dependency for HTTP client
- Add KeycloakAuthClient with token caching (TTL: 60s)
- Add role-based dependencies (RequireAdmin, RequireUser, etc.)
- Update DI container with Keycloak provider

Endpoints updated:
- GET /posts: filter by published status (admin can see all)
- Add pagination params (limit, offset) to list endpoints
- Enforce RBAC on post operations

Tests:
- Add 16 auth infrastructure tests
- Add 13 RBAC role tests
- Update existing tests for new required settings

Breaking changes:
- SECRET_KEY and KEYCLOAK_CLIENT_SECRET now required (no defaults)
2026-05-02 11:21:45 +03:00

69 lines
1.2 KiB
TOML

[project]
name = "blog"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"fastapi>=0.136.0",
"pydantic>=2.13.2",
"pydantic-settings>=2.14.0",
"uvicorn>=0.44.0",
"sqlalchemy>=2.0.0",
"aiosqlite>=0.21.0",
"asyncpg>=0.30.0",
"dishka>=1.5.0",
"httpx>=0.28.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["app"]
[dependency-groups]
dev = [
{include-group = "lints"},
{include-group = "tests"},
{include-group = "types"},
"pre-commit>=4.5.1",
]
tests = [
"httpx>=0.28.1",
"mimesis>=19.1.0",
"pytest>=9.0.3",
"pytest-asyncio>=1.3.0",
"pytest-cov>=7.1.0",
]
lints = [
"black>=23.7.0",
"ruff>=0.15.11",
"isort>=8.0.1",
]
types = [
"mimesis>=19.1.0",
"mypy>=1.20.1",
]
[project.scripts]
blog = "app.main:main"
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
addopts = "--cov=app --cov-report=term-missing --cov-report=html"
pythonpath = "."
testpaths = "tests"
xfail_strict = true
[tool.mypy]
strict = true
plugins = ["pydantic.mypy"]
[tool.isort]
profile = "black"
filter_files = true