statezero 0.1.0b16__py3-none-any.whl → 0.1.0b17__py3-none-any.whl
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.
Potentially problematic release.
This version of statezero might be problematic. Click here for more details.
- statezero/adaptors/django/schemas.py +1 -2
- statezero/adaptors/django/urls.py +2 -1
- statezero/adaptors/django/views.py +101 -0
- {statezero-0.1.0b16.dist-info → statezero-0.1.0b17.dist-info}/METADATA +1 -1
- {statezero-0.1.0b16.dist-info → statezero-0.1.0b17.dist-info}/RECORD +8 -8
- {statezero-0.1.0b16.dist-info → statezero-0.1.0b17.dist-info}/WHEEL +0 -0
- {statezero-0.1.0b16.dist-info → statezero-0.1.0b17.dist-info}/licenses/license.md +0 -0
- {statezero-0.1.0b16.dist-info → statezero-0.1.0b17.dist-info}/top_level.txt +0 -0
|
@@ -323,8 +323,7 @@ class DjangoSchemaGenerator(AbstractSchemaGenerator):
|
|
|
323
323
|
@staticmethod
|
|
324
324
|
def is_field_required(field: models.Field) -> bool:
|
|
325
325
|
return (
|
|
326
|
-
not field.
|
|
327
|
-
and not field.null
|
|
326
|
+
not field.null
|
|
328
327
|
and field.default == models.fields.NOT_PROVIDED
|
|
329
328
|
)
|
|
330
329
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from django.urls import path
|
|
2
2
|
|
|
3
|
-
from .views import EventsAuthView, ModelListView, ModelView, SchemaView, FileUploadView, FastUploadView, ActionSchemaView, ActionView, ValidateView
|
|
3
|
+
from .views import EventsAuthView, ModelListView, ModelView, SchemaView, FileUploadView, FastUploadView, ActionSchemaView, ActionView, ValidateView, FieldPermissionsView
|
|
4
4
|
|
|
5
5
|
app_name = "statezero"
|
|
6
6
|
|
|
@@ -12,6 +12,7 @@ urlpatterns = [
|
|
|
12
12
|
path("actions/<str:action_name>/", ActionView.as_view(), name="action"),
|
|
13
13
|
path("actions-schema/", ActionSchemaView.as_view(), name="actions_schema"),
|
|
14
14
|
path("<str:model_name>/validate/", ValidateView.as_view(), name="validate"),
|
|
15
|
+
path("<str:model_name>/field-permissions/", FieldPermissionsView.as_view(), name="field_permissions"),
|
|
15
16
|
path("<str:model_name>/get-schema/", SchemaView.as_view(), name="schema_view"),
|
|
16
17
|
path("<str:model_name>/", ModelView.as_view(), name="model_view"),
|
|
17
18
|
]
|
|
@@ -485,3 +485,104 @@ class ValidateView(APIView):
|
|
|
485
485
|
except Exception as original_exception:
|
|
486
486
|
# Let StateZero's exception handler deal with ValidationError, PermissionDenied, etc.
|
|
487
487
|
return explicit_exception_handler(original_exception)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
class FieldPermissionsView(APIView):
|
|
491
|
+
"""
|
|
492
|
+
Returns user-specific field permissions for a given model.
|
|
493
|
+
Used by frontend forms to determine which fields to show/enable at runtime.
|
|
494
|
+
"""
|
|
495
|
+
|
|
496
|
+
permission_classes = [permission_class]
|
|
497
|
+
|
|
498
|
+
def get(self, request, model_name):
|
|
499
|
+
"""Get field permissions for the current user."""
|
|
500
|
+
try:
|
|
501
|
+
# Create processor following the same pattern as other views
|
|
502
|
+
processor = RequestProcessor(config=config, registry=registry)
|
|
503
|
+
|
|
504
|
+
# Get model using the processor's ORM provider
|
|
505
|
+
try:
|
|
506
|
+
model = processor.orm_provider.get_model_by_name(model_name)
|
|
507
|
+
except (LookupError, ValueError):
|
|
508
|
+
return Response({"error": f"Model {model_name} not found"}, status=404)
|
|
509
|
+
|
|
510
|
+
if not model:
|
|
511
|
+
return Response({"error": f"Model {model_name} not found"}, status=404)
|
|
512
|
+
|
|
513
|
+
try:
|
|
514
|
+
model_config = processor.registry.get_config(model)
|
|
515
|
+
except ValueError:
|
|
516
|
+
return Response(
|
|
517
|
+
{"error": f"Model {model_name} not registered"}, status=404
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
# Compute field permissions using the same logic as ASTParser._get_operation_fields
|
|
521
|
+
all_fields = processor.orm_provider.get_fields(model)
|
|
522
|
+
|
|
523
|
+
visible_fields = self._compute_operation_fields(
|
|
524
|
+
model, model_config, all_fields, request, "read"
|
|
525
|
+
)
|
|
526
|
+
creatable_fields = self._compute_operation_fields(
|
|
527
|
+
model, model_config, all_fields, request, "create"
|
|
528
|
+
)
|
|
529
|
+
editable_fields = self._compute_operation_fields(
|
|
530
|
+
model, model_config, all_fields, request, "update"
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
return Response(
|
|
534
|
+
{
|
|
535
|
+
"visible_fields": list(visible_fields),
|
|
536
|
+
"creatable_fields": list(creatable_fields),
|
|
537
|
+
"editable_fields": list(editable_fields),
|
|
538
|
+
},
|
|
539
|
+
status=200,
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
except Exception as original_exception:
|
|
543
|
+
# Let StateZero's exception handler deal with errors
|
|
544
|
+
return explicit_exception_handler(original_exception)
|
|
545
|
+
|
|
546
|
+
def _compute_operation_fields(self, model, model_config, all_fields, request, operation_type):
|
|
547
|
+
"""
|
|
548
|
+
Compute allowed fields for a specific operation type.
|
|
549
|
+
Replicates the logic from ASTParser._get_operation_fields.
|
|
550
|
+
"""
|
|
551
|
+
from typing import Union, Set, Literal
|
|
552
|
+
|
|
553
|
+
allowed_fields = set()
|
|
554
|
+
|
|
555
|
+
for permission_cls in model_config.permissions:
|
|
556
|
+
permission = permission_cls()
|
|
557
|
+
|
|
558
|
+
# Get the appropriate field set based on operation
|
|
559
|
+
if operation_type == "read":
|
|
560
|
+
fields = permission.visible_fields(request, model)
|
|
561
|
+
elif operation_type == "create":
|
|
562
|
+
fields = permission.create_fields(request, model)
|
|
563
|
+
elif operation_type == "update":
|
|
564
|
+
fields = permission.editable_fields(request, model)
|
|
565
|
+
else:
|
|
566
|
+
fields = set()
|
|
567
|
+
|
|
568
|
+
# If any permission allows all fields
|
|
569
|
+
if fields == "__all__":
|
|
570
|
+
# For read operations, default "__all__" to frontend_fields
|
|
571
|
+
if operation_type == "read":
|
|
572
|
+
# If frontend_fields is also "__all__", then return all fields
|
|
573
|
+
if model_config.frontend_fields == "__all__":
|
|
574
|
+
return all_fields
|
|
575
|
+
# Otherwise, use frontend_fields as the default for "__all__"
|
|
576
|
+
else:
|
|
577
|
+
fields = model_config.frontend_fields
|
|
578
|
+
fields &= all_fields # Ensure fields actually exist
|
|
579
|
+
allowed_fields |= fields
|
|
580
|
+
else:
|
|
581
|
+
# For create/update operations, "__all__" means truly all fields
|
|
582
|
+
return all_fields
|
|
583
|
+
else:
|
|
584
|
+
# Add allowed fields from this permission
|
|
585
|
+
fields &= all_fields # Ensure fields actually exist
|
|
586
|
+
allowed_fields |= fields
|
|
587
|
+
|
|
588
|
+
return allowed_fields
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: statezero
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0b17
|
|
4
4
|
Summary: Connect your Python backend to a modern JavaScript SPA frontend with 90% less complexity.
|
|
5
5
|
Author-email: Robert <robert.herring@statezero.dev>
|
|
6
6
|
Project-URL: homepage, https://www.statezero.dev
|
|
@@ -13,10 +13,10 @@ statezero/adaptors/django/middleware.py,sha256=YVr8fkqCk51xJQM-ovtrUiB9Kt9H81cLd
|
|
|
13
13
|
statezero/adaptors/django/orm.py,sha256=Z62XheCvuKIpKOoIIiLLOwrpJ5jPhv-BGxg-pqPgNaU,40757
|
|
14
14
|
statezero/adaptors/django/permissions.py,sha256=fU2c4bKK0zX2uuVB0UazZHTI-5OkiI5-BtPNcPEWmW0,9525
|
|
15
15
|
statezero/adaptors/django/query_optimizer.py,sha256=-iAh5kyE8WNZdjb_qBbNag_nxKzejroUYPBdwG_uVaQ,41462
|
|
16
|
-
statezero/adaptors/django/schemas.py,sha256=
|
|
16
|
+
statezero/adaptors/django/schemas.py,sha256=YpmXd3XMZpkjPiHB_3OMnDgc1thgOj3RgFx-YXhScqs,14058
|
|
17
17
|
statezero/adaptors/django/serializers.py,sha256=YFFDu6bzoWkSEOVH5Wmc4yJ8SaOkUA6HbXXYt6djlfc,23296
|
|
18
|
-
statezero/adaptors/django/urls.py,sha256=
|
|
19
|
-
statezero/adaptors/django/views.py,sha256=
|
|
18
|
+
statezero/adaptors/django/urls.py,sha256=bLn_kL5a5VBQfhl2-UCpLmguSenjJ7bouPoKMKNTX5M,1054
|
|
19
|
+
statezero/adaptors/django/views.py,sha256=RKReFV3AiMT_5jL5fVbPDnSnKfhpBtVt5FlzL4psWhw,24201
|
|
20
20
|
statezero/adaptors/django/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
statezero/adaptors/django/extensions/custom_field_serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
statezero/adaptors/django/extensions/custom_field_serializers/file_fields.py,sha256=BaOaJPmyzCp-YFwpsTOvGHjHpk6s8UJuZ5JsF-PEGV4,4518
|
|
@@ -41,8 +41,8 @@ statezero/core/hook_checks.py,sha256=uqtvwRx1qGsF7Vc49elAWdOjMzhuv3RADKY1wiLvhK4
|
|
|
41
41
|
statezero/core/interfaces.py,sha256=kVkNWyh52tUlzD02CRheLJof3DyQoVcPuvX33fL6sn8,20544
|
|
42
42
|
statezero/core/process_request.py,sha256=dwIeBEVOE8zA-oE1h65XNOGiVqFbbXA7SzTAguLNgZk,8060
|
|
43
43
|
statezero/core/types.py,sha256=mMtqK3fGhEM6LtzUgQrxlyP-V0VgVqc-1eVKgRjTzp0,913
|
|
44
|
-
statezero-0.1.
|
|
45
|
-
statezero-0.1.
|
|
46
|
-
statezero-0.1.
|
|
47
|
-
statezero-0.1.
|
|
48
|
-
statezero-0.1.
|
|
44
|
+
statezero-0.1.0b17.dist-info/licenses/license.md,sha256=0uKjybTt9K_YbEmYgf25JN292qjjJ-BPofvIZ3wdtX4,7411
|
|
45
|
+
statezero-0.1.0b17.dist-info/METADATA,sha256=OTnEueJ01hbh4EwG6LzpGxgdF4HzCg0sxXb4QpXfeKM,6704
|
|
46
|
+
statezero-0.1.0b17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
47
|
+
statezero-0.1.0b17.dist-info/top_level.txt,sha256=UAuZYPKczradU1kcMQxsGjUzEW0qdgsqzhXyscrcLpw,10
|
|
48
|
+
statezero-0.1.0b17.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|