csrd-utils 0.3.60__tar.gz → 0.3.62__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.
Files changed (117) hide show
  1. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/PKG-INFO +1 -1
  2. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/pyproject.toml +1 -1
  3. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/__main__.py +5 -0
  4. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/generator.py +4 -0
  5. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/cookiecutter.json +1 -0
  6. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +6 -0
  7. csrd_utils-0.3.62/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/auth_service.py +64 -0
  8. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/requirements.txt +4 -0
  9. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/settings.py +7 -0
  10. csrd_utils-0.3.62/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +66 -0
  11. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/test_items.py +127 -28
  12. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/items_view.py +21 -0
  13. csrd_utils-0.3.60/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +0 -33
  14. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/.gitignore +0 -0
  15. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/README.md +0 -0
  16. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/__init__.py +0 -0
  17. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/audit.py +0 -0
  18. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/augmentor.py +0 -0
  19. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/cluster.py +0 -0
  20. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/doctor.py +0 -0
  21. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/conftest.fragment.py +0 -0
  22. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/docker-compose.fragment.yaml +0 -0
  23. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/manifest.yaml +0 -0
  24. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/requirements.fragment +0 -0
  25. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/settings.fragment.py +0 -0
  26. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/src/app/cache.py +0 -0
  27. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/caching/tests/test_cache.py +0 -0
  28. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/conftest.fragment.py +0 -0
  29. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/manifest.yaml +0 -0
  30. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/requirements.fragment +0 -0
  31. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/settings.fragment.py +0 -0
  32. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/src/app/middleware/logging.py +0 -0
  33. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/logging/tests/test_logging_middleware.py +0 -0
  34. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/conftest.fragment.py +0 -0
  35. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/docker-compose.fragment.yaml +0 -0
  36. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/manifest.yaml +0 -0
  37. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/requirements.fragment +0 -0
  38. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/settings.fragment.py +0 -0
  39. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/src/app/middleware/metrics.py +0 -0
  40. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/metrics/tests/test_metrics_middleware.py +0 -0
  41. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/conftest.fragment.py +0 -0
  42. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/manifest.yaml +0 -0
  43. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/requirements.fragment +0 -0
  44. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/settings.fragment.py +0 -0
  45. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/src/app/middleware/tracing.py +0 -0
  46. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/tracing/tests/test_tracing_middleware.py +0 -0
  47. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/conftest.fragment.py +0 -0
  48. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/docker-compose.fragment.yaml +0 -0
  49. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/manifest.yaml +0 -0
  50. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/requirements.fragment +0 -0
  51. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/settings.fragment.py +0 -0
  52. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/src/app/workers/__init__.py +0 -0
  53. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/src/app/workers/celery_app.py +0 -0
  54. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/src/app/workers/tasks.py +0 -0
  55. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/features/workers/tests/test_workers.py +0 -0
  56. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/fragments.py +0 -0
  57. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/resources.py +0 -0
  58. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/README.md +0 -0
  59. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/hooks/post_gen_project.py +0 -0
  60. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.cookiecutterignore +0 -0
  61. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
  62. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
  63. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
  64. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
  65. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/cache.py +0 -0
  66. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/__init__.py +0 -0
  67. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/upstreams.py +0 -0
  68. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/delegates.py +0 -0
  69. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/item_repository.py +0 -0
  70. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/worker_broker.py +0 -0
  71. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/docker-compose.yml +0 -0
  72. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/__init__.py +0 -0
  73. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/logging.py +0 -0
  74. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
  75. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/item_repository.py +0 -0
  76. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/__init__.py +0 -0
  77. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/__init__.py +0 -0
  78. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/test_logging_middleware.py +0 -0
  79. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/__init__.py +0 -0
  80. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_cache.py +0 -0
  81. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_database_settings.py +0 -0
  82. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_delegates.py +0 -0
  83. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_settings_contracts.py +0 -0
  84. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_worker_broker.py +0 -0
  85. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
  86. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
  87. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
  88. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/__init__.py +0 -0
  89. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/tasks.py +0 -0
  90. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/cookiecutter.json +0 -0
  91. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
  92. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
  93. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
  94. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
  95. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
  96. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
  97. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/repositories/token_repository.py +0 -0
  98. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
  99. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
  100. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
  101. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
  102. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/auth_view.py +0 -0
  103. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-auth-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
  104. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/cookiecutter.json +0 -0
  105. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
  106. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
  107. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
  108. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
  109. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
  110. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
  111. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/repositories/user_repository.py +0 -0
  112. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
  113. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
  114. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
  115. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
  116. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
  117. {csrd_utils-0.3.60 → csrd_utils-0.3.62}/src/csrd_utils/templates/platform-identity-service/{{cookiecutter.__service_name_snake}}/views/unversioned/users_view.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csrd-utils
3
- Version: 0.3.60
3
+ Version: 0.3.62
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "csrd-utils"
3
- version = "0.3.60"
3
+ version = "0.3.62"
4
4
  description = "CLI utilities for csrd service generation and feature augmentation"
5
5
  license = { text = "MIT" }
6
6
  requires-python = ">=3.12"
@@ -41,6 +41,7 @@ class GenerateServiceArgs(TypedDict):
41
41
  broker: str
42
42
  has_caching: bool
43
43
  cache_backend: str
44
+ has_auth: bool
44
45
  has_structured_logging: bool
45
46
  overwrite_if_exists: bool
46
47
 
@@ -236,6 +237,7 @@ def _collect_new_service_config(args: argparse.Namespace) -> GenerateServiceArgs
236
237
  "broker": args.broker,
237
238
  "has_caching": args.caching,
238
239
  "cache_backend": args.cache_backend,
240
+ "has_auth": False,
239
241
  "has_structured_logging": args.structured_logging,
240
242
  "overwrite_if_exists": args.force,
241
243
  }
@@ -327,6 +329,7 @@ def _collect_new_service_config(args: argparse.Namespace) -> GenerateServiceArgs
327
329
  "broker": broker,
328
330
  "has_caching": has_caching,
329
331
  "cache_backend": cache_backend,
332
+ "has_auth": False,
330
333
  "has_structured_logging": has_structured_logging,
331
334
  "overwrite_if_exists": overwrite_if_exists,
332
335
  }
@@ -468,6 +471,7 @@ def _generate_services_from_cluster_spec(
468
471
  has_delegates = bool(delegates_list)
469
472
  has_workers = service_type == "worker" or "workers" in features
470
473
  has_caching = "caching" in features
474
+ has_auth = "auth-service" in service.get("requires", []) and name != "auth-service"
471
475
  has_structured_logging = "logging" in features
472
476
  database = str(service.get("database", "sqlite")) if has_database else "sqlite"
473
477
 
@@ -516,6 +520,7 @@ def _generate_services_from_cluster_spec(
516
520
  broker=broker,
517
521
  has_caching=has_caching,
518
522
  cache_backend="redis",
523
+ has_auth=has_auth,
519
524
  has_structured_logging=has_structured_logging,
520
525
  overwrite_if_exists=force,
521
526
  )
@@ -137,6 +137,7 @@ def _build_context(
137
137
  broker: str,
138
138
  has_caching: bool,
139
139
  cache_backend: str,
140
+ has_auth: bool,
140
141
  has_structured_logging: bool,
141
142
  ) -> dict[str, Any]:
142
143
  return {
@@ -153,6 +154,7 @@ def _build_context(
153
154
  "broker": broker,
154
155
  "has_caching": has_caching,
155
156
  "cache_backend": cache_backend,
157
+ "has_auth": has_auth,
156
158
  "has_structured_logging": has_structured_logging,
157
159
  }
158
160
 
@@ -175,6 +177,7 @@ def generate_service(
175
177
  cache_backend: str,
176
178
  has_structured_logging: bool,
177
179
  overwrite_if_exists: bool,
180
+ has_auth: bool = False,
178
181
  ) -> Path:
179
182
  """Generate a service from the bundled cookiecutter-service template."""
180
183
  output_root = output_dir.resolve()
@@ -204,6 +207,7 @@ def generate_service(
204
207
  broker=broker,
205
208
  has_caching=has_caching,
206
209
  cache_backend=cache_backend,
210
+ has_auth=has_auth,
207
211
  has_structured_logging=has_structured_logging,
208
212
  )
209
213
 
@@ -18,6 +18,7 @@
18
18
  "cache_backend": [
19
19
  "redis"
20
20
  ],
21
+ "has_auth": false,
21
22
  "has_structured_logging": true,
22
23
  "port": "8080",
23
24
  "model_name": "Item",
@@ -17,3 +17,9 @@ from .worker_broker import get_worker_broker_url
17
17
 
18
18
  __all__ += ("get_worker_broker_url",)
19
19
  {%- endif %}
20
+
21
+ {%- if cookiecutter.has_auth %}
22
+ from .auth_service import VerifiedTokenDep
23
+
24
+ __all__ += ("VerifiedTokenDep",)
25
+ {%- endif %}
@@ -0,0 +1,64 @@
1
+ {%- if cookiecutter.has_auth %}
2
+ from typing import Annotated
3
+
4
+ import httpx
5
+ from fastapi import HTTPException, Security
6
+ from fastapi.requests import Request
7
+
8
+ from csrd.auth import CallbackAuthenticator, create_bearer_dependency
9
+ from csrd.models.claims import UserClaims
10
+ from csrd.versioning import find_token
11
+
12
+ from ..settings import settings
13
+
14
+
15
+ def _map_claims(payload: dict[str, object]) -> UserClaims:
16
+ claims = payload.get("claims") if isinstance(payload.get("claims"), dict) else payload
17
+ if not isinstance(claims, dict):
18
+ raise HTTPException(status_code=502, detail="invalid auth response")
19
+
20
+ authorities = claims.get("authorities") or claims.get("roles") or []
21
+ if isinstance(authorities, str):
22
+ authorities = authorities.split()
23
+
24
+ sub = str(claims.get("sub", ""))
25
+ user_name = str(claims.get("user_name") or sub)
26
+
27
+ return UserClaims(
28
+ sub=sub,
29
+ user_name=user_name,
30
+ authorities=list(authorities),
31
+ )
32
+
33
+
34
+ async def _remote_verify(_: Request, token: str) -> UserClaims:
35
+ try:
36
+ async with httpx.AsyncClient(timeout=5.0) as client:
37
+ response = await client.post(
38
+ f"{settings.auth_service_url}/api/verify",
39
+ json={"token": token},
40
+ )
41
+ except httpx.ConnectError as exc:
42
+ raise HTTPException(status_code=503, detail="auth service unavailable") from exc
43
+
44
+ if response.status_code != 200:
45
+ raise HTTPException(status_code=401, detail="invalid token")
46
+
47
+ payload = response.json()
48
+ if not isinstance(payload, dict):
49
+ raise HTTPException(status_code=502, detail="invalid auth response")
50
+ return _map_claims(payload)
51
+
52
+
53
+ _authenticator = CallbackAuthenticator(callback=_remote_verify)
54
+
55
+ VerifiedTokenDep = Annotated[
56
+ UserClaims,
57
+ Security(create_bearer_dependency(_authenticator, token_finder=find_token)),
58
+ ]
59
+
60
+
61
+ __all__ = ("VerifiedTokenDep",)
62
+ {%- else %}
63
+ __all__: tuple[str, ...] = ()
64
+ {%- endif %}
@@ -24,6 +24,10 @@ psycopg[binary]>=3.2,<4
24
24
  csrd-delegate>=0.1.36,<1
25
25
  {%- endif %}
26
26
 
27
+ {%- if cookiecutter.has_auth %}
28
+ csrd-auth>=0.1.36,<1
29
+ {%- endif %}
30
+
27
31
  {%- if cookiecutter.has_workers %}
28
32
  celery>=5.4,<6
29
33
  {%- if cookiecutter.broker == "redis" %}
@@ -57,6 +57,13 @@ class Settings(BaseSettings):
57
57
  has_caching: bool = False
58
58
  {%- endif %}
59
59
 
60
+ {%- if cookiecutter.has_auth %}
61
+ has_auth: bool = True
62
+ auth_service_url: str = "http://auth-service:8081"
63
+ {%- else %}
64
+ has_auth: bool = False
65
+ {%- endif %}
66
+
60
67
  @model_validator(mode="after")
61
68
  def validate_db_credentials(self) -> Self:
62
69
  if not self.has_database:
@@ -0,0 +1,66 @@
1
+ """Shared test fixtures for {{ cookiecutter.service_name }}."""
2
+
3
+ import os
4
+ import secrets
5
+
6
+ import pytest
7
+ from fastapi.testclient import TestClient
8
+ {%- if cookiecutter.has_auth %}
9
+ from fastapi import HTTPException
10
+
11
+ from csrd.models.claims import UserClaims
12
+
13
+ from {{cookiecutter.__service_name_snake}}.dependencies import auth_service as auth_dependency
14
+ {%- endif %}
15
+
16
+ from {{cookiecutter.__service_name_snake}} import build_app
17
+
18
+ HAS_DATABASE = {{"True" if cookiecutter.has_database else "False"}}
19
+ DB_KIND = "{{ cookiecutter.database }}"
20
+ HAS_AUTH = {{"True" if cookiecutter.has_auth else "False"}}
21
+
22
+
23
+ # [INSERT: fixtures]
24
+
25
+
26
+ {%- if cookiecutter.has_auth %}
27
+ @pytest.fixture
28
+ def auth_token() -> str:
29
+ # Generate a per-test bearer token value used by auth-guarded endpoints.
30
+ return f"test-token-{secrets.token_hex(8)}"
31
+
32
+
33
+ @pytest.fixture(autouse=True)
34
+ def mock_auth_verifier(auth_token: str):
35
+ original_callback = auth_dependency._authenticator.callback
36
+
37
+ async def _fake_verify(_request, token: str) -> UserClaims:
38
+ if token != auth_token:
39
+ raise HTTPException(status_code=401, detail="invalid token")
40
+ return UserClaims(sub="test-user", user_name="test-user", authorities=["ROLE_USER"])
41
+
42
+ auth_dependency._authenticator.callback = _fake_verify
43
+ try:
44
+ yield
45
+ finally:
46
+ auth_dependency._authenticator.callback = original_callback
47
+ {%- endif %}
48
+
49
+
50
+ @pytest.fixture
51
+ def client():
52
+ if HAS_DATABASE and DB_KIND == "maria":
53
+ os.environ.setdefault("DB_HOST", "localhost")
54
+ os.environ.setdefault("DB_PORT", "3306")
55
+ os.environ.setdefault("DB_USER", "service_user")
56
+ os.environ.setdefault("DB_PASSWORD", "change_me")
57
+ os.environ.setdefault("DB_NAME", "service_db")
58
+ elif HAS_DATABASE and DB_KIND == "postgres":
59
+ os.environ.setdefault("DB_HOST", "localhost")
60
+ os.environ.setdefault("DB_PORT", "5432")
61
+ os.environ.setdefault("DB_USER", "service_user")
62
+ os.environ.setdefault("DB_PASSWORD", "change_me")
63
+ os.environ.setdefault("DB_NAME", "service_db")
64
+
65
+ app = build_app()
66
+ return TestClient(app)
@@ -2,6 +2,13 @@
2
2
 
3
3
  from fastapi import HTTPException
4
4
 
5
+ {%- if cookiecutter.has_auth %}
6
+
7
+
8
+ def _auth_headers(token: str) -> dict[str, str]:
9
+ return {"Authorization": f"Bearer {token}"}
10
+ {%- endif %}
11
+
5
12
 
6
13
  def test_health(client):
7
14
  response = client.get("/health")
@@ -10,9 +17,13 @@ def test_health(client):
10
17
 
11
18
 
12
19
  {%- if cookiecutter.has_database or not cookiecutter.has_delegates %}
13
- def test_create_item_returns_data(client):
20
+ def test_create_item_returns_data(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
14
21
  create_response = client.post(
15
- "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "Test Item"}
22
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
23
+ json={"name": "Test Item"},
24
+ {%- if cookiecutter.has_auth %}
25
+ headers=_auth_headers(auth_token),
26
+ {%- endif %}
16
27
  )
17
28
  assert create_response.status_code == 200
18
29
  item = create_response.json()
@@ -21,11 +32,28 @@ def test_create_item_returns_data(client):
21
32
  assert "created_at" in item
22
33
 
23
34
 
24
- def test_list_items(client):
25
- client.post("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "Item 1"})
26
- client.post("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "Item 2"})
35
+ def test_list_items(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
36
+ client.post(
37
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
38
+ json={"name": "Item 1"},
39
+ {%- if cookiecutter.has_auth %}
40
+ headers=_auth_headers(auth_token),
41
+ {%- endif %}
42
+ )
43
+ client.post(
44
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
45
+ json={"name": "Item 2"},
46
+ {%- if cookiecutter.has_auth %}
47
+ headers=_auth_headers(auth_token),
48
+ {%- endif %}
49
+ )
27
50
 
28
- response = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}")
51
+ response = client.get(
52
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
53
+ {%- if cookiecutter.has_auth %}
54
+ headers=_auth_headers(auth_token),
55
+ {%- endif %}
56
+ )
29
57
  assert response.status_code == 200
30
58
  items = response.json()["{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}"]
31
59
  names = {item["name"] for item in items}
@@ -33,46 +61,73 @@ def test_list_items(client):
33
61
  assert "Item 2" in names
34
62
 
35
63
 
36
- def test_get_item_missing_returns_404(client):
37
- response = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing-id")
64
+ def test_get_item_missing_returns_404(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
65
+ response = client.get(
66
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing-id",
67
+ {%- if cookiecutter.has_auth %}
68
+ headers=_auth_headers(auth_token),
69
+ {%- endif %}
70
+ )
38
71
  assert response.status_code == 404
39
72
 
40
73
 
41
- def test_get_item_returns_created_item(client):
74
+ def test_get_item_returns_created_item(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
42
75
  created = client.post(
43
- "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "Lookup"}
76
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
77
+ json={"name": "Lookup"},
78
+ {%- if cookiecutter.has_auth %}
79
+ headers=_auth_headers(auth_token),
80
+ {%- endif %}
44
81
  ).json()
45
82
  response = client.get(
46
- f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{created['id']}"
83
+ f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{created['id']}",
84
+ {%- if cookiecutter.has_auth %}
85
+ headers=_auth_headers(auth_token),
86
+ {%- endif %}
47
87
  )
48
88
  assert response.status_code == 200
49
89
  assert response.json()["id"] == created["id"]
50
90
  assert response.json()["name"] == "Lookup"
51
91
 
52
92
 
53
- def test_update_and_delete_item(client):
93
+ def test_update_and_delete_item(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
54
94
  created = client.post(
55
- "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "Original"}
95
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
96
+ json={"name": "Original"},
97
+ {%- if cookiecutter.has_auth %}
98
+ headers=_auth_headers(auth_token),
99
+ {%- endif %}
56
100
  ).json()
57
101
  item_id = created["id"]
58
102
 
59
103
  updated = client.put(
60
104
  f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{item_id}",
61
105
  json={"name": "Updated"},
106
+ {%- if cookiecutter.has_auth %}
107
+ headers=_auth_headers(auth_token),
108
+ {%- endif %}
62
109
  )
63
110
  assert updated.status_code == 200
64
111
  assert updated.json()["updated"] is True
65
112
 
66
- deleted = client.delete(f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{item_id}")
113
+ deleted = client.delete(
114
+ f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{item_id}",
115
+ {%- if cookiecutter.has_auth %}
116
+ headers=_auth_headers(auth_token),
117
+ {%- endif %}
118
+ )
67
119
  assert deleted.status_code == 200
68
120
  assert deleted.json()["deleted"] is True
69
121
 
70
122
 
71
- def test_upsert_item(client):
123
+ def test_upsert_item(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
72
124
  item_id = "custom-upsert-id"
73
125
  first = client.put(
74
126
  f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{item_id}/upsert",
75
127
  json={"name": "Created"},
128
+ {%- if cookiecutter.has_auth %}
129
+ headers=_auth_headers(auth_token),
130
+ {%- endif %}
76
131
  )
77
132
  assert first.status_code == 200
78
133
  assert first.json()["rows_affected"] == 1
@@ -80,29 +135,38 @@ def test_upsert_item(client):
80
135
  second = client.put(
81
136
  f"/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/{item_id}/upsert",
82
137
  json={"name": "Updated"},
138
+ {%- if cookiecutter.has_auth %}
139
+ headers=_auth_headers(auth_token),
140
+ {%- endif %}
83
141
  )
84
142
  assert second.status_code == 200
85
143
  assert second.json()["rows_affected"] == 1
86
144
 
87
145
 
88
- def test_update_missing_returns_404(client):
146
+ def test_update_missing_returns_404(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
89
147
  response = client.put(
90
148
  "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing-id",
91
149
  json={"name": "Nope"},
150
+ {%- if cookiecutter.has_auth %}
151
+ headers=_auth_headers(auth_token),
152
+ {%- endif %}
92
153
  )
93
154
  assert response.status_code == 404
94
155
 
95
156
 
96
- def test_delete_missing_returns_404(client):
157
+ def test_delete_missing_returns_404(client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
97
158
  response = client.delete(
98
- "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing-id"
159
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing-id",
160
+ {%- if cookiecutter.has_auth %}
161
+ headers=_auth_headers(auth_token),
162
+ {%- endif %}
99
163
  )
100
164
  assert response.status_code == 404
101
165
  {%- endif %}
102
166
 
103
167
 
104
168
  {%- if cookiecutter.has_delegates and not cookiecutter.has_database %}
105
- def test_delegate_create_and_list(monkeypatch, client):
169
+ def test_delegate_create_and_list(monkeypatch, client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
106
170
  calls: list[tuple[str, str]] = []
107
171
 
108
172
  async def fake_delegate_request(method: str, path: str, payload=None):
@@ -114,28 +178,42 @@ def test_delegate_create_and_list(monkeypatch, client):
114
178
  monkeypatch.setattr("{{cookiecutter.__service_name_snake}}.views.unversioned.items_view._delegate_request", fake_delegate_request)
115
179
 
116
180
  created = client.post(
117
- "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}", json={"name": "X"}
181
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
182
+ json={"name": "X"},
183
+ {%- if cookiecutter.has_auth %}
184
+ headers=_auth_headers(auth_token),
185
+ {%- endif %}
118
186
  )
119
187
  assert created.status_code == 200
120
188
  assert created.json()["id"] == "d1"
121
189
 
122
- listed = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}")
190
+ listed = client.get(
191
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
192
+ {%- if cookiecutter.has_auth %}
193
+ headers=_auth_headers(auth_token),
194
+ {%- endif %}
195
+ )
123
196
  assert listed.status_code == 200
124
197
  assert len(listed.json()["{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}"]) == 1
125
198
  assert calls[0][0] == "POST"
126
199
  assert calls[1][0] == "GET"
127
200
 
128
201
 
129
- def test_delegate_error_mapping(monkeypatch, client):
202
+ def test_delegate_error_mapping(monkeypatch, client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
130
203
  async def fake_delegate_request(_method: str, _path: str, payload=None):
131
204
  raise HTTPException(status_code=404, detail="not found")
132
205
 
133
206
  monkeypatch.setattr("{{cookiecutter.__service_name_snake}}.views.unversioned.items_view._delegate_request", fake_delegate_request)
134
- response = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing")
207
+ response = client.get(
208
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/missing",
209
+ {%- if cookiecutter.has_auth %}
210
+ headers=_auth_headers(auth_token),
211
+ {%- endif %}
212
+ )
135
213
  assert response.status_code == 404
136
214
 
137
215
 
138
- def test_delegate_get_update_upsert_delete(monkeypatch, client):
216
+ def test_delegate_get_update_upsert_delete(monkeypatch, client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
139
217
  async def fake_delegate_request(method: str, path: str, payload=None):
140
218
  if method == "GET":
141
219
  return {"id": "d2", "name": "From delegate", "created_at": "2026-01-01T00:00:00Z"}
@@ -149,13 +227,21 @@ def test_delegate_get_update_upsert_delete(monkeypatch, client):
149
227
 
150
228
  monkeypatch.setattr("{{cookiecutter.__service_name_snake}}.views.unversioned.items_view._delegate_request", fake_delegate_request)
151
229
 
152
- fetched = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2")
230
+ fetched = client.get(
231
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2",
232
+ {%- if cookiecutter.has_auth %}
233
+ headers=_auth_headers(auth_token),
234
+ {%- endif %}
235
+ )
153
236
  assert fetched.status_code == 200
154
237
  assert fetched.json()["id"] == "d2"
155
238
 
156
239
  updated = client.put(
157
240
  "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2",
158
241
  json={"name": "Updated"},
242
+ {%- if cookiecutter.has_auth %}
243
+ headers=_auth_headers(auth_token),
244
+ {%- endif %}
159
245
  )
160
246
  assert updated.status_code == 200
161
247
  assert updated.json()["updated"] is True
@@ -163,20 +249,33 @@ def test_delegate_get_update_upsert_delete(monkeypatch, client):
163
249
  upserted = client.put(
164
250
  "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2/upsert",
165
251
  json={"name": "Upserted"},
252
+ {%- if cookiecutter.has_auth %}
253
+ headers=_auth_headers(auth_token),
254
+ {%- endif %}
166
255
  )
167
256
  assert upserted.status_code == 200
168
257
  assert upserted.json()["rows_affected"] == 1
169
258
 
170
- deleted = client.delete("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2")
259
+ deleted = client.delete(
260
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}/d2",
261
+ {%- if cookiecutter.has_auth %}
262
+ headers=_auth_headers(auth_token),
263
+ {%- endif %}
264
+ )
171
265
  assert deleted.status_code == 200
172
266
  assert deleted.json()["deleted"] is True
173
267
 
174
268
 
175
- def test_delegate_list_invalid_payload_returns_502(monkeypatch, client):
269
+ def test_delegate_list_invalid_payload_returns_502(monkeypatch, client{%- if cookiecutter.has_auth %}, auth_token{% endif %}):
176
270
  async def fake_delegate_request(_method: str, _path: str, payload=None):
177
271
  return {"{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}": "bad"}
178
272
 
179
273
  monkeypatch.setattr("{{cookiecutter.__service_name_snake}}.views.unversioned.items_view._delegate_request", fake_delegate_request)
180
- response = client.get("/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}")
274
+ response = client.get(
275
+ "/api/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}",
276
+ {%- if cookiecutter.has_auth %}
277
+ headers=_auth_headers(auth_token),
278
+ {%- endif %}
279
+ )
181
280
  assert response.status_code == 502
182
281
  {%- endif %}
@@ -11,6 +11,9 @@ from pydantic import BaseModel
11
11
  {%- if cookiecutter.has_database %}
12
12
  from ...dependencies import RepositoryDep
13
13
  {%- endif %}
14
+ {%- if cookiecutter.has_auth %}
15
+ from ...dependencies import VerifiedTokenDep
16
+ {%- endif %}
14
17
 
15
18
  ITEMS_ROUTE = "/{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}"
16
19
 
@@ -89,6 +92,9 @@ def _dummy_item(record_id: str, name: str, created_at: str) -> dict[str, str]:
89
92
  @router.post(ITEMS_ROUTE, response_model={{ cookiecutter.model_name }}Response)
90
93
  async def create_{{ cookiecutter.model_name | lower }}(
91
94
  payload: Create{{ cookiecutter.model_name }}Request,
95
+ {%- if cookiecutter.has_auth %}
96
+ _verified: VerifiedTokenDep,
97
+ {%- endif %}
92
98
  {%- if cookiecutter.has_database %}
93
99
  repo: RepositoryDep,
94
100
  {%- endif %}
@@ -113,6 +119,9 @@ async def create_{{ cookiecutter.model_name | lower }}(
113
119
 
114
120
  @router.get(ITEMS_ROUTE, response_model={{ cookiecutter.model_name }}ListResponse)
115
121
  async def list_{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}(
122
+ {%- if cookiecutter.has_auth %}
123
+ _verified: VerifiedTokenDep,
124
+ {%- endif %}
116
125
  {%- if cookiecutter.has_database %}
117
126
  repo: RepositoryDep,
118
127
  {%- endif %}
@@ -134,6 +143,9 @@ async def list_{{ cookiecutter.model_name_plural | lower | replace(' ', '_') }}(
134
143
  @router.get(f"{ITEMS_ROUTE}" + "/{entity_id}", response_model={{ cookiecutter.model_name }}Response)
135
144
  async def get_{{ cookiecutter.model_name | lower }}(
136
145
  entity_id: str,
146
+ {%- if cookiecutter.has_auth %}
147
+ _verified: VerifiedTokenDep,
148
+ {%- endif %}
137
149
  {%- if cookiecutter.has_database %}
138
150
  repo: RepositoryDep,
139
151
  {%- endif %}
@@ -161,6 +173,9 @@ async def get_{{ cookiecutter.model_name | lower }}(
161
173
  async def update_{{ cookiecutter.model_name | lower }}(
162
174
  entity_id: str,
163
175
  payload: Update{{ cookiecutter.model_name }}Request,
176
+ {%- if cookiecutter.has_auth %}
177
+ _verified: VerifiedTokenDep,
178
+ {%- endif %}
164
179
  {%- if cookiecutter.has_database %}
165
180
  repo: RepositoryDep,
166
181
  {%- endif %}
@@ -197,6 +212,9 @@ async def update_{{ cookiecutter.model_name | lower }}(
197
212
  async def upsert_{{ cookiecutter.model_name | lower }}(
198
213
  entity_id: str,
199
214
  payload: Update{{ cookiecutter.model_name }}Request,
215
+ {%- if cookiecutter.has_auth %}
216
+ _verified: VerifiedTokenDep,
217
+ {%- endif %}
200
218
  {%- if cookiecutter.has_database %}
201
219
  repo: RepositoryDep,
202
220
  {%- endif %}
@@ -229,6 +247,9 @@ async def upsert_{{ cookiecutter.model_name | lower }}(
229
247
  @router.delete(f"{ITEMS_ROUTE}" + "/{entity_id}", response_model={{ cookiecutter.model_name }}DeleteResponse)
230
248
  async def delete_{{ cookiecutter.model_name | lower }}(
231
249
  entity_id: str,
250
+ {%- if cookiecutter.has_auth %}
251
+ _verified: VerifiedTokenDep,
252
+ {%- endif %}
232
253
  {%- if cookiecutter.has_database %}
233
254
  repo: RepositoryDep,
234
255
  {%- endif %}
@@ -1,33 +0,0 @@
1
- """Shared test fixtures for {{ cookiecutter.service_name }}."""
2
-
3
- import os
4
-
5
- import pytest
6
- from fastapi.testclient import TestClient
7
-
8
- from {{cookiecutter.__service_name_snake}} import build_app
9
-
10
- HAS_DATABASE = {{"True" if cookiecutter.has_database else "False"}}
11
- DB_KIND = "{{ cookiecutter.database }}"
12
-
13
-
14
- # [INSERT: fixtures]
15
-
16
-
17
- @pytest.fixture
18
- def client():
19
- if HAS_DATABASE and DB_KIND == "maria":
20
- os.environ.setdefault("DB_HOST", "localhost")
21
- os.environ.setdefault("DB_PORT", "3306")
22
- os.environ.setdefault("DB_USER", "service_user")
23
- os.environ.setdefault("DB_PASSWORD", "change_me")
24
- os.environ.setdefault("DB_NAME", "service_db")
25
- elif HAS_DATABASE and DB_KIND == "postgres":
26
- os.environ.setdefault("DB_HOST", "localhost")
27
- os.environ.setdefault("DB_PORT", "5432")
28
- os.environ.setdefault("DB_USER", "service_user")
29
- os.environ.setdefault("DB_PASSWORD", "change_me")
30
- os.environ.setdefault("DB_NAME", "service_db")
31
-
32
- app = build_app()
33
- return TestClient(app)
File without changes
File without changes