numerous supervisor upgrades

This commit is contained in:
Ross
2024-10-28 16:30:13 +00:00
parent 375261dd84
commit a2907fa285
21 changed files with 455 additions and 27 deletions
+136 -6
View File
@@ -98,12 +98,14 @@ from rapids.models import (
ExamQuestionDetail as RapidsExamQuestionDetail,
)
from rapids.models import Exam as RapidsExam
from rapids.models import UserAnswer as RapidsUserAnswer
from longs.models import (
Long as LongQuestion,
LongSeries,
ExamQuestionDetail as LongsExamQuestionDetail,
)
from longs.models import Exam as LongsExam
from longs.models import UserAnswer as LongsUserAnswer
from anatomy.models import (
AnatomyQuestion as AnatomyQuestion,
ExamQuestionDetail as AnatomyExamQuestionDetail,
@@ -113,12 +115,15 @@ from sbas.models import (
Question as SbasQuestion,
ExamQuestionDetail as SbasExamQuestionDetail,
)
from anatomy.models import UserAnswer as AnatomyUserAnswer
from sbas.models import Exam as SbasExam
from sbas.models import UserAnswer as SbasUserAnswer
from physics.models import (
Question as PhysicsQuestion,
ExamQuestionDetail as PhysicsExamQuestionDetail,
)
from physics.models import Exam as PhysicsExam
from physics.models import UserAnswer as PhysicsUserAnswer
from django.db.models import Case, When
from django.conf import settings
@@ -164,6 +169,34 @@ class CidManagerRequiredMixin(UserPassesTestMixin):
# raise PermissionDenied() # or Http404
def get_user_exams(user, supervisor_view=False):
EXAM_ANSWER_MAP = {
"physics": (PhysicsUserAnswer, PhysicsExam),
"anatomy": (AnatomyUserAnswer, AnatomyExam),
"rapids": (RapidsUserAnswer, RapidsExam),
"longs": (LongsUserAnswer, LongsExam),
"sbas": (SbasUserAnswer, SbasExam),
}
kwargs = {
"exam_mode": True,
"archive": False
}
if supervisor_view:
kwargs["results_supervisor_visible"] = True
exams = []
for exam_type in EXAM_ANSWER_MAP:
UserAnswer, Exam = EXAM_ANSWER_MAP[exam_type]
exam_answers = UserAnswer.objects.filter(user=user)
exam_ids = exam_answers.values_list("exam").distinct()
exams_to_add = Exam.objects.filter(id__in=exam_ids, **kwargs)
if exams_to_add:
exams.append((exam_type, exams_to_add))
return exams
def get_exam_model_from_app_name(app_name: str) -> ExamBase:
EXAM_MAP = {
"physics": PhysicsExam,
@@ -494,6 +527,9 @@ class ExamViews(View, LoginRequiredMixin):
if (exam.open_access and exam.active) or user in exam.get_author_objects():
return True
if exam.cid_user_exam.filter(user_user=user):
return True
if marker and user in exam.markers.all():
return True
@@ -1521,7 +1557,9 @@ class ExamViews(View, LoginRequiredMixin):
exams = self.Exam.objects.all()
filter = self.ExtraExamFilter(request.GET, queryset=exams)
else:
exams = self.Exam.objects.filter(author__id=request.user.id) | self.Exam.objects.filter(open_access=True)
exams = self.Exam.objects.filter(
author__id=request.user.id
) | self.Exam.objects.filter(open_access=True)
filter = self.BasicExamFilter(request.GET, queryset=exams)
return render(
@@ -2044,21 +2082,38 @@ class ExamViews(View, LoginRequiredMixin):
user = User.objects.get(id=user_id)
return self.exam_scores_cid_user(request, pk, user=user)
def exam_scores_user_supervisor(self, request, pk, user_id):
user = User.objects.get(id=user_id)
if not request.user.supervisor == user.userprofile.supervisor:
raise PermissionDenied
return self.exam_scores_cid_user(request, pk, user=user, supervisor=request.user)
@method_decorator(user_passes_test(lambda u: u.is_superuser))
def exam_scores_cid_user_admin(self, request, pk, cid):
user = CidUser.objects.get(cid=cid)
return self.exam_scores_cid_user(request, pk, cid, user.passcode)
def exam_scores_cid_user(self, request, pk, cid=None, passcode="", user=None):
def exam_scores_cid_user(self, request, pk, cid=None, passcode="", user=None, supervisor=None):
exam: ExamBase = get_object_or_404(self.Exam, pk=pk)
if not exam.exam_mode:
raise Http404("Packet not in exam mode")
if not exam.check_cid_user(cid, passcode, request.user):
if not self.check_user_access(request.user, pk):
# raise PermissionDenied
raise Http404("Error accessing exam")
if supervisor is None:
if not exam.check_cid_user(cid, passcode, request.user):
#TODO clear this up
# Should users be able to access results for exams they do not have access to (if they have results)?
if not self.check_user_access(request.user, pk):
# raise PermissionDenied
#if request.user.supervisor == user.userprofile.supervisor:
# pass
# check for supervisor access
raise Http404("Error accessing exam")
else:
if user is None:
raise Exception("user must be defined")
if user is not None:
request.user = user
@@ -2176,6 +2231,8 @@ class ExamViews(View, LoginRequiredMixin):
case _:
max_score = len(questions)
cid_user_exam = exam.cid_user_exam.filter(user_user=user).first()
template_context = {
"exam": exam,
"cid": cid,
@@ -2187,6 +2244,8 @@ class ExamViews(View, LoginRequiredMixin):
"max_score": max_score,
"answers_and_marks": answers_and_marks,
"view_all_results": view_all_results,
"supervisor": supervisor,
"cid_user_exam": cid_user_exam,
}
if self.normalise_score is not None:
@@ -3754,3 +3813,74 @@ class UpdateQuestionMixin(RedirectMixin, RevisionMixin, UpdateView):
if self.request.user in obj.get_author_objects():
return context
raise PermissionDenied() # or Http404
def supervisor_overview(request, pk):
supervisor = get_object_or_404(Supervisor, pk=pk)
if not request.user.supervisor == supervisor:
raise PermissionDenied()
trainees = User.objects.filter(userprofile__supervisor=supervisor)
return render(
request,
"generic/supervisor_overview.html",
{"supervisor": supervisor, "trainees": trainees},
)
def supervisor_trainee(request, pk, trainee_id):
supervisor = get_object_or_404(Supervisor, pk=pk)
if not request.user.supervisor == supervisor:
raise PermissionDenied()
# We do this to check that the supervisor can (should) see the trainee results
trainee = User.objects.get(userprofile__supervisor=supervisor, pk=trainee_id)
exams = get_user_exams(trainee, supervisor_view=True)
print(trainee)
return render(
request,
"generic/supervisor_trainee.html",
{"supervisor": supervisor, "trainee": trainee, "all_exams": exams},
)
def supervisor_request_account(request):
if request.method == "POST":
email = request.POST.get("email")
try:
validate_email(email)
except ValidationError:
return HttpResponse(f"Invalid email address ({email})")
try:
supervisor = Supervisor.objects.get(email=email)
except Supervisor.DoesNotExist:
return HttpResponse(f"Invalid email address ({email})")
if supervisor.user:
return HttpResponse(format_html("User already exists. Reset your password <a href='{}'>here</a>", reverse("password_reset")))
try:
user_account = User.objects.get(email=email)
except User.DoesNotExist:
try:
first, last = supervisor.name.split(" ", 1)
except ValueError:
first, last = supervisor.name, ""
user_account = User.objects.create_user(email=email, username=email, password=secrets.token_hex(nbytes=16), first_name=first, last_name=last)
supervisor.user = user_account
supervisor.save()
return HttpResponse(format_html("Account created, you now need to reset your password <a href='{}'>here</a>", reverse("password_reset")))
else:
return render(request, "generic/supervisor_request_account.html", {})