From fcf22fdd7345dcf6b6c896578ae4129ac8cf32ee Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 27 Feb 2023 14:49:25 +0000 Subject: [PATCH] start migrating from DRF to ninja --- anatomy/api.py | 53 +++++++++++++++++++ anatomy/templates/anatomy/view.html | 6 ++- anatomy/views.py | 28 +++++----- generic/constants.py | 7 +++ generic/decorators.py | 22 ++++++++ generic/views.py | 4 +- longs/api.py | 53 +++++++++++++++++++ longs/views.py | 6 +-- rad/api.py | 8 ++- rad/urls.py | 6 +-- rapids/api.py | 27 ++++++++-- .../rapids/question_display_block.html | 2 +- rapids/templates/rapids/view.html | 33 ++++++------ templates/question_table_view.html | 9 ++-- 14 files changed, 215 insertions(+), 49 deletions(-) create mode 100644 anatomy/api.py create mode 100644 generic/constants.py create mode 100644 longs/api.py diff --git a/anatomy/api.py b/anatomy/api.py new file mode 100644 index 00000000..2f5dd342 --- /dev/null +++ b/anatomy/api.py @@ -0,0 +1,53 @@ +from typing import List +from django.shortcuts import get_object_or_404 +from ninja import ModelSchema, Router +from .models import AnatomyQuestion as Question, Exam + +from django.core.exceptions import PermissionDenied + +from generic.decorators import check_user_in_group +from generic.constants import Group + +from ninja.security import django_auth + +router = Router() + + +class QuestionSchema(ModelSchema): + class Config: + model = Question + + #model_fields = ["question", "history", "feedback", "normal", "laterality"] + model_fields = "__all__" + + #model_exclude = ["answers"] + +class ExamSchema(ModelSchema): + class Config: + model = Exam + + model_fields = ["id", "name", "active", "publish_results"] + +@router.get('/') +def list_questions(request): + return [ + {"id": e.id, "normal": e.normal} + for e in Question.objects.all() + ] + +@router.get('/question/{question_id}', response=QuestionSchema) +@check_user_in_group(Group.cid_user_manager) +def get_rapid_details(request, question_id: int): + + rapid = get_object_or_404(Question, id=question_id) + return rapid + + +@router.get('/user_exams', response=List[ExamSchema], url_name="anatomy_user_exams") +def user_exams(request): + """Returns a list of exams that the user has access to""" + user = request.user + if user.groups.filter(name="anatomy_checker").exists(): + return Exam.objects.filter(archive=False).order_by('name') + + return Exam.objects.filter(author__id=user.id, archive=False).order_by('name') \ No newline at end of file diff --git a/anatomy/templates/anatomy/view.html b/anatomy/templates/anatomy/view.html index 6158be8d..73605f08 100755 --- a/anatomy/templates/anatomy/view.html +++ b/anatomy/templates/anatomy/view.html @@ -15,7 +15,11 @@ {% render_table table %} -
diff --git a/anatomy/views.py b/anatomy/views.py index b0cfb6f4..1f448b4e 100644 --- a/anatomy/views.py +++ b/anatomy/views.py @@ -775,20 +775,20 @@ class ExamDelete(AuthorOrCheckerRequiredMixin, ExamDeleteBase): -class ExamViewSet(RevisionMixin, viewsets.ModelViewSet): - # queryset = Exam.objects.all().order_by('name') - serializer_class = ExamSerializer - permission_classes = [permissions.IsAuthenticated] - - def get_queryset(self): - """ - This view should return a list exams available to a user. - """ - user = self.request.user - if user.groups.filter(name="anatomy_checker").exists(): - return Exam.objects.all() - - return Exam.objects.filter(author__id=user.id) +#class ExamViewSet(RevisionMixin, viewsets.ModelViewSet): +# # queryset = Exam.objects.all().order_by('name') +# serializer_class = ExamSerializer +# permission_classes = [permissions.IsAuthenticated] +# +# def get_queryset(self): +# """ +# This view should return a list exams available to a user. +# """ +# user = self.request.user +# if user.groups.filter(name="anatomy_checker").exists(): +# return Exam.objects.all() +# +# return Exam.objects.filter(author__id=user.id) class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, UpdateView): diff --git a/generic/constants.py b/generic/constants.py new file mode 100644 index 00000000..2317b460 --- /dev/null +++ b/generic/constants.py @@ -0,0 +1,7 @@ +# constants.py + +from enum import Enum +class Group(Enum): + cid_user_manager = "cid_user_manager" + marker = "marker" + anatomy_marker = "anatomy_marker" \ No newline at end of file diff --git a/generic/decorators.py b/generic/decorators.py index e486228d..b3c5ae8e 100755 --- a/generic/decorators.py +++ b/generic/decorators.py @@ -1,5 +1,9 @@ from django.core.exceptions import PermissionDenied +from django.http import Http404 +from .constants import Group + +from functools import wraps def user_is_cid_user_manager(function): def wrap(request, *args, **kwargs): @@ -14,3 +18,21 @@ def user_is_cid_user_manager(function): wrap.__doc__ = function.__doc__ wrap.__name__ = function.__name__ return wrap + + +def check_user_in_group(*groups: Group): + print("DEC") + print(groups) + + def decorator(function): + @wraps(function) + def wrapper(request, *args, **kwargs): + print(request.user) + if request.user.is_superuser or request.user.groups.filter( + name__in=[group.name for group in groups] + ).exists(): + return function(request, *args, **kwargs) + raise PermissionDenied + + return wrapper + return decorator \ No newline at end of file diff --git a/generic/views.py b/generic/views.py index 59c5835c..80c76551 100644 --- a/generic/views.py +++ b/generic/views.py @@ -195,10 +195,10 @@ def generic_exam_json_edit(request): if request.method == "POST": question_type = request.POST.get("type") - if question_type == "rapid": + if question_type == "rapids": Exam = RapidExam Question = RapidQuestion - elif question_type == "long": + elif question_type == "longs": Exam = LongExam Question = LongQuestion elif question_type == "anatomy": diff --git a/longs/api.py b/longs/api.py new file mode 100644 index 00000000..6c1bc513 --- /dev/null +++ b/longs/api.py @@ -0,0 +1,53 @@ +from typing import List +from django.shortcuts import get_object_or_404 +from ninja import ModelSchema, Router +from .models import Exam, Long as Question + +from django.core.exceptions import PermissionDenied + +from generic.decorators import check_user_in_group +from generic.constants import Group + +from ninja.security import django_auth + +router = Router() + + +class QuestionSchema(ModelSchema): + class Config: + model = Question + + #model_fields = ["question", "history", "feedback", "normal", "laterality"] + model_fields = "__all__" + + #model_exclude = ["answers"] + +class ExamSchema(ModelSchema): + class Config: + model = Exam + + model_fields = ["id", "name", "active", "publish_results"] + +@router.get('/') +def list_questions(request): + return [ + {"id": e.id, "normal": e.normal} + for e in Question.objects.all() + ] + +@router.get('/question/{question_id}', response=QuestionSchema) +@check_user_in_group(Group.cid_user_manager) +def get_rapid_details(request, question_id: int): + + rapid = get_object_or_404(Question, id=question_id) + return rapid + + +@router.get('/user_exams', response=List[ExamSchema], url_name="longs_user_exams") +def user_exams(request): + """Returns a list of exams that the user has access to""" + user = request.user + if user.groups.filter(name="long_checker").exists(): + return Exam.objects.filter(archive=False).order_by('name') + + return Exam.objects.filter(author__id=user.id, archive=False).order_by('name') \ No newline at end of file diff --git a/longs/views.py b/longs/views.py index 0b709872..3920acfe 100755 --- a/longs/views.py +++ b/longs/views.py @@ -1135,9 +1135,9 @@ class ExamAuthorUpdate(RevisionMixin, LoginRequiredMixin, AuthorRequiredMixin, U form_class = ExamAuthorForm -class ExamViewSet(RevisionMixin, viewsets.ModelViewSet): - queryset = Exam.objects.all().order_by("name") - serializer_class = ExamSerializer +#class ExamViewSet(RevisionMixin, viewsets.ModelViewSet): +# queryset = Exam.objects.all().order_by("name") +# serializer_class = ExamSerializer def question_json_unbased(request, pk): diff --git a/rad/api.py b/rad/api.py index 7dbe7524..e2c3d2f6 100644 --- a/rad/api.py +++ b/rad/api.py @@ -1,12 +1,16 @@ from ninja import NinjaAPI from rapids.api import router as rapids_router +from longs.api import router as longs_router +from anatomy.api import router as anatomy_router -api = NinjaAPI(csrf=True) +api = NinjaAPI(csrf=True, version="1") -api.add_router("/rapid/", rapids_router) +api.add_router("rapid/", rapids_router) +api.add_router("anatomy/", anatomy_router) +api.add_router("longs/", longs_router) @api.get("/hello") def hello(request): diff --git a/rad/urls.py b/rad/urls.py index d6b669a3..954e171d 100644 --- a/rad/urls.py +++ b/rad/urls.py @@ -37,9 +37,9 @@ from .api import api router_drf = routers.DefaultRouter() -router_drf.register(r"rapids/exams", rapid_views.ExamViewSet, basename="rapid-exam") -router_drf.register(r"anatomy/exams", anatomy_views.ExamViewSet, basename="anatomy-exam") -router_drf.register(r"longs/exams", long_views.ExamViewSet, basename="long-exam") +#router_drf.register(r"rapids/exams", rapid_views.ExamViewSet, basename="rapid-exam") +#router_drf.register(r"anatomy/exams", anatomy_views.ExamViewSet, basename="anatomy-exam") +#router_drf.register(r"longs/exams", long_views.ExamViewSet, basename="long-exam") router_drf.register( r"rapids/answers", rapid_views.QuestionAnswerViewSet, diff --git a/rapids/api.py b/rapids/api.py index 4065cad7..b0f4875c 100644 --- a/rapids/api.py +++ b/rapids/api.py @@ -1,10 +1,14 @@ +from typing import List from django.shortcuts import get_object_or_404 from ninja import ModelSchema, Router -from .models import Rapid +from .models import Rapid, Exam from .decorators import user_is_author_or_rapid_checker from django.core.exceptions import PermissionDenied +from generic.decorators import check_user_in_group +from generic.constants import Group + from ninja.security import django_auth router = Router() @@ -19,6 +23,11 @@ class RapidSchema(ModelSchema): #model_exclude = ["answers"] +class ExamSchema(ModelSchema): + class Config: + model = Exam + + model_fields = ["id", "name", "active", "publish_results"] @router.get('/') def list_rapids(request): @@ -28,10 +37,18 @@ def list_rapids(request): ] @router.get('/question/{question_id}', response=RapidSchema) +@check_user_in_group(Group.cid_user_manager) def get_rapid_details(request, question_id: int): - print(request.user) - #if not request.user.is_superuser: - # raise PermissionDenied rapid = get_object_or_404(Rapid, id=question_id) - return rapid \ No newline at end of file + return rapid + + +@router.get('/user_exams', response=List[ExamSchema], url_name="rapids_user_exams") +def user_exams(request): + """Returns a list of exams that the user has access to""" + user = request.user + if user.groups.filter(name="rapid_checker").exists(): + return Exam.objects.filter(archive=False).order_by('name') + + return Exam.objects.filter(author__id=user.id, archive=False).order_by('name') \ No newline at end of file diff --git a/rapids/templates/rapids/question_display_block.html b/rapids/templates/rapids/question_display_block.html index 69335e41..415da73c 100755 --- a/rapids/templates/rapids/question_display_block.html +++ b/rapids/templates/rapids/question_display_block.html @@ -34,7 +34,7 @@ {% endfor %} diff --git a/rapids/templates/rapids/view.html b/rapids/templates/rapids/view.html index efd4bd3a..2b842669 100755 --- a/rapids/templates/rapids/view.html +++ b/rapids/templates/rapids/view.html @@ -6,23 +6,26 @@ {% block content %} -
-

Filter Rapids

-
- {{ filter.form }} - -
-
-{% render_table table %} +
+

Filter Rapids

+
+ {{ filter.form }} + +
+
+ {% render_table table %} - -
+ +
- + }); + {% endblock %} \ No newline at end of file diff --git a/templates/question_table_view.html b/templates/question_table_view.html index 72f0a8d9..132d50f0 100644 --- a/templates/question_table_view.html +++ b/templates/question_table_view.html @@ -20,8 +20,11 @@ {% render_table table %} - -
+ +
{% endblock %} \ No newline at end of file