core-framework 0.12.1__tar.gz → 0.12.2__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.
- {core_framework-0.12.1 → core_framework-0.12.2}/PKG-INFO +1 -1
- {core_framework-0.12.1 → core_framework-0.12.2}/core/__init__.py +66 -2
- {core_framework-0.12.1 → core_framework-0.12.2}/core/app.py +65 -3
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/__init__.py +27 -2
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/base.py +146 -0
- core_framework-0.12.2/core/auth/middleware.py +316 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/models.py +139 -23
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/schemas.py +5 -1
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/views.py +168 -50
- {core_framework-0.12.1 → core_framework-0.12.2}/core/config.py +27 -0
- core_framework-0.12.2/core/middleware.py +774 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/operations.py +88 -10
- {core_framework-0.12.1 → core_framework-0.12.2}/core/views.py +453 -28
- core_framework-0.12.2/docs/30-changelog-0.12.2.md +265 -0
- core_framework-0.12.2/docs/31-middleware.md +580 -0
- core_framework-0.12.2/docs/32-migration-guide-0.12.2.md +421 -0
- core_framework-0.12.2/docs/99-faq-troubleshooting.md +985 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/README.md +14 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/pyproject.toml +1 -1
- {core_framework-0.12.1 → core_framework-0.12.2}/.gitignore +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/README.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/backends.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/decorators.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/hashers.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/permissions.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/auth/tokens.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/choices.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/cli/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/cli/main.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/database.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/datetime.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/dependencies.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/deployment/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/deployment/docker.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/deployment/kubernetes.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/deployment/pm2.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/exceptions.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/fields.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/avro.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/base.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/config.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/confluent/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/confluent/consumer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/confluent/producer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/decorators.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/kafka/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/kafka/admin.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/kafka/broker.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/kafka/consumer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/kafka/producer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/rabbitmq/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/rabbitmq/broker.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/rabbitmq/consumer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/rabbitmq/producer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/redis/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/redis/broker.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/redis/consumer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/redis/producer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/registry.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/topics.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/messaging/workers.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/analyzer.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/cli.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/engine.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/migration.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/migrations/state.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/models.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/permissions.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/querysets.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/relations.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/routing.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/serializers.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/base.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/config.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/decorators.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/registry.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/scheduler.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tasks/worker.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/tenancy.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/core/validators.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/01-quickstart.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/02-viewsets.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/03-authentication.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/04-messaging.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/05-multi-service.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/06-tasks.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/07-deployment.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/08-complete-example.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/09-settings.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/10-migrations.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/11-permissions.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/12-auth-backends.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/13-validators.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/14-querysets.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/15-routing.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/16-serializers.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/17-datetime.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/18-dependencies.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/19-views.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/20-fields.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/21-tenancy.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/22-replicas.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/23-soft-delete.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/24-relations.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/25-exceptions.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/26-choices.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/27-workers.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/28-avro.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/29-topics.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/docs/GUIDE.md +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/app.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/auth.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/models.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/schemas.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/example/views.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/libs/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/main.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/tests/__init__.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/tests/conftest.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/tests/test_models.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/tests/test_querysets.py +0 -0
- {core_framework-0.12.1 → core_framework-0.12.2}/tests/test_serializers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: core-framework
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.2
|
|
4
4
|
Summary: Core Framework - Django-inspired, FastAPI-powered. Alta performance, baixo acoplamento, produtividade extrema.
|
|
5
5
|
Project-URL: Homepage, https://github.com/SorPuti/core-framework
|
|
6
6
|
Project-URL: Documentation, https://github.com/SorPuti/core-framework#readme
|
|
@@ -20,7 +20,21 @@ Enterprise Features (v0.3.0+):
|
|
|
20
20
|
|
|
21
21
|
from core.models import Model, Field, SoftDeleteMixin, SoftDeleteManager, TenantSoftDeleteManager
|
|
22
22
|
from core.serializers import InputSchema, OutputSchema, Serializer
|
|
23
|
-
from core.views import
|
|
23
|
+
from core.views import (
|
|
24
|
+
APIView,
|
|
25
|
+
ViewSet,
|
|
26
|
+
ModelViewSet,
|
|
27
|
+
ReadOnlyModelViewSet,
|
|
28
|
+
CreateModelViewSet,
|
|
29
|
+
ListModelViewSet,
|
|
30
|
+
ListCreateModelViewSet,
|
|
31
|
+
RetrieveUpdateModelViewSet,
|
|
32
|
+
RetrieveDestroyModelViewSet,
|
|
33
|
+
RetrieveUpdateDestroyModelViewSet,
|
|
34
|
+
SearchModelViewSet,
|
|
35
|
+
BulkModelViewSet,
|
|
36
|
+
action,
|
|
37
|
+
)
|
|
24
38
|
from core.routing import Router, AutoRouter
|
|
25
39
|
from core.permissions import Permission, IsAuthenticated, AllowAny, IsAdmin, IsOwner, HasRole
|
|
26
40
|
from core.dependencies import Depends, get_db, get_current_user
|
|
@@ -84,6 +98,25 @@ from core.datetime import (
|
|
|
84
98
|
get_timezone,
|
|
85
99
|
)
|
|
86
100
|
|
|
101
|
+
# Middleware - Sistema Django-style
|
|
102
|
+
from core.middleware import (
|
|
103
|
+
BaseMiddleware,
|
|
104
|
+
configure_middleware,
|
|
105
|
+
register_middleware,
|
|
106
|
+
apply_middlewares,
|
|
107
|
+
get_middleware_stack_info,
|
|
108
|
+
print_middleware_stack,
|
|
109
|
+
# Pre-built middlewares
|
|
110
|
+
TimingMiddleware,
|
|
111
|
+
RequestIDMiddleware,
|
|
112
|
+
LoggingMiddleware,
|
|
113
|
+
MaintenanceModeMiddleware,
|
|
114
|
+
SecurityHeadersMiddleware,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Auth - ViewSet
|
|
118
|
+
from core.auth.views import AuthViewSet
|
|
119
|
+
|
|
87
120
|
# Auth - Sistema plugável de autenticação
|
|
88
121
|
from core.auth import (
|
|
89
122
|
# Config
|
|
@@ -123,6 +156,7 @@ from core.auth import (
|
|
|
123
156
|
ObjectPermissionBackend,
|
|
124
157
|
# Models
|
|
125
158
|
AbstractUser,
|
|
159
|
+
AbstractUUIDUser,
|
|
126
160
|
Group,
|
|
127
161
|
Permission as AuthPermission,
|
|
128
162
|
PermissionsMixin,
|
|
@@ -136,6 +170,9 @@ from core.auth import (
|
|
|
136
170
|
require_staff,
|
|
137
171
|
require_active,
|
|
138
172
|
login_required,
|
|
173
|
+
# Middleware
|
|
174
|
+
AuthenticationMiddleware,
|
|
175
|
+
OptionalAuthenticationMiddleware,
|
|
139
176
|
)
|
|
140
177
|
|
|
141
178
|
# Migrations
|
|
@@ -241,7 +278,7 @@ from core.exceptions import (
|
|
|
241
278
|
MissingDependency,
|
|
242
279
|
)
|
|
243
280
|
|
|
244
|
-
__version__ = "0.12.
|
|
281
|
+
__version__ = "0.12.2"
|
|
245
282
|
__all__ = [
|
|
246
283
|
# Models
|
|
247
284
|
"Model",
|
|
@@ -257,6 +294,15 @@ __all__ = [
|
|
|
257
294
|
"APIView",
|
|
258
295
|
"ViewSet",
|
|
259
296
|
"ModelViewSet",
|
|
297
|
+
"ReadOnlyModelViewSet",
|
|
298
|
+
"CreateModelViewSet",
|
|
299
|
+
"ListModelViewSet",
|
|
300
|
+
"ListCreateModelViewSet",
|
|
301
|
+
"RetrieveUpdateModelViewSet",
|
|
302
|
+
"RetrieveDestroyModelViewSet",
|
|
303
|
+
"RetrieveUpdateDestroyModelViewSet",
|
|
304
|
+
"SearchModelViewSet",
|
|
305
|
+
"BulkModelViewSet",
|
|
260
306
|
"action",
|
|
261
307
|
# Routing
|
|
262
308
|
"Router",
|
|
@@ -277,6 +323,18 @@ __all__ = [
|
|
|
277
323
|
"get_settings",
|
|
278
324
|
# App
|
|
279
325
|
"CoreApp",
|
|
326
|
+
# Middleware
|
|
327
|
+
"BaseMiddleware",
|
|
328
|
+
"configure_middleware",
|
|
329
|
+
"register_middleware",
|
|
330
|
+
"apply_middlewares",
|
|
331
|
+
"get_middleware_stack_info",
|
|
332
|
+
"print_middleware_stack",
|
|
333
|
+
"TimingMiddleware",
|
|
334
|
+
"RequestIDMiddleware",
|
|
335
|
+
"LoggingMiddleware",
|
|
336
|
+
"MaintenanceModeMiddleware",
|
|
337
|
+
"SecurityHeadersMiddleware",
|
|
280
338
|
# Advanced Fields
|
|
281
339
|
"uuid7",
|
|
282
340
|
"uuid7_str",
|
|
@@ -316,6 +374,8 @@ __all__ = [
|
|
|
316
374
|
"configure_datetime",
|
|
317
375
|
"get_datetime_config",
|
|
318
376
|
"get_timezone",
|
|
377
|
+
# Auth - ViewSet
|
|
378
|
+
"AuthViewSet",
|
|
319
379
|
# Auth - Config
|
|
320
380
|
"AuthConfig",
|
|
321
381
|
"configure_auth",
|
|
@@ -352,10 +412,14 @@ __all__ = [
|
|
|
352
412
|
"ObjectPermissionBackend",
|
|
353
413
|
# Auth - Models
|
|
354
414
|
"AbstractUser",
|
|
415
|
+
"AbstractUUIDUser",
|
|
355
416
|
"Group",
|
|
356
417
|
"AuthPermission",
|
|
357
418
|
"PermissionsMixin",
|
|
358
419
|
"get_user_model",
|
|
420
|
+
# Auth - Middleware
|
|
421
|
+
"AuthenticationMiddleware",
|
|
422
|
+
"OptionalAuthenticationMiddleware",
|
|
359
423
|
# Auth - Decorators
|
|
360
424
|
"HasPermission",
|
|
361
425
|
"IsInGroup",
|
|
@@ -34,7 +34,7 @@ class CoreApp:
|
|
|
34
34
|
|
|
35
35
|
Encapsula FastAPI com configurações e lifecycle management.
|
|
36
36
|
|
|
37
|
-
Exemplo:
|
|
37
|
+
Exemplo básico:
|
|
38
38
|
app = CoreApp(
|
|
39
39
|
title="My API",
|
|
40
40
|
settings=MySettings(),
|
|
@@ -45,6 +45,23 @@ class CoreApp:
|
|
|
45
45
|
|
|
46
46
|
# Obtém a aplicação FastAPI
|
|
47
47
|
fastapi_app = app.app
|
|
48
|
+
|
|
49
|
+
Exemplo com middlewares Django-style:
|
|
50
|
+
app = CoreApp(
|
|
51
|
+
title="My API",
|
|
52
|
+
middleware=[
|
|
53
|
+
"core.middleware.TimingMiddleware",
|
|
54
|
+
"core.auth.AuthenticationMiddleware",
|
|
55
|
+
("core.middleware.LoggingMiddleware", {"log_headers": True}),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
Shortcuts disponíveis:
|
|
60
|
+
- "auth": AuthenticationMiddleware
|
|
61
|
+
- "timing": TimingMiddleware
|
|
62
|
+
- "request_id": RequestIDMiddleware
|
|
63
|
+
- "logging": LoggingMiddleware
|
|
64
|
+
- "security_headers": SecurityHeadersMiddleware
|
|
48
65
|
"""
|
|
49
66
|
|
|
50
67
|
def __init__(
|
|
@@ -57,6 +74,7 @@ class CoreApp:
|
|
|
57
74
|
on_startup: list[Callable] | None = None,
|
|
58
75
|
on_shutdown: list[Callable] | None = None,
|
|
59
76
|
middlewares: list[tuple[type, dict[str, Any]]] | None = None,
|
|
77
|
+
middleware: list[str | type | tuple] | None = None,
|
|
60
78
|
exception_handlers: dict[type, Callable] | None = None,
|
|
61
79
|
auto_create_tables: bool = True,
|
|
62
80
|
**fastapi_kwargs: Any,
|
|
@@ -72,10 +90,19 @@ class CoreApp:
|
|
|
72
90
|
routers: Lista de routers a incluir
|
|
73
91
|
on_startup: Callbacks de startup
|
|
74
92
|
on_shutdown: Callbacks de shutdown
|
|
75
|
-
middlewares: Lista de middlewares (classe, kwargs)
|
|
93
|
+
middlewares: Lista de middlewares formato antigo (classe, kwargs)
|
|
94
|
+
middleware: Lista de middlewares formato Django-style (strings/classes)
|
|
76
95
|
exception_handlers: Handlers de exceção customizados
|
|
77
96
|
auto_create_tables: Se True, cria tabelas automaticamente
|
|
78
97
|
**fastapi_kwargs: Argumentos extras para FastAPI
|
|
98
|
+
|
|
99
|
+
Middleware format (novo, Django-style):
|
|
100
|
+
middleware=[
|
|
101
|
+
"core.auth.AuthenticationMiddleware", # String path
|
|
102
|
+
"auth", # Shortcut
|
|
103
|
+
MyMiddleware, # Classe direta
|
|
104
|
+
("logging", {"log_body": True}), # Com kwargs
|
|
105
|
+
]
|
|
79
106
|
"""
|
|
80
107
|
self.settings = settings or get_settings()
|
|
81
108
|
self._on_startup = on_startup or []
|
|
@@ -100,7 +127,12 @@ class CoreApp:
|
|
|
100
127
|
if self.settings.tenancy_enabled:
|
|
101
128
|
self._setup_tenancy_middleware()
|
|
102
129
|
|
|
103
|
-
# Adiciona middlewares
|
|
130
|
+
# Adiciona middlewares - formato novo Django-style (parâmetro ou settings)
|
|
131
|
+
middleware_list = middleware or getattr(self.settings, "middleware", None)
|
|
132
|
+
if middleware_list:
|
|
133
|
+
self._setup_django_style_middleware(middleware_list)
|
|
134
|
+
|
|
135
|
+
# Adiciona middlewares - formato antigo (tuple)
|
|
104
136
|
if middlewares:
|
|
105
137
|
for middleware_class, middleware_kwargs in middlewares:
|
|
106
138
|
self.app.add_middleware(middleware_class, **middleware_kwargs)
|
|
@@ -206,6 +238,36 @@ class CoreApp:
|
|
|
206
238
|
require_tenant=self.settings.tenancy_require,
|
|
207
239
|
)
|
|
208
240
|
|
|
241
|
+
def _setup_django_style_middleware(
|
|
242
|
+
self,
|
|
243
|
+
middleware_list: list[str | type | tuple],
|
|
244
|
+
) -> None:
|
|
245
|
+
"""
|
|
246
|
+
Configura middlewares no estilo Django.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
middleware_list: Lista de middlewares
|
|
250
|
+
- String: path do middleware (ex: "core.auth.AuthenticationMiddleware")
|
|
251
|
+
- String shortcut: nome curto (ex: "auth", "timing")
|
|
252
|
+
- Classe: classe do middleware diretamente
|
|
253
|
+
- Tuple: (middleware, kwargs) para passar configurações
|
|
254
|
+
|
|
255
|
+
Example:
|
|
256
|
+
middleware_list = [
|
|
257
|
+
"core.middleware.TimingMiddleware",
|
|
258
|
+
"auth", # shortcut para AuthenticationMiddleware
|
|
259
|
+
MyCustomMiddleware,
|
|
260
|
+
("logging", {"log_body": True}),
|
|
261
|
+
]
|
|
262
|
+
"""
|
|
263
|
+
from core.middleware import configure_middleware, apply_middlewares
|
|
264
|
+
|
|
265
|
+
# Configura no registry global
|
|
266
|
+
configure_middleware(middleware_list, clear_existing=True)
|
|
267
|
+
|
|
268
|
+
# Aplica ao app
|
|
269
|
+
apply_middlewares(self.app)
|
|
270
|
+
|
|
209
271
|
def _setup_exception_handlers(
|
|
210
272
|
self,
|
|
211
273
|
custom_handlers: dict[type, Callable] | None = None,
|
|
@@ -43,8 +43,13 @@ from core.auth.base import (
|
|
|
43
43
|
# Config
|
|
44
44
|
AuthConfig,
|
|
45
45
|
AuthConfigurationError,
|
|
46
|
+
ConfigurationWarning,
|
|
46
47
|
configure_auth,
|
|
47
48
|
get_auth_config,
|
|
49
|
+
# Validation helpers (preventive)
|
|
50
|
+
validate_auth_configuration,
|
|
51
|
+
check_middleware_configured,
|
|
52
|
+
get_auth_setup_checklist,
|
|
48
53
|
)
|
|
49
54
|
|
|
50
55
|
# Default implementations
|
|
@@ -76,10 +81,12 @@ from core.auth.permissions import (
|
|
|
76
81
|
# Models
|
|
77
82
|
from core.auth.models import (
|
|
78
83
|
AbstractUser,
|
|
84
|
+
AbstractUUIDUser,
|
|
79
85
|
PermissionsMixin,
|
|
80
86
|
Group,
|
|
81
87
|
Permission,
|
|
82
88
|
get_user_model,
|
|
89
|
+
clear_association_table_cache,
|
|
83
90
|
)
|
|
84
91
|
|
|
85
92
|
# Decorators and dependencies
|
|
@@ -107,7 +114,14 @@ from core.auth.schemas import (
|
|
|
107
114
|
|
|
108
115
|
# Views
|
|
109
116
|
from core.auth.views import (
|
|
110
|
-
|
|
117
|
+
AuthViewSet,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Middleware (Bug #8 Fix)
|
|
121
|
+
from core.auth.middleware import (
|
|
122
|
+
AuthenticationMiddleware,
|
|
123
|
+
OptionalAuthenticationMiddleware,
|
|
124
|
+
ensure_auth_middleware,
|
|
111
125
|
)
|
|
112
126
|
|
|
113
127
|
__all__ = [
|
|
@@ -128,8 +142,13 @@ __all__ = [
|
|
|
128
142
|
# Config
|
|
129
143
|
"AuthConfig",
|
|
130
144
|
"AuthConfigurationError",
|
|
145
|
+
"ConfigurationWarning",
|
|
131
146
|
"configure_auth",
|
|
132
147
|
"get_auth_config",
|
|
148
|
+
# Validation helpers
|
|
149
|
+
"validate_auth_configuration",
|
|
150
|
+
"check_middleware_configured",
|
|
151
|
+
"get_auth_setup_checklist",
|
|
133
152
|
# Hashers
|
|
134
153
|
"PBKDF2Hasher",
|
|
135
154
|
"Argon2Hasher",
|
|
@@ -149,10 +168,12 @@ __all__ = [
|
|
|
149
168
|
"ObjectPermissionBackend",
|
|
150
169
|
# Models
|
|
151
170
|
"AbstractUser",
|
|
171
|
+
"AbstractUUIDUser",
|
|
152
172
|
"PermissionsMixin",
|
|
153
173
|
"Group",
|
|
154
174
|
"Permission",
|
|
155
175
|
"get_user_model",
|
|
176
|
+
"clear_association_table_cache",
|
|
156
177
|
# Decorators
|
|
157
178
|
"HasPermission",
|
|
158
179
|
"IsInGroup",
|
|
@@ -171,5 +192,9 @@ __all__ = [
|
|
|
171
192
|
"BaseUserOutput",
|
|
172
193
|
"MessageResponse",
|
|
173
194
|
# Views
|
|
174
|
-
"
|
|
195
|
+
"AuthViewSet",
|
|
196
|
+
# Middleware
|
|
197
|
+
"AuthenticationMiddleware",
|
|
198
|
+
"OptionalAuthenticationMiddleware",
|
|
199
|
+
"ensure_auth_middleware",
|
|
175
200
|
]
|
|
@@ -485,6 +485,10 @@ class AuthConfig:
|
|
|
485
485
|
password_require_lowercase: bool = False
|
|
486
486
|
password_require_digit: bool = False
|
|
487
487
|
password_require_special: bool = False
|
|
488
|
+
|
|
489
|
+
# Middleware automático (Bug #8 preventive)
|
|
490
|
+
# Se True, emite warning se middleware não estiver configurado
|
|
491
|
+
warn_missing_middleware: bool = True
|
|
488
492
|
|
|
489
493
|
|
|
490
494
|
_auth_config: AuthConfig | None = None
|
|
@@ -599,3 +603,145 @@ def get_auth_config() -> AuthConfig:
|
|
|
599
603
|
if _auth_config is None:
|
|
600
604
|
_auth_config = AuthConfig()
|
|
601
605
|
return _auth_config
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
# =============================================================================
|
|
609
|
+
# Configuration Validation (Preventive measures)
|
|
610
|
+
# =============================================================================
|
|
611
|
+
|
|
612
|
+
class ConfigurationWarning(UserWarning):
|
|
613
|
+
"""Warning for potential configuration issues."""
|
|
614
|
+
pass
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def validate_auth_configuration() -> list[str]:
|
|
618
|
+
"""
|
|
619
|
+
Validate current auth configuration and return list of issues.
|
|
620
|
+
|
|
621
|
+
This is a preventive measure to catch common configuration mistakes.
|
|
622
|
+
|
|
623
|
+
Returns:
|
|
624
|
+
List of warning messages
|
|
625
|
+
"""
|
|
626
|
+
issues = []
|
|
627
|
+
config = get_auth_config()
|
|
628
|
+
|
|
629
|
+
# Check secret key
|
|
630
|
+
if config.secret_key == "change-me-in-production":
|
|
631
|
+
issues.append(
|
|
632
|
+
"Using default SECRET_KEY. Set a secure key in production: "
|
|
633
|
+
"configure_auth(secret_key='your-secure-key-256-bits')"
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
# Check if user_model is configured
|
|
637
|
+
if config.user_model is None:
|
|
638
|
+
issues.append(
|
|
639
|
+
"No user_model configured. Authentication endpoints may not work. "
|
|
640
|
+
"Use: configure_auth(user_model=YourUserClass)"
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
# Check if user_model has UUID PK and warn about PermissionsMixin
|
|
644
|
+
if config.user_model is not None:
|
|
645
|
+
try:
|
|
646
|
+
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
|
|
647
|
+
from sqlalchemy import Uuid
|
|
648
|
+
|
|
649
|
+
if hasattr(config.user_model, "__table__"):
|
|
650
|
+
pk_cols = [c for c in config.user_model.__table__.columns if c.primary_key]
|
|
651
|
+
if pk_cols and isinstance(pk_cols[0].type, (PG_UUID, Uuid)):
|
|
652
|
+
# Has UUID PK - check if PermissionsMixin is used
|
|
653
|
+
from core.auth.models import PermissionsMixin
|
|
654
|
+
if issubclass(config.user_model, PermissionsMixin):
|
|
655
|
+
# This is now handled, but inform the user
|
|
656
|
+
pass # Silently pass, we fixed the issue
|
|
657
|
+
except Exception:
|
|
658
|
+
pass
|
|
659
|
+
|
|
660
|
+
return issues
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def emit_configuration_warnings() -> None:
|
|
664
|
+
"""
|
|
665
|
+
Emit warnings for configuration issues.
|
|
666
|
+
|
|
667
|
+
Called automatically when using authentication features.
|
|
668
|
+
"""
|
|
669
|
+
import warnings
|
|
670
|
+
|
|
671
|
+
issues = validate_auth_configuration()
|
|
672
|
+
for issue in issues:
|
|
673
|
+
warnings.warn(issue, ConfigurationWarning, stacklevel=3)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def check_middleware_configured(app: Any = None) -> bool:
|
|
677
|
+
"""
|
|
678
|
+
Check if AuthenticationMiddleware is configured on the app.
|
|
679
|
+
|
|
680
|
+
Args:
|
|
681
|
+
app: FastAPI or CoreApp instance (optional)
|
|
682
|
+
|
|
683
|
+
Returns:
|
|
684
|
+
True if middleware appears to be configured
|
|
685
|
+
"""
|
|
686
|
+
if app is None:
|
|
687
|
+
return False
|
|
688
|
+
|
|
689
|
+
# Check if app has our middleware
|
|
690
|
+
try:
|
|
691
|
+
if hasattr(app, "app"):
|
|
692
|
+
# CoreApp wrapping FastAPI
|
|
693
|
+
fastapi_app = app.app
|
|
694
|
+
else:
|
|
695
|
+
fastapi_app = app
|
|
696
|
+
|
|
697
|
+
if hasattr(fastapi_app, "middleware_stack"):
|
|
698
|
+
# Check middleware stack for our middleware
|
|
699
|
+
stack = fastapi_app.middleware_stack
|
|
700
|
+
while stack is not None:
|
|
701
|
+
if hasattr(stack, "app"):
|
|
702
|
+
if "AuthenticationMiddleware" in type(stack.app).__name__:
|
|
703
|
+
return True
|
|
704
|
+
stack = getattr(stack, "app", None)
|
|
705
|
+
else:
|
|
706
|
+
break
|
|
707
|
+
except Exception:
|
|
708
|
+
pass
|
|
709
|
+
|
|
710
|
+
return False
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def get_auth_setup_checklist() -> str:
|
|
714
|
+
"""
|
|
715
|
+
Return a checklist of auth setup steps.
|
|
716
|
+
|
|
717
|
+
Useful for documentation and debugging.
|
|
718
|
+
|
|
719
|
+
Returns:
|
|
720
|
+
Formatted checklist string
|
|
721
|
+
"""
|
|
722
|
+
config = get_auth_config()
|
|
723
|
+
|
|
724
|
+
checklist = []
|
|
725
|
+
checklist.append("## Auth Setup Checklist\n")
|
|
726
|
+
|
|
727
|
+
# 1. User model
|
|
728
|
+
if config.user_model:
|
|
729
|
+
checklist.append(f" User model configured: {config.user_model.__name__}")
|
|
730
|
+
else:
|
|
731
|
+
checklist.append("X User model NOT configured")
|
|
732
|
+
checklist.append(" -> configure_auth(user_model=YourUserClass)")
|
|
733
|
+
|
|
734
|
+
# 2. Secret key
|
|
735
|
+
if config.secret_key != "change-me-in-production":
|
|
736
|
+
checklist.append(" Secret key configured")
|
|
737
|
+
else:
|
|
738
|
+
checklist.append("! Using default secret key (OK for development)")
|
|
739
|
+
checklist.append(" -> configure_auth(secret_key='secure-key') for production")
|
|
740
|
+
|
|
741
|
+
# 3. Middleware
|
|
742
|
+
checklist.append("")
|
|
743
|
+
checklist.append("[!] Don't forget to add AuthenticationMiddleware:")
|
|
744
|
+
checklist.append(" from core.auth import AuthenticationMiddleware")
|
|
745
|
+
checklist.append(" app = CoreApp(middlewares=[(AuthenticationMiddleware, {})])")
|
|
746
|
+
|
|
747
|
+
return "\n".join(checklist)
|