numerous supervisor upgrades
This commit is contained in:
+136
-6
@@ -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", {})
|
||||
|
||||
Reference in New Issue
Block a user