csrd-utils 0.3.93__tar.gz → 0.3.96__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/PKG-INFO +1 -1
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/pyproject.toml +1 -1
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/augments.py +9 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/renderer.py +12 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/scaffolder.py +14 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/service_renderers.py +20 -4
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/delegates/auth_delegate.py +35 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/dependencies/auth_passthrough.py +21 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/models/auth_passthrough.py +32 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/views/auth_passthrough_view.py +25 -0
- csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/db-config/dependencies/db.py → csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/db-config/dependencies/db.py.template +10 -4
- csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/jwt-auth-consumer/dependencies/auth.py → csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-consumer/dependencies/auth.py.template +5 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/dependencies/db.py.template +46 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/models/auth.py +39 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/models/jwks.py +11 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/models/users.py +26 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/augments/jwt-auth-provider/repositories/user_repository.py +42 -34
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/augments/jwt-auth-provider/views/auth_view.py +24 -62
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/augments/jwt-auth-provider/views/jwks_view.py +3 -12
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/views/users_view.py +44 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +27 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/models/__init__.py +1 -0
- csrd_utils-0.3.96/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/models/health.py +10 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/requirements.txt +1 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/settings.py +1 -2
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/views/health_view.py +2 -7
- csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/jwt-auth-provider/dependencies/db.py +0 -31
- csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/jwt-auth-provider/views/users_view.py +0 -101
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/.gitignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/__main__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/audit.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/augmentor.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/cluster.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/doctor.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/conftest.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/manifest.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/requirements.fragment +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/settings.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/src/app/cache.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/caching/tests/test_cache.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/conftest.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/manifest.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/requirements.fragment +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/settings.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/src/app/middleware/logging.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/logging/tests/test_logging_middleware.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/conftest.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/manifest.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/requirements.fragment +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/settings.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/src/app/middleware/metrics.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/metrics/tests/test_metrics_middleware.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/conftest.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/manifest.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/requirements.fragment +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/settings.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/src/app/middleware/tracing.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/tracing/tests/test_tracing_middleware.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/conftest.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/manifest.yaml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/requirements.fragment +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/settings.fragment.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/src/app/workers/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/src/app/workers/celery_app.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/src/app/workers/tasks.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/features/workers/tests/test_workers.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/fragments.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/generator.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/resources.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/cookiecutter.json +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/hooks/post_gen_project.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.cookiecutterignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/cache.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/upstreams.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/auth_service.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/delegates.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/item_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/worker_broker.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/docker-compose.yml +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/logging.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/item_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/test_logging_middleware.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/test_items.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_cache.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_database_settings.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_delegates.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_settings_contracts.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_worker_broker.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/items_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/tasks.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/cookiecutter.json +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/delegates/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/delegates/auth_delegate.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/delegates/identity_delegate.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/dependencies/auth_passthrough.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/dependencies/auth_service.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/dependencies/item_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/models/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/models/auth_service.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/models/items.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/repositories/item_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/views/unversioned/auth_service_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-app-service/{{cookiecutter.__service_name_snake}}/views/unversioned/items_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/cookiecutter.json +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/models/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/models/auth.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/repositories/token_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/auth_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/cookiecutter.json +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/models/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/models/users.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/repositories/user_repository.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/users_view.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/AGENTS.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/git.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/infra.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/loader.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/operations.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/presets.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/compose/yaml_editor.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/generate/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/generate/handlers.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/generate/helpers.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/generate/menu.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/models/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/models/base.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/models/spec.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/models/types.py +0 -0
- /csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/db-config/migrations.py → /csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/db-config/migrations.py.template +0 -0
- /csrd_utils-0.3.93/src/csrd_utils/v2/templates/augments/jwt-auth-provider/migrations.py → /csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/migrations.py.template +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/cookiecutter.json +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/tests/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/tests/test_health.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/csrd_utils/v2/templates/service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/__init__.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/exceptions.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/menu.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/models.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/prompts.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/terminal.py +0 -0
- {csrd_utils-0.3.93 → csrd_utils-0.3.96}/src/tui_wizard/wizard.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csrd-utils
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.96
|
|
4
4
|
Summary: CLI utilities for csrd service generation and feature augmentation
|
|
5
5
|
Project-URL: Repository, https://github.com/csrd-api/fastapi-common
|
|
6
6
|
Project-URL: Documentation, https://github.com/csrd-api/fastapi-common/tree/main/packages/utils
|
|
@@ -131,6 +131,15 @@ AUGMENT_REGISTRY: dict[str, AugmentDescriptor] = {
|
|
|
131
131
|
template_dir="jwt-auth-consumer",
|
|
132
132
|
# compose_env, compose_depends_on, settings_fields resolved from spec
|
|
133
133
|
),
|
|
134
|
+
"auth-passthrough": AugmentDescriptor(
|
|
135
|
+
name="auth-passthrough",
|
|
136
|
+
scope="service",
|
|
137
|
+
description="Unguarded signup/login proxy endpoints to the auth service",
|
|
138
|
+
requires_workspace_augment="jwt-auth-provider",
|
|
139
|
+
packages=["csrd-delegate", "csrd-models"],
|
|
140
|
+
template_dir="auth-passthrough",
|
|
141
|
+
# compose_env, compose_depends_on, settings_fields resolved from spec
|
|
142
|
+
),
|
|
134
143
|
"context-logging": AugmentDescriptor(
|
|
135
144
|
name="context-logging",
|
|
136
145
|
scope="service",
|
|
@@ -103,6 +103,18 @@ def _wire_augment(
|
|
|
103
103
|
env["AUTH_JWKS_URL"] = f"http://{auth_svc.name}:{auth_svc.port}/.well-known/jwks.json"
|
|
104
104
|
deps[auth_svc.name] = {"condition": "service_started"}
|
|
105
105
|
|
|
106
|
+
# ── Dynamic: auth-passthrough ────────────────────────────────────
|
|
107
|
+
#
|
|
108
|
+
# Resolve the auth service URL for signup/login proxy endpoints.
|
|
109
|
+
if augment.name == "auth-passthrough":
|
|
110
|
+
auth_svc = next(
|
|
111
|
+
(s for s in spec.services if s.role == "auth"),
|
|
112
|
+
None,
|
|
113
|
+
)
|
|
114
|
+
if auth_svc is not None and auth_svc.name != svc.name:
|
|
115
|
+
env["AUTH_SERVICE_URL"] = f"http://{auth_svc.name}:{auth_svc.port}"
|
|
116
|
+
deps[auth_svc.name] = {"condition": "service_started"}
|
|
117
|
+
|
|
106
118
|
# ── Dynamic: delegate-config ────────────────────────────────────
|
|
107
119
|
#
|
|
108
120
|
# Resolve target service URLs from the spec and inject per-target
|
|
@@ -189,6 +189,16 @@ def _augment_template_vars(
|
|
|
189
189
|
variables["auth_service_name"] = auth_svc.name
|
|
190
190
|
variables["auth_service_port"] = str(auth_svc.port)
|
|
191
191
|
|
|
192
|
+
# Dynamic: auth-passthrough — resolve auth service URL
|
|
193
|
+
if augment.name == "auth-passthrough":
|
|
194
|
+
auth_svc = next(
|
|
195
|
+
(s for s in spec.services if s.role == "auth"),
|
|
196
|
+
None,
|
|
197
|
+
)
|
|
198
|
+
if auth_svc is not None:
|
|
199
|
+
variables["auth_service_name"] = auth_svc.name
|
|
200
|
+
variables["auth_service_port"] = str(auth_svc.port)
|
|
201
|
+
|
|
192
202
|
# Dynamic: delegate-config — resolve targets
|
|
193
203
|
if augment.name == "delegate-config":
|
|
194
204
|
targets = augment.options.get("targets", [])
|
|
@@ -250,6 +260,10 @@ def scaffold_augment(
|
|
|
250
260
|
relative = template_file.relative_to(template_dir)
|
|
251
261
|
dest = svc_dest / relative
|
|
252
262
|
|
|
263
|
+
# Strip .template suffix so e.g. db.py.template → db.py
|
|
264
|
+
if dest.name.endswith(".template"):
|
|
265
|
+
dest = dest.with_name(dest.name.removesuffix(".template"))
|
|
266
|
+
|
|
253
267
|
# Never overwrite existing files
|
|
254
268
|
if dest.exists():
|
|
255
269
|
continue
|
|
@@ -29,6 +29,7 @@ _BASE_PACKAGES: list[str] = [
|
|
|
29
29
|
"fastapi>=0.115,<1",
|
|
30
30
|
"uvicorn[standard]>=0.30,<1",
|
|
31
31
|
"pydantic-settings>=2.6,<3",
|
|
32
|
+
"csrd-models>=0.3,<1",
|
|
32
33
|
"csrd-versioning>=0.1.36,<1",
|
|
33
34
|
]
|
|
34
35
|
|
|
@@ -154,6 +155,15 @@ def _augment_settings_fields(
|
|
|
154
155
|
augment_fields["jwt_issuer"] = '"csrd-auth"'
|
|
155
156
|
augment_fields["jwt_audience"] = f'"{spec.workspace.name}"'
|
|
156
157
|
|
|
158
|
+
# Dynamic: auth-passthrough
|
|
159
|
+
if augment.name == "auth-passthrough":
|
|
160
|
+
auth_svc = next(
|
|
161
|
+
(s for s in spec.services if s.role == "auth"),
|
|
162
|
+
None,
|
|
163
|
+
)
|
|
164
|
+
if auth_svc is not None:
|
|
165
|
+
augment_fields["auth_service_url"] = f'"http://{auth_svc.name}:{auth_svc.port}"'
|
|
166
|
+
|
|
157
167
|
# Dynamic: delegate-config
|
|
158
168
|
if augment.name == "delegate-config":
|
|
159
169
|
targets = augment.options.get("targets", [])
|
|
@@ -202,13 +212,10 @@ def render_settings(svc: ServiceNode, spec: ComposeSpec) -> str:
|
|
|
202
212
|
augment_fields = _augment_settings_fields(svc, spec)
|
|
203
213
|
|
|
204
214
|
lines = [
|
|
205
|
-
"from
|
|
215
|
+
"from csrd.models import BaseSettings",
|
|
206
216
|
"",
|
|
207
217
|
"",
|
|
208
218
|
"class Settings(BaseSettings):",
|
|
209
|
-
" model_config = SettingsConfigDict("
|
|
210
|
-
'env_file=".env", env_file_encoding="utf-8", extra="ignore"'
|
|
211
|
-
")",
|
|
212
219
|
"",
|
|
213
220
|
f' app_name: str = "{svc.name}"',
|
|
214
221
|
f" port: int = {svc.port}",
|
|
@@ -281,6 +288,10 @@ def render_init(svc: ServiceNode, spec: ComposeSpec) -> str:
|
|
|
281
288
|
imports.append("")
|
|
282
289
|
imports.append("from csrd.context.middleware import RequestContextMiddleware")
|
|
283
290
|
|
|
291
|
+
if "auth-passthrough" in augment_names:
|
|
292
|
+
imports.append("")
|
|
293
|
+
imports.append("from .views.auth_passthrough_view import router as auth_passthrough_router")
|
|
294
|
+
|
|
284
295
|
if "service-layer" in augment_names:
|
|
285
296
|
imports.append("")
|
|
286
297
|
imports.append("from csrd.service import service_exception_handler")
|
|
@@ -298,12 +309,17 @@ def render_init(svc: ServiceNode, spec: ComposeSpec) -> str:
|
|
|
298
309
|
body.append(" unversioned_app.include_router(jwks_router)")
|
|
299
310
|
body.append("")
|
|
300
311
|
|
|
312
|
+
if "auth-passthrough" in augment_names:
|
|
313
|
+
body.append(" unversioned_app.include_router(auth_passthrough_router)")
|
|
314
|
+
body.append("")
|
|
315
|
+
|
|
301
316
|
body.extend(
|
|
302
317
|
[
|
|
303
318
|
" app = compose_versioned_apps(",
|
|
304
319
|
" version_mapping={UNVERSIONED: unversioned_app},",
|
|
305
320
|
" config=VersionedAppComposeConfig(",
|
|
306
321
|
f' title="{svc.name}",',
|
|
322
|
+
' app_state={"settings": settings},',
|
|
307
323
|
" api=VersionedApiConfig(",
|
|
308
324
|
' prefix="/",',
|
|
309
325
|
" include_actuator_endpoints=settings.include_actuator_endpoints,",
|
csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/delegates/auth_delegate.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Auth service delegate for signup and login.
|
|
2
|
+
|
|
3
|
+
Proxies requests to the auth service's API endpoints.
|
|
4
|
+
This file is scaffolded once and never overwritten.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from csrd.delegate import BaseDelegate
|
|
8
|
+
|
|
9
|
+
from ..models.auth_passthrough import TokenResponse, UserResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AuthDelegate(BaseDelegate):
|
|
13
|
+
"""Delegate for the cluster auth service."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, base_url: str) -> None:
|
|
16
|
+
super().__init__(base_url)
|
|
17
|
+
|
|
18
|
+
async def signup(self, username: str, password: str) -> UserResponse:
|
|
19
|
+
"""Create a new user account via the auth service."""
|
|
20
|
+
return await self.post(
|
|
21
|
+
"/api/signup",
|
|
22
|
+
json={"username": username, "password": password},
|
|
23
|
+
response_model=UserResponse,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
async def login(self, username: str, password: str) -> TokenResponse:
|
|
27
|
+
"""Authenticate and obtain a JWT token via the auth service."""
|
|
28
|
+
return await self.post(
|
|
29
|
+
"/api/token",
|
|
30
|
+
json={"username": username, "password": password},
|
|
31
|
+
response_model=TokenResponse,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = ("AuthDelegate",)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""FastAPI dependency for the auth passthrough delegate.
|
|
2
|
+
|
|
3
|
+
This file is scaffolded once and never overwritten.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
from fastapi import Depends
|
|
9
|
+
|
|
10
|
+
from ..delegates.auth_delegate import AuthDelegate
|
|
11
|
+
from . import Settings
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def auth_delegate_factory(settings: Settings) -> AuthDelegate:
|
|
15
|
+
"""Create an ``AuthDelegate`` bound to the configured auth service URL."""
|
|
16
|
+
return AuthDelegate(settings.auth_service_url)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
AuthDelegateDep = Annotated[AuthDelegate, Depends(auth_delegate_factory)]
|
|
20
|
+
|
|
21
|
+
__all__ = ("AuthDelegateDep", "auth_delegate_factory")
|
csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/auth-passthrough/models/auth_passthrough.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Auth passthrough request/response models."""
|
|
2
|
+
|
|
3
|
+
from csrd.models import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SignupRequest(BaseModel):
|
|
7
|
+
"""Signup request body."""
|
|
8
|
+
|
|
9
|
+
username: str
|
|
10
|
+
password: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LoginRequest(BaseModel):
|
|
14
|
+
"""Login request body."""
|
|
15
|
+
|
|
16
|
+
username: str
|
|
17
|
+
password: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TokenResponse(BaseModel):
|
|
21
|
+
"""Token response from the auth service."""
|
|
22
|
+
|
|
23
|
+
access_token: str
|
|
24
|
+
token_type: str = "bearer"
|
|
25
|
+
expires_in: int
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class UserResponse(BaseModel):
|
|
29
|
+
"""User response from the auth service."""
|
|
30
|
+
|
|
31
|
+
id: str
|
|
32
|
+
username: str
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Auth passthrough endpoints — unguarded signup and login.
|
|
2
|
+
|
|
3
|
+
Proxies signup and login requests to the cluster auth service.
|
|
4
|
+
No authentication required on these endpoints.
|
|
5
|
+
This file is scaffolded once and never overwritten.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from fastapi import APIRouter
|
|
9
|
+
|
|
10
|
+
from ..dependencies.auth_passthrough import AuthDelegateDep
|
|
11
|
+
from ..models.auth_passthrough import LoginRequest, SignupRequest, TokenResponse, UserResponse
|
|
12
|
+
|
|
13
|
+
router = APIRouter(prefix="/api/auth", tags=["Auth"])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@router.post("/signup", status_code=201, response_model=UserResponse)
|
|
17
|
+
async def signup(body: SignupRequest, delegate: AuthDelegateDep) -> UserResponse:
|
|
18
|
+
"""Create a new user account via the auth service."""
|
|
19
|
+
return await delegate.signup(body.username, body.password)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@router.post("/login", response_model=TokenResponse)
|
|
23
|
+
async def login(body: LoginRequest, delegate: AuthDelegateDep) -> TokenResponse:
|
|
24
|
+
"""Authenticate and obtain a JWT token via the auth service."""
|
|
25
|
+
return await delegate.login(body.username, body.password)
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
"""Database adapter
|
|
1
|
+
"""Database adapter dependency for $service_name.
|
|
2
2
|
|
|
3
3
|
This file is scaffolded once and never overwritten. Customize the
|
|
4
4
|
adapter type, DSN construction, or add connection pooling here.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
from fastapi import Depends
|
|
10
|
+
|
|
7
11
|
$db_adapter_import
|
|
8
12
|
|
|
9
|
-
from
|
|
13
|
+
from . import Settings
|
|
10
14
|
|
|
11
15
|
|
|
12
|
-
def
|
|
16
|
+
def _create_adapter(settings: Settings) -> $db_adapter_class:
|
|
13
17
|
"""Create the database adapter for this service.
|
|
14
18
|
|
|
15
19
|
Override this to switch adapter types (PGAdapter, MariaAdapter)
|
|
@@ -18,4 +22,6 @@ def create_adapter() -> $db_adapter_class:
|
|
|
18
22
|
return $db_adapter_constructor
|
|
19
23
|
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
Adapter = Annotated[$db_adapter_class, Depends(_create_adapter)]
|
|
26
|
+
|
|
27
|
+
__all__ = ("Adapter",)
|
|
@@ -13,6 +13,11 @@ from ..settings import settings
|
|
|
13
13
|
|
|
14
14
|
# Build the auth dependency — tokens are verified locally using
|
|
15
15
|
# the public keys from the auth service's JWKS endpoint.
|
|
16
|
+
#
|
|
17
|
+
# Note: this is constructed at module level because FastAPI security
|
|
18
|
+
# dependencies (Security / Depends) must be stable objects. The
|
|
19
|
+
# settings singleton is appropriate here — auth config is fixed
|
|
20
|
+
# for the lifetime of the process.
|
|
16
21
|
auth_dep = create_jwt_bearer(
|
|
17
22
|
key=JWKSKeyProvider(url=settings.auth_jwks_url),
|
|
18
23
|
algorithms=[settings.jwt_algorithm],
|
csrd_utils-0.3.96/src/csrd_utils/v2/templates/augments/jwt-auth-provider/dependencies/db.py.template
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Database and repository dependencies for the auth service.
|
|
2
|
+
|
|
3
|
+
This file is scaffolded once and never overwritten.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
from fastapi import Depends
|
|
9
|
+
|
|
10
|
+
$db_adapter_import
|
|
11
|
+
|
|
12
|
+
from ..repositories.user_repository import UserRepository
|
|
13
|
+
from . import Settings
|
|
14
|
+
|
|
15
|
+
_adapter: $db_adapter_class | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def _get_adapter(settings: Settings) -> $db_adapter_class:
|
|
19
|
+
"""Get or create the database adapter (singleton per process)."""
|
|
20
|
+
global _adapter
|
|
21
|
+
if _adapter is None:
|
|
22
|
+
_adapter = $db_adapter_constructor
|
|
23
|
+
await _adapter.connect()
|
|
24
|
+
|
|
25
|
+
# Apply migrations on first connect
|
|
26
|
+
from csrd.migration import MigrationRunner
|
|
27
|
+
|
|
28
|
+
from ..migrations import migrations
|
|
29
|
+
|
|
30
|
+
runner = MigrationRunner()
|
|
31
|
+
await runner.apply_all(_adapter, migrations)
|
|
32
|
+
|
|
33
|
+
return _adapter
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Adapter = Annotated[$db_adapter_class, Depends(_get_adapter)]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _user_repository_factory(adapter: Adapter) -> UserRepository:
|
|
40
|
+
"""Create a ``UserRepository`` backed by the database adapter."""
|
|
41
|
+
return UserRepository(adapter)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
UserRepo = Annotated[UserRepository, Depends(_user_repository_factory)]
|
|
45
|
+
|
|
46
|
+
__all__ = ("Adapter", "UserRepo")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Token issuance and verification models."""
|
|
2
|
+
|
|
3
|
+
from csrd.models import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TokenRequest(BaseModel):
|
|
7
|
+
username: str
|
|
8
|
+
password: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TokenResponse(BaseModel):
|
|
12
|
+
"""JWT token issuance response."""
|
|
13
|
+
|
|
14
|
+
access_token: str
|
|
15
|
+
token_type: str = "bearer"
|
|
16
|
+
expires_in: int
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class VerifyRequest(BaseModel):
|
|
20
|
+
token: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class VerifyClaims(BaseModel):
|
|
24
|
+
"""JWT claim fields returned by the verify endpoint."""
|
|
25
|
+
|
|
26
|
+
sub: str
|
|
27
|
+
user_name: str
|
|
28
|
+
authorities: list[str]
|
|
29
|
+
iat: int
|
|
30
|
+
exp: int
|
|
31
|
+
iss: str
|
|
32
|
+
aud: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class VerifyResponse(BaseModel):
|
|
36
|
+
"""Token verification response."""
|
|
37
|
+
|
|
38
|
+
active: bool
|
|
39
|
+
claims: VerifyClaims
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""User management models."""
|
|
2
|
+
|
|
3
|
+
from csrd.models import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SignupRequest(BaseModel):
|
|
7
|
+
username: str
|
|
8
|
+
password: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UserResponse(BaseModel):
|
|
12
|
+
"""Basic user info returned after signup or lookup."""
|
|
13
|
+
|
|
14
|
+
id: str
|
|
15
|
+
username: str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class UserRolesResponse(BaseModel):
|
|
19
|
+
"""User with their assigned roles/authorities."""
|
|
20
|
+
|
|
21
|
+
user_id: str
|
|
22
|
+
roles: list[str]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RoleRequest(BaseModel):
|
|
26
|
+
role: str
|
|
@@ -7,85 +7,93 @@ This file is scaffolded once and never overwritten.
|
|
|
7
7
|
import hashlib
|
|
8
8
|
import secrets
|
|
9
9
|
import uuid
|
|
10
|
-
from typing import Any
|
|
11
10
|
|
|
11
|
+
from fastapi import HTTPException
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
from csrd.repository import BaseRepository
|
|
14
|
+
|
|
15
|
+
from ..models.users import UserResponse, UserRolesResponse
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
class UserRepository(BaseRepository):
|
|
19
|
+
"""User, credential, and role storage backed by a database adapter."""
|
|
18
20
|
|
|
19
21
|
# ── User CRUD ────────────────────────────────────────────────────
|
|
20
22
|
|
|
21
|
-
async def create_user(self, username: str, password: str) ->
|
|
23
|
+
async def create_user(self, username: str, password: str) -> UserResponse:
|
|
22
24
|
"""Create a new user with hashed credentials."""
|
|
23
25
|
user_id = str(uuid.uuid4())
|
|
24
|
-
await self.
|
|
26
|
+
await self.execute(
|
|
25
27
|
"INSERT INTO users (id, username) VALUES (:id, :username)",
|
|
26
28
|
{"id": user_id, "username": username},
|
|
27
29
|
)
|
|
28
30
|
|
|
29
31
|
password_hash = self._hash_password(password)
|
|
30
|
-
await self.
|
|
32
|
+
await self.execute(
|
|
31
33
|
"INSERT INTO user_credentials (user_id, password_hash) "
|
|
32
34
|
"VALUES (:user_id, :password_hash)",
|
|
33
35
|
{"user_id": user_id, "password_hash": password_hash},
|
|
34
36
|
)
|
|
35
37
|
|
|
36
|
-
return
|
|
38
|
+
return UserResponse(id=user_id, username=username)
|
|
37
39
|
|
|
38
|
-
async def get_user(self, user_id: str) ->
|
|
39
|
-
"""Get a user by ID."""
|
|
40
|
-
return await self.
|
|
41
|
-
"SELECT id, username
|
|
40
|
+
async def get_user(self, user_id: str) -> UserResponse:
|
|
41
|
+
"""Get a user by ID. Raises 404 if not found."""
|
|
42
|
+
return await self.require_one(
|
|
43
|
+
"SELECT id, username FROM users WHERE id = :id",
|
|
42
44
|
{"id": user_id},
|
|
45
|
+
model=UserResponse,
|
|
46
|
+
detail="User not found",
|
|
43
47
|
)
|
|
44
48
|
|
|
45
|
-
async def get_user_by_username(self, username: str) ->
|
|
46
|
-
"""Get a user by username."""
|
|
47
|
-
|
|
48
|
-
"SELECT id, username
|
|
49
|
+
async def get_user_by_username(self, username: str) -> UserResponse | None:
|
|
50
|
+
"""Get a user by username, or ``None`` if not found."""
|
|
51
|
+
row = await self.fetch_one(
|
|
52
|
+
"SELECT id, username FROM users WHERE username = :username",
|
|
49
53
|
{"username": username},
|
|
50
54
|
)
|
|
55
|
+
if row is None:
|
|
56
|
+
return None
|
|
57
|
+
return self.apply_model(row, model=UserResponse)
|
|
51
58
|
|
|
52
59
|
# ── Credential verification ──────────────────────────────────────
|
|
53
60
|
|
|
54
|
-
async def verify_credentials(self, username: str, password: str) ->
|
|
55
|
-
"""Verify username + password.
|
|
61
|
+
async def verify_credentials(self, username: str, password: str) -> UserResponse:
|
|
62
|
+
"""Verify username + password. Raises 401 on failure."""
|
|
56
63
|
user = await self.get_user_by_username(username)
|
|
57
64
|
if user is None:
|
|
58
|
-
|
|
65
|
+
raise HTTPException(status_code=401, detail="Invalid credentials")
|
|
59
66
|
|
|
60
|
-
cred = await self.
|
|
67
|
+
cred = await self.fetch_one(
|
|
61
68
|
"SELECT password_hash FROM user_credentials WHERE user_id = :user_id",
|
|
62
|
-
{"user_id": user
|
|
69
|
+
{"user_id": user.id},
|
|
63
70
|
)
|
|
64
|
-
if cred is None:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if not self._verify_password(password, cred["password_hash"]):
|
|
68
|
-
return None
|
|
71
|
+
if cred is None or not self._verify_password(password, cred["password_hash"]):
|
|
72
|
+
raise HTTPException(status_code=401, detail="Invalid credentials")
|
|
69
73
|
|
|
70
74
|
return user
|
|
71
75
|
|
|
72
76
|
# ── Role management ──────────────────────────────────────────────
|
|
73
77
|
|
|
74
|
-
async def
|
|
75
|
-
"""Get all roles for a user."""
|
|
76
|
-
|
|
78
|
+
async def get_user_roles(self, user_id: str) -> UserRolesResponse:
|
|
79
|
+
"""Get all roles for a user. Raises 404 if user not found."""
|
|
80
|
+
await self.get_user(user_id) # ensures user exists (raises 404)
|
|
81
|
+
rows = await self.fetch_all(
|
|
77
82
|
"SELECT role FROM user_roles WHERE user_id = :user_id",
|
|
78
83
|
{"user_id": user_id},
|
|
79
84
|
)
|
|
80
|
-
|
|
85
|
+
roles = [row["role"] for row in rows]
|
|
86
|
+
return UserRolesResponse(user_id=user_id, roles=roles)
|
|
81
87
|
|
|
82
|
-
async def add_role(self, user_id: str, role: str) ->
|
|
83
|
-
"""Add a role to a user. Idempotent."""
|
|
84
|
-
await self.
|
|
88
|
+
async def add_role(self, user_id: str, role: str) -> UserRolesResponse:
|
|
89
|
+
"""Add a role to a user. Idempotent. Returns updated roles."""
|
|
90
|
+
await self.get_user(user_id) # ensures user exists (raises 404)
|
|
91
|
+
await self.execute(
|
|
85
92
|
"INSERT OR IGNORE INTO user_roles (user_id, role) "
|
|
86
93
|
"VALUES (:user_id, :role)",
|
|
87
94
|
{"user_id": user_id, "role": role},
|
|
88
95
|
)
|
|
96
|
+
return await self.get_user_roles(user_id)
|
|
89
97
|
|
|
90
98
|
# ── Password hashing ─────────────────────────────────────────────
|
|
91
99
|
#
|