From 4262c138019a0032e5b51ee01e61d4e9c5d09d83 Mon Sep 17 00:00:00 2001 From: Julian Leucker <leuckerj@gmail.com> Date: Mon, 3 Apr 2023 15:44:23 +0200 Subject: [PATCH] Create CRU queries and mutations for Room --- aleksis/core/schema/__init__.py | 23 +++++++++++++++++- aleksis/core/schema/base.py | 41 +++++++++++++++++++++++++++++++++ aleksis/core/schema/room.py | 16 ++++++++++++- pyproject.toml | 1 + 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/aleksis/core/schema/__init__.py b/aleksis/core/schema/__init__.py index deab0e28b..901c4d8a3 100644 --- a/aleksis/core/schema/__init__.py +++ b/aleksis/core/schema/__init__.py @@ -9,7 +9,7 @@ from haystack.inputs import AutoQuery from haystack.query import SearchQuerySet from haystack.utils.loading import UnifiedIndex -from ..models import CustomMenu, DynamicRoute, Notification, PDFFile, Person, TaskUserAssignment +from ..models import CustomMenu, DynamicRoute, Notification, PDFFile, Person, TaskUserAssignment, Room from ..util.apps import AppConfig from ..util.core_helpers import get_allowed_object_ids, get_app_module, get_app_packages, has_person from .celery_progress import CeleryProgressFetchedMutation, CeleryProgressType @@ -21,6 +21,7 @@ from .message import MessageType from .notification import MarkNotificationReadMutation, NotificationType from .pdf import PDFFileType from .person import PersonMutation, PersonType +from .room import RoomType, RoomBatchPatchMutation, RoomCreateMutation from .school_term import SchoolTermType # noqa from .search import SearchResultType from .system_properties import SystemPropertiesType @@ -59,6 +60,9 @@ class Query(graphene.ObjectType): two_factor = graphene.Field(TwoFactorType) + rooms = graphene.List(RoomType) + room_by_id = graphene.Field(RoomType, id=graphene.ID()) + def resolve_ping(root, info, payload) -> str: return payload @@ -157,6 +161,20 @@ class Query(graphene.ObjectType): return None return info.context.user + @staticmethod + def resolve_rooms(root, info, **kwargs): + return Room.objects.all() # FIXME permissions + + @staticmethod + def resolve_room_by_id(root, info, **kwargs): + pk = kwargs.get("id") + room_object = Room.objects.get(pk=pk) + + if not info.context.user.has_perm("core.view_room_rule"): + raise PermissionDenied + + return room_object + class Mutation(graphene.ObjectType): update_person = PersonMutation.Field() @@ -165,6 +183,9 @@ class Mutation(graphene.ObjectType): celery_progress_fetched = CeleryProgressFetchedMutation.Field() + create_room = RoomCreateMutation.Field() + update_rooms = RoomBatchPatchMutation.Field() + def build_global_schema(): """Build global GraphQL schema from all apps.""" diff --git a/aleksis/core/schema/base.py b/aleksis/core/schema/base.py index e927dadcc..f100f562b 100644 --- a/aleksis/core/schema/base.py +++ b/aleksis/core/schema/base.py @@ -1,6 +1,9 @@ import graphene from graphene_django import DjangoObjectType +from django.db.models import Model +from django.contrib.contenttypes.models import ContentType + from ..util.core_helpers import queryset_rules_filter @@ -24,3 +27,41 @@ class FieldFileType(graphene.ObjectType): def resolve_absolute_url(root, info, **kwargs): return info.context.build_absolute_uri(root.url) if root else "" + + +class PermissionsTypeMixin: + """Mixin for adding permissions to a Graphene type. + + To configure the names for the permissions or to do + different permission checking, override the respective + methods `resolve_can_edit` and `resolve_can_delete` + """ + + can_edit = graphene.Boolean() + can_delete = graphene.Boolean() + + @staticmethod + def resolve_can_edit(root: Model, info, **kwargs): + content_type = ContentType.objects.get_for_model(root) + perm = f"{content_type.app_label}.edit_{content_type.model}_rule" + return info.context.user.has_perm(perm, root) + + @staticmethod + def resolve_can_delete(root: Model, info, **kwargs): + content_type = ContentType.objects.get_for_model(root) + perm = f"{content_type.app_label}.delete_{content_type.model}_rule" + return info.context.user.has_perm(perm, root) + + +class PermissionBatchPatchMixin: + class Meta: + login_required = True + + @classmethod + def check_permissions(cls, root, info, input): + # TODO: Check PERMISSIONS (or rules) + return True + + + + diff --git a/aleksis/core/schema/room.py b/aleksis/core/schema/room.py index d4f767007..d4d5c1480 100644 --- a/aleksis/core/schema/room.py +++ b/aleksis/core/schema/room.py @@ -1,9 +1,23 @@ from graphene_django import DjangoObjectType +from graphene_django_cud.mutations import DjangoCreateMutation, DjangoBatchPatchMutation +from .base import PermissionsTypeMixin, PermissionBatchPatchMixin from ..models import Room -class RoomType(DjangoObjectType): +class RoomType(PermissionsTypeMixin, DjangoObjectType): class Meta: model = Room fields = ("id", "name", "short_name") + + +class RoomCreateMutation(DjangoCreateMutation): + class Meta: + model = Room + permissions = "core.create_room" + + +class RoomBatchPatchMutation(PermissionBatchPatchMixin, DjangoBatchPatchMutation): + class Meta: + model = Room + permissions = "core.change_room" diff --git a/pyproject.toml b/pyproject.toml index 9a3318eae..3c2d76502 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,6 +127,7 @@ customidenticon = "^0.1.5" graphene-django = "^3.0.0" selenium = "^4.4.3" django-vite = "^2.0.2" +graphene-django-cud = "^0.10.0" [tool.poetry.extras] ldap = ["django-auth-ldap"] -- GitLab