def get_or_delete_course(request, pk): """ permissions: admin can view/ delete any course user can get courses they are in """ user = request.user course = get_object_or_404(Course, pk=pk) if request.method == 'DELETE': if user.is_staff: course.delete() return HttpResponse(status=200) else: return HttpResponse( status=403, data={ "message": "you dont have permission to delete this course" }) elif request.method == 'GET': serializer = CourseSerializer( course, context={ 'question_context': { 'fields': ['id', 'title'], }, 'groups_context': { "fields": ["id", "name", "users"], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }) # print(serializer.data) return HttpResponse(serializer.data)
def add_or_delete_student_to_course(request, pk): """ permissions: admin can add or delete users to any course instructors can add/ delete users to courses they instruct """ uids = request.data.get('users', None) if uids is None: return HttpResponse(status=400, data={"message": 'required field: users'}) course = get_object_or_404(Course, pk=pk) users = UserProfile.objects.filter(pk__in=uids) # get all users via uids print(request) if request.method == 'POST': # TO DO add check for having add user permission for user in users: print(user) elif request.method == 'DELETE': # TO DO add check for delete user permission pass serializer = CourseSerializer( course, context={ 'question_context': { 'fields': ['id', 'title'], }, 'groups_context': { "fields": ["id", "name", "users"], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }) return HttpResponse(status=200, data=serializer.data)
def create_a_course(request): """ permissions: only admin can create a course """ fullname = request.data.get('fullname', None) shortname = request.data.get('shortname', None) if fullname and shortname: course = Course.objects.create(fullname=fullname, shortname=shortname) serializer = CourseSerializer( course, context={ 'question_context': { 'fields': ['id', 'title'], }, 'groups_context': { "fields": ["id", "name", 'users'], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }) return HttpResponse(serializer.data) else: return HttpResponse( status=400, data={"message": 'required fields: fullname and shortname'})
def create_group_to_course(request, pk): """ permissions: admin can create groups for any course instructors can create groups for courses they instruct """ course = get_object_or_404(Course, pk=pk) name = request.data.get('name', None) print(request.data) if name is None: return HttpResponse(status=400, data={"msg": "name field is requried"}) if request.method == 'POST': # try: # course.create_group(name) # course.groups.get(name=course.shortname+'_'+name).permissions.set([]) # get from request.data when tianqi can add it # except IntegrityError as e: # return HttpResponse(status=400, data={"msg": str(e)}) serializer = CourseSerializer( course, context={ 'question_context': { 'fields': ['id', 'title'], }, 'groups_context': { "fields": ["id", "name", 'users'], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }) return HttpResponse(status=200, data=serializer.data)
def destroy(self, request, pk=None): ''' DELETE /question/{id}/ permission: admin or instructor(owner) ''' question = Question.objects.get(pk=pk) if request.user.is_staff or question.author.pk == request.user.pk: question.delete() return HttpResponse(status=200) else: return HttpResponse(status=403)
def validate_quiz_questions(course_id, data, user): course = get_object_or_404(Course, pk=course_id) questions = data.get('questions', None) if questions is None: return data qids = {} for question in questions: question['mark'] = question.get('mark', 0) if question.get('id', None) is None: HttpResponse(status=400) else: qids[str(question['id'])] = question # validate questions belong to course instructor_not_course_questions = Question.objects.filter( author=user, pk__in=qids.keys()).exclude(course__id=course_id) questions_in_course = Question.objects.filter(pk__in=qids.keys(), course__id=course_id) questions = questions_in_course.union(instructor_not_course_questions) if len(questions) != len(qids): raise serializers.ValidationError({"error": "there is some questions does not belong to course and yourself"}) copy_questions = [] for question in instructor_not_course_questions: old_id = question.id new_question = copy_a_question(question, course=course_id) copy_questions.append(new_question) qids[str(old_id)]['id'] = new_question.id data['questions'] = qids.values() course.questions.add(*copy_questions) # auto add question into course return data
def get_all_quiz(request): ''' permission: login if admin return all quizzes else return quizzes they can access ''' user = request.user if user.is_staff: quizzes = Quiz.objects.all() else: quizzes = find_user_quizzes(user) serializer = QuizSerializer(quizzes, many=True, context={'exclude_fields': ['questions']}) if request.query_params.get('group', None) == 'status': return HttpResponse(status=200, data=group_quiz_by_status(serializer.data)) else: return HttpResponse(status=200, data=serializer.data)
def get_quiz_attempt_by_id(request, pk): ''' permission: has this quiz attempt or is instructor for this quiz ''' attempt = get_object_or_404(Attempt, pk=pk) data = serilizer_quiz_attempt(attempt) return HttpResponse(data)
def get_courses(request): """ permissions: admin can see all courses user can see all courses they are in """ print('get courses') if request.user.is_staff: courses = Course.objects.all() else: courses = find_user_courses(request.user) # print(courses) serializer = CourseSerializer( courses, context={ 'question_context': { 'fields': ['id', 'title'], }, 'groups_context': { "fields": ["id", "name", "users"], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }, many=True) # print(serializer.data) return HttpResponse(serializer.data)
def add_delete_users_to_group(request, course_id, group_id): """ permissions: admin can add/ delete users to any course instructor can add/ delete users to courses they instruct """ uids = request.data.get('users', None) if uids is None: return HttpResponse(status=400, data={"message": 'required field: users'}) course = get_object_or_404(Course, pk=course_id) role = get_object_or_404(Role, pk=group_id) if request.query_params.get('username', False): users = UserProfile.objects.filter(username__in=uids) else: users = UserProfile.objects.filter( pk__in=uids) # get all users via uids if request.method == 'POST': for user in users: try: UserRole.objects.create(user=user, course=course, role=role) except IntegrityError: return HttpResponse( status=403, data={"msg": "User already has a role for this course"}) # if none of the users are in a group for this course then add them all to the group print('after group set') elif request.method == 'DELETE': UserRole.objects.filter(user__in=users).delete() serializer = RoleSerializer( role, context={ "fields": ["id", "name", "users"], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } }, course=course) print(serializer) if serializer.is_valid(): print(serializer.data) else: print(serializer.errors) return HttpResponse(status=200, data=serializer.data)
def submit_quiz_attempt_by_id(request, pk): attempt = get_object_or_404(Attempt, pk=pk) for question in request.data['questions']: qid = question['id'] for response in question['responses']: rid = response['id'] if response['answer'] == '' or response['answer'] is None: break i = find_object_from_list_by_id(qid, attempt.quiz_attempts['questions']) if i == -1: return HttpResponse(status=400, data={"message": "attempt-{} has no question-{}".format(pk, qid)}) j = find_object_from_list_by_id(rid, attempt.quiz_attempts['questions'][i]['responses']) if j == -1: return HttpResponse(status=400, data={"message": "question-{} has no response-{}".format(qid, rid)}) response_data = attempt.quiz_attempts['questions'][i]['responses'][j] remain_times = left_tries(response_data['tries'], ignore_grade=False) if remain_times: response_data['tries'][-1*remain_times][0] = response['answer'] if request.data['submit']: response_object = get_object_or_404(Response, pk=response['id']) question_object = get_object_or_404(Question, pk=qid) answers = AnswerSerializer(response_object.answers.all().order_by('id'), many=True).data # monkey patch print(answers) if response_object.rtype['name'] == 'tree': question_script = question_object.variables[0].get_code() if len(question_object.variables) > 0 else '' args = { "full": False, "script": question_script + '\n' + response_object.rtype['script'] } grade, feedback = DecisionTreeAlgorithm().execute(response_object.rtype['tree'], response['answer'], args) else: grade, feedback = response_object.algorithm.execute(response['answer'], answers) response_data['tries'][-1*remain_times][1] = grade response_data['tries'][-1*remain_times][2] = (int(grade) >= int(response_object.mark)) response_data['tries'][-1*remain_times].append(feedback) else: return HttpResponse(status=400, data={"message": "no more tries are allowed"}) if request.data['submit']: update_grade(attempt.quiz_id, attempt.quiz_attempts) attempt.save() data = serilizer_quiz_attempt(attempt) return HttpResponse(status=200, data=data)
def get_quizzes_by_course_id(request, course_id): ''' permission: login return quizzes belongs to given course ''' quizzes = Quiz.objects.filter(course__id=course_id) serializer = QuizSerializer(quizzes, many=True, context={'exclude_fields': ['questions']}) return HttpResponse(status=200, data=serializer.data)
def delete_group(request, course_id, group_id): """ permissions: admin can delete groups for any course instructor can delete from courses they instruct """ course = get_object_or_404(Course, pk=course_id) group_qs = course.groups.filter(pk=group_id) if len(group_qs) == 1: group = group_qs[0] if len(group.name) >= 7 and group.name[:7] == 'COURSE_': return HttpResponse(status=403, data={"msg": "you can not delete " \ + group.name + " please delete the course responding to it"}) group.delete() return HttpResponse(status=200) else: return HttpResponse(status=400, data={"msg": "course does not have this group"})
def create_a_quiz_by_couse_id(request): ''' permission: admin/in course's group if method is POST => create a quiz in such course ''' data = request.data course_id = data.get('course', None) if course_id is None: return HttpResponse(status=400) validate_quiz_questions(course_id, data, request.user) serializer = QuizSerializer(data=data) if serializer.is_valid(): serializer.save() else: HttpResponse(status=400, data=serializer.errors) return HttpResponse(status=200, data=serializer.data)
def results(self, request, pk=None): poll = get_object_or_404(Poll, pk=pk) user = request.user if not user.is_staff and not poll.user_has_voted(user): raise PermissionDenied() return HttpResponse({ str(id): num for id, num in poll.results().values_list('id', 'votes') })
def create_quiz_attempt_by_quiz_id(request, quiz_id): ''' permission: has a group in this quiz's course TODO: check if this perm should be restricted more ''' student = request.user quiz = get_object_or_404(Quiz, pk=quiz_id) attempt = Attempt.objects.create(student=student, quiz=quiz) data = serilizer_quiz_attempt(attempt) return HttpResponse(status=200, data=data)
def list(self, request): ''' GET /question/ permission: admin or instructor ''' data, length = Question.objects.with_query(**self.request.query_params) serializer = QuestionSerializer(data, many=True) return HttpResponse({ 'status': 'success', 'questions': serializer.data, "length": length })
def partial_update(self, request, pk=None): ''' POST /question/{id}/ permission: admin or instructor(owner) ''' request.data['author'] = request.user.id question = get_object_or_404(Question, pk=pk) if not request.user.is_staff and question.author and question.author.pk != request.user.pk: return HttpResponse(status=403) response = super().partial_update(request, pk=pk) response.data = {'status': 'success', 'question': response.data} return response
def create(self, request): ''' POST /question/ permission: admin or instructor ''' courses_id = dict(request.query_params).get('courses[]', []) courses = Course.objects.filter(pk__in=courses_id) request.data['author'] = request.user.id # request.data['course'] = None serializer = QuestionSerializer(data=request.data) if serializer.is_valid(): question = serializer.save() data = QuestionSerializer(question).data for course in courses: question = copy_a_question(question, course=course.id) return HttpResponse(status=200, data={ 'status': 'success', 'question': data }) else: return HttpResponse(status=400, data=serializer.errors)
def get_or_delete_a_quiz(request, quiz_id): ''' permission: admin can get/ delete any quiz user can get a quiz they are in the course for ''' user = request.user quiz = Quiz.objects.get(pk=quiz_id) data = request.data course_id = data.get('course', quiz.course.id) course = get_object_or_404(Course, pk=course_id) role = get_object_or_404(UserRole, user=user, course=course).role overlap = role.permissions.all() if request.method == 'DELETE': perm = Permission.objects.get(codename='delete_quiz') if user.is_staff or perm in overlap: # if admin has permission to delete quizzes quiz.delete() return HttpResponse(status=200) else: return HttpResponse(status=403) elif request.method == 'GET': perm = Permission.objects.get(codename='view_quiz') context = {} if not user.is_staff and perm not in overlap: # if neither instructor or admin context['question_context'] = {'exclude_fields': ['responses', 'author', 'quizzes', 'course']} serializer = QuizSerializer(quiz, context=context) return HttpResponse(status=200, data=serializer.data) elif request.method == 'PUT': perm = Permission.objects.get(codename='change_quiz') if not user.is_staff and perm not in overlap: # if neither instructor or admin return HttpResponse(status=403) validate_quiz_questions(course_id, data, user) serializer = QuizSerializer(quiz, data=request.data, partial=False) if serializer.is_valid(): serializer.save() else: return HttpResponse(status=400, data=serializer.errors) return HttpResponse(status=200, data=QuizSerializer(quiz).data) elif request.method == 'PATCH': perm = Permission.objects.get(codename='change_quiz') if not user.is_staff and perm not in overlap: # if neither instructor or admin return HttpResponse(status=403) validate_quiz_questions(course_id, data, user) serializer = QuizSerializer(quiz, data=request.data, partial=True) if serializer.is_valid(): serializer.save() return HttpResponse(status=200, data=QuizSerializer(quiz).data)
def user_question_list(self, request, pk=None): ''' GET /userprofile/{pk}/question/ permission: admin or instructor ''' if str(request.query_params.get("exclude_course", None)) == "1": questions = Question.objects.filter(author=pk, course__id=None) else: questions = Question.objects.filter(author=pk) serializer = QuestionSerializer(questions, many=True) return HttpResponse({ 'status': 'success', 'questions': serializer.data, "length": len(serializer.data) })
def copy_or_delete_questions_to_course(request, course_id): ''' permission: instructor in course's group copy and paste questions to course ''' def validate_data(data): questions_id = data.get('questions', None) if questions_id is None or isinstance(questions_id, list) is False: raise serializers.ValidationError({ "questions": "questions field is required and questions is a list" }) return questions_id course = get_object_or_404(Course, pk=course_id) questions_id = validate_data(request.data) if request.method == 'POST': if request.user.is_staff: questions = Question.objects.filter(pk__in=questions_id).exclude( course__id=course_id) else: # TO DO add check for permission questions = Question.objects.filter( pk__in=questions_id, author=request.user).exclude(course__id=course_id) # course.questions.add(*questions) copy_questions = [copy_a_question(q) for q in questions] course.questions.add(*copy_questions) elif request.method == 'DELETE': # TO DO add check for delete permissions questions = course.questions.filter(pk__in=questions_id, author=request.user, course__id=course_id) course.questions.remove(*questions) serializer = CourseSerializer( course, context={ 'question_context': {}, 'groups_context': { "fields": ["id", "name"], "users_context": { "fields": ['id', 'username', 'first_name', 'last_name', 'email'] } } }) return HttpResponse(status=200, data=serializer.data)
def get_quizzes_attempt_by_quiz_id(request, quiz_id): ''' permission: admin sees all attempts instructor sees their courses attempts student sees their own attempts ''' student = request.user quiz = get_object_or_404(Quiz, pk=quiz_id) if request.user.is_staff: attempts = Attempt.objects.filter(quiz=quiz) else: role = get_object_or_404(UserRole, user=request.user, course=quiz.course).role perm = Permission.get(codename='view_attempt') if perm in role.permissions.all(): attempts = Attempt.objects.filter(quiz=quiz) else: attempts = Attempt.objects.filter(student=student, quiz=quiz) data = {"quiz_attempts": [serilizer_quiz_attempt(attempt) for attempt in attempts]} return HttpResponse(status=200, data=data)
def get(self, request, *args, **kwargs): #pylint:disable=unused-argument,too-many-locals self._start_time() from_root, trail = self.breadcrumbs roots = [trail[-1][0]] if trail else None self._report_queries("at rollup_scores entry point") rollup_tree = None rollups = self._cut_tree(self.build_content_tree(roots, prefix=from_root, cut=TransparentCut()), cut=TransparentCut()) for _, rollup in six.iteritems(rollups): rollup_tree = rollup break self._report_queries("rollup_tree generated") leafs = self.get_leafs(rollup_tree=rollup_tree) self._report_queries("leafs loaded") for prefix, values_tuple in six.iteritems(leafs): self.populate_leaf( prefix, values_tuple[0], get_historical_scores( includes=Sample.objects.filter(account=self.account), prefix=prefix), agg_key='last_activity_at') # Relies on # `get_historical_scores()` # to use `Sample.created_at` self._report_queries("leafs populated") populate_rollup(rollup_tree, True) self._report_queries("rollup_tree populated") # We populated the historical scores per section. # Now we need to transpose them by sample_id. accounts = {} self.flatten_distributions(rollup_tree, accounts, prefix=from_root) result = [] for account_key, account in six.iteritems(accounts): result += [{ "key": account_key.strftime("%b %Y"), "values": list(six.iteritems(account)) }] return HttpResponse(result)
def get(self, request, format=None): """ blank """ return HttpResponse("under repaire")
def retrieve(self, request, *args, **kwargs): trail = self.get_full_element_path(self.kwargs.get('path')) return HttpResponse(self.serializer_class().to_representation( {'weight': get_score_weight(trail[-1].tag)}))
def get(self, request, *args, **kwargs): #pylint:disable=unused-argument return HttpResponse(self.get_queryset())
def votes_timeseries(self, request, pk=None): if not request.user.is_staff: raise PermissionDenied() return HttpResponse(Vote.votes_per_hour(pk))
def vote(self, resquest, pk): HttpResponse({})
def update(self, request, *args, **kwargs): #pylint:disable=unused-argument partial = kwargs.pop('partial', False) serializer = self.serializer_class(data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return HttpResponse(serializer.data)