def student_reputation(req): args = get_json_params(req, args=["id"]) if isinstance(args, HttpResponse): return args (student_id, ), __ = args if req.user.student.pk != student_id: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=( "Access to reputation of student {} from student {}.".format( student_id, req.user.student.pk)), log=logger.warning, ) try: student = Student.objects.get(pk=student_id) except Student.DoesNotExist: return response_400( req, msg=_("This student doesn't exist."), logger_msg=( "Tried to obtain student with pk {}".format(student_id)), log=logger.warning, ) if student.reputation is None: student.reputation = Reputation.create(student) student.save() reputation, reputations = student.reputation.evaluate() data = {"reputation": reputation, "reputations": reputations} return JsonResponse(data, status=200)
def wrapper(req, *args, **kwargs): if not isinstance(req.user, User): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non teacher user.".format( req.path)), log=logger.warning, ) if req.user.is_staff: return fct(req, *args, **kwargs) else: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non teacher user.".format( req.path)), log=logger.warning, )
def wrapper(req, *args, **kwargs): if not isinstance(req.user, User) or hasattr(req.user, "student"): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from student {}.".format( req.path, req.user)), log=logger.warning, ) return fct(req, *args, **kwargs)
def wrapper(req, *args, **kwargs): if not Teacher.objects.filter(user=req.user).exists(): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non teacher user.".format( req.path)), log=logger.warning, ) return fct(req, *args, **kwargs)
def wrapper(req, *args, **kwargs): if not isinstance(req.user, User): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non teacher user.".format( req.path)), log=logger.warning, ) try: teacher = Teacher.objects.get(user=req.user) return fct(req, *args, teacher=teacher, **kwargs) except Teacher.DoesNotExist: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non teacher user.".format( req.path)), log=logger.warning, )
def wrapper(req, *args, **kwargs): if not isinstance(req.user, User): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from a non student user.".format( req.path)), log=logger.warning, ) try: student = Student.objects.get(student=req.user) return fct(req, *args, student=student, **kwargs) except Student.DoesNotExist: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} with a non student user.".format( req.path)), log=logger.warning, )
def wrapper(req, *args, **kwargs): if not hasattr(req.user, "student"): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} with a non student user.".format( req.path)), log=logger.warning, ) return fct(req, *args, **kwargs)
def wrapper(req, *args, **kwargs): if (not isinstance(req.user, User) or Student.objects.filter(student=req.user).exists()): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from student {}.".format( req.path, req.user)), log=logger.warning, ) return fct(req, *args, **kwargs)
def verify_teacher(req, type_): """ Verifies if the teacher exists , returning it if that's the case and an error response if not. Parameters ---------- req : HttpRequest Request type_ : str Which use type it the quality for Returns ------- Either Quality Quality corresponding to the group HttpResponse 400 or 403 error response """ try: teacher = Teacher.objects.get(user=req.user) except (Teacher.DoesNotExist, AttributeError): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from user {}.".format( req.path, req.user.pk if hasattr(req, "user") and isinstance(req.user, User) else "anonymous", )), log=logger.warning, ) if teacher.quality is None: quality_type = QualityType.objects.get(type="teacher") try: quality_use_type = QualityUseType.objects.get(type=type_) except QualityUseType.DoesNotExist: return response_400( req, msg=_("Some parameters are wrong"), logger_msg=("An access to {} was tried with the wrong ".format( req.path) + "quality use type{}.".format(type_)), log=logger.warning, ) teacher.quality = Quality.objects.create( quality_type=quality_type, quality_use_type=quality_use_type) teacher.save() return teacher.quality
def test_response_403__default_message(rf, caplog): logger = logging.getLogger("test") req = rf.get("/test") req.user = AnonymousUser() resp = response_403(req, msg="test1", log=logger.warning, use_template=True) assert isinstance(resp, TemplateResponse) assert resp.status_code == 403 assert len(caplog.records) == 1 assert (caplog.records[0].message == "403 error for user AnonymousUser on path /test.")
def test_response_403(rf, caplog): logger = logging.getLogger("test") req = rf.get("/test") resp = response_403( req, msg="test1", logger_msg="test2", log=logger.warning, use_template=True, ) assert isinstance(resp, TemplateResponse) assert resp.status_code == 403 assert len(caplog.records) == 1 assert caplog.records[0].message == "test2"
def wrapper(req, *args, **kwargs): group_hash = kwargs.get("group_hash", None) assignment_hash = kwargs.get("assignment_hash", None) return_assignment = assignment_hash is not None if group_hash is None and assignment_hash is None: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=( "Access to {} without a group or assignment hash.".format( req.path)), log=logger.warning, ) try: teacher = Teacher.objects.get(user=req.user) except Teacher.DoesNotExist: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} with a non teacher user.".format( req.path)), log=logger.warning, ) if assignment_hash is not None: assignment = StudentGroupAssignment.get(assignment_hash) if assignment is None: return response_400( req, msg=_('There is no assignment with hash "{}".'.format( assignment_hash)), logger_msg=( "Access to {} with a invalid assignment hash.".format( req.path)), log=logger.warning, ) group = assignment.group else: group = StudentGroup.get(group_hash) if group is None: return response_400( req, msg=_('There is no group with hash "{}".'.format( group_hash)), logger_msg=( "Access to {} with a invalid group hash.".format( req.path)), log=logger.warning, ) if teacher not in group.teacher.all(): return response_403( req, msg=_("You don't have access to this resource. You must be " "registered as a teacher for the group {}.".format( group.name)), logger_msg=( "Invalid access to group {} from teacher {}.".format( group.pk, teacher.pk)), log=logger.warning, ) if return_assignment: return fct(req, *args, teacher=teacher, group=group, assignment=assignment, **kwargs) else: return fct(req, *args, teacher=teacher, group=group, **kwargs)
def verify_assignment(req, type_, assignment_pk): """ Verifies if the assignment exists and the user is allowed to change the assignment, returning it if that's the case and an error response if not. Parameters ---------- req : HttpRequest Request type_ : str Which use type it the quality for assignment_pk : int Primary key for the assignment Returns ------- Either Quality Quality corresponding to the assignment HttpResponse 400 or 403 error response """ try: assignment = StudentGroupAssignment.objects.get(pk=assignment_pk) except StudentGroupAssignment.DoesNotExist: return response_400( req, msg=_("Some parameters are wrong"), logger_msg=( "An access to {} was tried with the wrong ".format(req.path) + "assignment primary key {}.".format(assignment_pk)), log=logger.warning, ) try: teacher = Teacher.objects.get(user=req.user) except Teacher.DoesNotExist: return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from user {}.".format( req.path, req.user.pk)), log=logger.warning, ) if not assignment.group.teacher.filter(pk=teacher.pk).exists(): return response_403( req, msg=_("You don't have access to this resource."), logger_msg=("Access to {} from user {}.".format( req.path, req.user.pk)), log=logger.warning, ) if assignment.quality is None: quality_type = QualityType.objects.get(type="studentgroupassignment") try: quality_use_type = QualityUseType.objects.get(type=type_) except QualityUseType.DoesNotExist: return response_400( req, msg=_("Some parameters are wrong"), logger_msg=("An access to {} was tried with the wrong ".format( req.path) + "quality use type{}.".format(type_)), log=logger.warning, ) assignment.quality = Quality.objects.create( quality_type=quality_type, quality_use_type=quality_use_type) assignment.save() return assignment.quality
def request_gradebook(req, teacher): """ Request the generation of a gradebook. An response containing the task id is returned so the client can poll the server for the result until it's ready. Parameters ---------- req : HttpRequest Request with: parameters group_id: int Primary key of the group for which the gradebook is wanted optional parameters: assignment_id: int (default : None) Primary key of the assignment for which the gradebook is wanted teacher : Teacher Teacher instance returned by `teacher_required` Returns ------- Either JsonResponse with json data Response 201 (created) with json data if computation run asynchronously { task_id: str Id corresponding to the celery task for use in polling } Response 200 with json data if computation run synchronously Either If group gradebook wanted { assignments: List[str] Assignment identifier school_id_needed: bool If a school id is needed results: [{ school_id: Optional[str] School id if needed email: str Student email assignments: [{ n_completed: int Number of completed questions n_correct: int Number of correct questions }] }] } If assignment gradebook wanted { questions: List[str] Question title school_id_needed: bool If a school id is needed results: [{ school_id: Optional[str] School id if needed email: str Student email questions: List[float] Grade for each question }] } HttpResponse Error response """ args = get_json_params(req, args=["group_id"], opt_args=["assignment_id"]) if isinstance(args, HttpResponse): return args (group_pk, ), (assignment_pk, ) = args try: group = StudentGroup.objects.get(pk=group_pk) except StudentGroup.DoesNotExist: return response_400( req, msg=translate("The group doesn't exist."), logger_msg=("Access to {} with an invalid group {}.".format( req.path, group_pk)), log=logger.warning, ) if teacher not in group.teacher.all(): return response_403( req, msg=translate( "You don't have access to this resource. You must be " "registered as a teacher for the group."), logger_msg=( "Unauthorized access to group {} from teacher {}.".format( group.pk, teacher.pk)), log=logger.warning, ) if assignment_pk is not None: try: assignment = StudentGroupAssignment.objects.get(pk=assignment_pk) except StudentGroupAssignment.DoesNotExist: return response_400( req, msg=translate("The group or assignment don't exist."), logger_msg=( "Access to {} with an invalid assignment {}.".format( req.path, assignment_pk)), log=logger.warning, ) result = compute_gradebook_async(group_pk, assignment_pk) if assignment_pk is None: description = format_html("gradebook for group <strong>{}</strong>", group.name) else: description = "gradebook for assignment {} and group {}".format( assignment.assignment.identifier, group.name) if isinstance(result, AsyncResult): task = RunningTask.objects.create(id=result.id, description=description, teacher=teacher) data = { "id": task.id, "description": task.description, "completed": False, "datetime": task.datetime.strftime("%Y-%m-%d %H:%M:%S.%f"), } return JsonResponse(data, status=201) else: return download_gradebook(req, results=result)
def validate_group_data(req): """ Checks if the request is a well formed json, contains the data to get group information and the group exists. The group is obtained with either a field `group_name` or `group_link`. Returns ------- Either: StudentGroup Student and group corresponding for the request HttpResponse Response corresponding to the obtained error """ try: data = json.loads(req.body) except ValueError: return response_400( req, msg=_("Wrong data type was sent."), logger_msg=("The sent data wasn't in a valid JSON format."), log=logger.warning, ) try: group_name = data["group_name"].strip() group_link = None except KeyError: try: group_link = data["group_link"].strip() group_name = None except KeyError: return response_400( req, msg=_("There are missing parameters."), logger_msg=( "The arguments 'group_name' or 'group_link' were missing." ), log=logger.warning, ) if group_name is None: try: hash_ = re.match( rf"^{req.scheme}://[^/]+/\w*/live/signup/form/([0-9A-Za-z=_-]+)$", # noqa E501 group_link, ).group(1) except AttributeError: return response_400( req, msg=_("There pas an error parsing the sent link. Please try " "again."), logger_msg=( "A student signup was tried with the link %s.", group_link, ), log=logger.warning, ) group = StudentGroup.get(hash_) if group is None: return response_400( req, msg=_("There doesn't seem to be any group corresponding to" "the link. Please try again."), logger_msg=( "There is no group corresponding to the hash %s.", hash_, ), log=logger.warning, ) else: try: group = StudentGroup.objects.get(name=group_name) except StudentGroup.DoesNotExist: return response_403( req, msg=_("The group doesn't seem to exist. Refresh the page " "and try again"), logger_msg=( "There is no group corresponding to the name %s.", group_name, ), log=logger.warning, ) return group
def login_student(req, token=None): """ Logs in the user depending on the given token and req.user. For lti users, the student corresponding to the email is used, creating it if necessary. Parameters ---------- req : HttpRequest Request with a logged in user or not token : Optional[str] (default : None) Student token Parameters ---------- Either Student Logged in student HttpResponse Error response bool If this is a new student """ if token is None: if not isinstance(req.user, User): return ( response_403( req, msg=_("You must be a logged in student to access this " "resource."), logger_msg=( "Student index page accessed without a token or being " "logged in."), log=logger.warning, ), None, ) user = req.user username, password = get_student_username_and_password(user.email) is_lti = user.username != username else: user, is_lti = authenticate_student(req, token) if isinstance(user, HttpResponse): return user, None if is_lti: username, password = get_student_username_and_password(user.email) if is_lti: try: user = User.objects.get(username=username) except User.DoesNotExist: user = User.objects.create_user(username=username, password=password, email=user.email) try: student = Student.objects.get(student=user) new_student = False except Student.DoesNotExist: if is_lti: return ( response_403( req, msg=_("You must be a logged in student to access this " "resource."), logger_msg=( "Student index page accessed without a token or being " "logged in."), log=logger.warning, ), None, ) student = Student.objects.create(student=user) new_student = True if not user.is_active or new_student: user.is_active = True user.save() new_student = True logout(req) login(req, user, backend="peerinst.backends.CustomPermissionsBackend") return student, new_student