예제 #1
0
    def post(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)
        # anyone who passes checking below should be an instructor or admin
        require(
            EDIT,
            user,
            title="Notifications Not Updated",
            message=
            "Sorry, your system role does not allow you to update notification settings for this user."
        )

        if not user.email:
            abort(
                400,
                title="Notifications Not Updated",
                message=
                "Sorry, you cannot update notification settings since this user does not have an email address in ComPAIR."
            )

        params = update_notification_settings_parser.parse_args()

        email_notification_method = params.get("email_notification_method")
        check_valid_email_notification_method(email_notification_method)
        user.email_notification_method = EmailNotificationMethod(
            email_notification_method)

        db.session.commit()
        on_user_notifications_update.send(
            self,
            event_name=on_user_notifications_update.name,
            user=current_user)
        return marshal(user,
                       dataformat.get_user(is_user_access_restricted(user)))
예제 #2
0
파일: users.py 프로젝트: ubc/acj-versus
def marshal_user_data(user):
    if impersonation.is_impersonating() and current_user.id == user.id:
        # when retrieving the profile of the student being impersonated,
        # don't include full profile (i.e. no email)
        return marshal(user, dataformat.get_user(False))
    elif allow(MANAGE, user) or current_user.id == user.id:
        return marshal(user, dataformat.get_full_user())
    else:
        return marshal(user, dataformat.get_user(is_user_access_restricted(user)))
예제 #3
0
파일: users.py 프로젝트: ubc/compair
def marshal_user_data(user):
    if impersonation.is_impersonating() and current_user.id == user.id:
        # when retrieving the profile of the student being impersonated,
        # don't include full profile (i.e. no email)
        return marshal(user, dataformat.get_user(False))
    elif can(MANAGE, user) or current_user.id == user.id:
        return marshal(user, dataformat.get_full_user())
    else:
        return marshal(user, dataformat.get_user(is_user_access_restricted(user)))
예제 #4
0
    def get(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)

        on_user_get.send(self,
                         event_name=on_user_get.name,
                         user=current_user,
                         data={'id': user.id})
        return marshal(user,
                       dataformat.get_user(is_user_access_restricted(user)))
예제 #5
0
    def get(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)

        on_user_get.send(
            self,
            event_name=on_user_get.name,
            user=current_user,
            data={'id': user.id}
        )
        return marshal(user, dataformat.get_user(is_user_access_restricted(user)))
예제 #6
0
    def get(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)
        require(READ, Comparison(course_id=course.id),
            title="Comparisons Unavailable",
            message="Sorry, your role in this course does not allow you to view all comparisons for this assignment.")

        restrict_user = is_user_access_restricted(current_user)
        params = assignment_users_comparison_list_parser.parse_args()

        # only get users who have at least made one comparison
        # each paginated item is a user (with a set of comparisons and self-evaluations)
        user_query = User.query \
            .join(UserCourse, and_(
                User.id == UserCourse.user_id,
                UserCourse.course_id == course.id
            )) \
            .join(Comparison, and_(
                Comparison.user_id == User.id,
                Comparison.assignment_id == assignment.id
            )) \
            .filter(and_(
                UserCourse.course_role != CourseRole.dropped,
                Comparison.completed == True
            )) \
            .group_by(User) \
            .order_by(User.lastname, User.firstname)

        self_evaluation_total = AnswerComment.query \
            .join("answer") \
            .with_entities(
                func.count(Answer.assignment_id).label('self_evaluation_count')
            ) \
            .filter(and_(
                AnswerComment.active == True,
                AnswerComment.comment_type == AnswerCommentType.self_evaluation,
                AnswerComment.draft == False,
                Answer.active == True,
                Answer.practice == False,
                Answer.draft == False,
                Answer.assignment_id == assignment.id
            ))

        comparison_total = Comparison.query \
            .with_entities(
                func.count(Comparison.assignment_id).label('comparison_count')
            ) \
            .filter(and_(
                Comparison.completed == True,
                Comparison.assignment_id == assignment.id
            ))

        if params['author']:
            user = User.get_by_uuid_or_404(params['author'])

            user_query = user_query.filter(User.id == user.id)
            self_evaluation_total = self_evaluation_total.filter(AnswerComment.user_id == user.id)
            comparison_total = comparison_total.filter(Comparison.user_id == user.id)
        elif params['group']:
            user_query = user_query.filter(UserCourse.group_name == params['group'])

            self_evaluation_total = self_evaluation_total \
                .join(UserCourse, and_(
                    AnswerComment.user_id == UserCourse.user_id,
                    UserCourse.course_id == course.id
                )) \
                .filter(UserCourse.group_name == params['group'])

            comparison_total = comparison_total \
                .join(UserCourse, and_(
                    Comparison.user_id == UserCourse.user_id,
                    UserCourse.course_id == course.id
                )) \
                .filter(UserCourse.group_name == params['group'])

        page = user_query.paginate(params['page'], params['perPage'])
        self_evaluation_total = self_evaluation_total.scalar()
        comparison_total = comparison_total.scalar()

        comparison_sets = []
        if page.total:
            user_ids = [user.id for user in page.items]

            # get all comparisons that group of users created
            comparisons = Comparison.query \
                .filter(and_(
                    Comparison.completed == True,
                    Comparison.assignment_id == assignment.id,
                    Comparison.user_id.in_(user_ids)
                )) \
                .all()

            # retrieve the answer comments
            user_comparison_answers = {}
            for comparison in comparisons:
                user_answers = user_comparison_answers.setdefault(comparison.user_id, set())
                user_answers.add(comparison.answer1_id)
                user_answers.add(comparison.answer2_id)

            conditions = []
            for user_id, answer_set in user_comparison_answers.items():
                conditions.append(and_(
                        AnswerComment.comment_type == AnswerCommentType.evaluation,
                        AnswerComment.user_id == user_id,
                        AnswerComment.answer_id.in_(list(answer_set)),
                        AnswerComment.assignment_id == assignment.id
                ))
                conditions.append(and_(
                    AnswerComment.comment_type == AnswerCommentType.self_evaluation,
                    AnswerComment.user_id == user_id,
                    AnswerComment.assignment_id == assignment.id
                ))

            answer_comments = AnswerComment.query \
                .filter(or_(*conditions)) \
                .filter_by(draft=False) \
                .all()

            # add comparison answer evaluation comments to comparison object
            for comparison in comparisons:
                comparison.answer1_feedback = [comment for comment in answer_comments if
                    comment.user_id == comparison.user_id and
                    comment.answer_id == comparison.answer1_id and
                    comment.comment_type == AnswerCommentType.evaluation
                ]

                comparison.answer2_feedback = [comment for comment in answer_comments if
                    comment.user_id == comparison.user_id and
                    comment.answer_id == comparison.answer2_id and
                    comment.comment_type == AnswerCommentType.evaluation
                ]

            for user in page.items:
                comparison_sets.append({
                    'user': user,
                    'comparisons': [comparison for comparison in comparisons if
                        comparison.user_id == user.id
                    ],
                    'self_evaluations': [comment for comment in answer_comments if
                        comment.user_id == user.id and
                        comment.comment_type == AnswerCommentType.self_evaluation
                    ]
                })


        on_assignment_users_comparisons_get.send(
            self,
            event_name=on_assignment_users_comparisons_get.name,
            user=current_user,
            course_id=course.id,
            data={'assignment_id': assignment.id}
        )

        return {"objects": marshal(comparison_sets, dataformat.get_comparison_set(restrict_user, with_user=True)),
                "comparison_total": comparison_total, "self_evaluation_total": self_evaluation_total,
                "page": page.page, "pages": page.pages, "total": page.total, "per_page": page.per_page}
예제 #7
0
    def get(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)
        require(READ, assignment,
            title="Comparisons Unavailable",
            message="Sorry, your role in this course does not allow you to view comparisons for this assignment.")

        restrict_user = is_user_access_restricted(current_user)

        # get comparisons for current user
        comparisons = Comparison.query \
            .filter(and_(
                Comparison.completed == True,
                Comparison.assignment_id == assignment.id,
                Comparison.user_id == current_user.id
            )) \
            .all()

        # get all self-evaluations and evaluation comments for current user
        answer_comments = AnswerComment.query \
            .join("answer") \
            .filter(and_(
                AnswerComment.active == True,
                AnswerComment.comment_type.in_([AnswerCommentType.self_evaluation, AnswerCommentType.evaluation]),
                AnswerComment.draft == False,
                Answer.active == True,
                Answer.draft == False,
                Answer.assignment_id == assignment.id,
                AnswerComment.user_id == current_user.id
            )) \
            .all()

        # add comparison answer evaluation comments to comparison object
        for comparison in comparisons:
            comparison.answer1_feedback = [comment for comment in answer_comments if
                comment.user_id == comparison.user_id and
                comment.answer_id == comparison.answer1_id and
                comment.comment_type == AnswerCommentType.evaluation
            ]

            comparison.answer2_feedback = [comment for comment in answer_comments if
                comment.user_id == comparison.user_id and
                comment.answer_id == comparison.answer2_id and
                comment.comment_type == AnswerCommentType.evaluation
            ]

        on_assignment_user_comparisons_get.send(
            self,
            event_name=on_assignment_user_comparisons_get.name,
            user=current_user,
            course_id=course.id,
            data={'assignment_id': assignment.id}
        )

        comparison_set = {
            'comparisons': [comparison for comparison in comparisons if
                comparison.user_id == current_user.id
            ],
            'self_evaluations': [comment for comment in answer_comments if
                comment.user_id == current_user.id and
                comment.comment_type == AnswerCommentType.self_evaluation
            ]
        }

        return marshal(comparison_set, dataformat.get_comparison_set(restrict_user, with_user=False))
예제 #8
0
    def get(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)
        require(READ, Comparison(course_id=course.id),
            title="Comparisons Unavailable",
            message="Sorry, your role in this course does not allow you to view all comparisons for this assignment.")

        restrict_user = is_user_access_restricted(current_user)
        params = assignment_users_comparison_list_parser.parse_args()

        # only get users who have at least made one comparison
        # each paginated item is a user (with a set of comparisons and self-evaluations)
        user_query = User.query \
            .join(UserCourse, and_(
                User.id == UserCourse.user_id,
                UserCourse.course_id == course.id
            )) \
            .join(Comparison, and_(
                Comparison.user_id == User.id,
                Comparison.assignment_id == assignment.id
            )) \
            .filter(and_(
                UserCourse.course_role != CourseRole.dropped,
                Comparison.completed == True
            )) \
            .group_by(User) \
            .order_by(User.lastname, User.firstname)

        self_evaluation_total = AnswerComment.query \
            .join("answer") \
            .with_entities(
                func.count(Answer.assignment_id).label('self_evaluation_count')
            ) \
            .filter(and_(
                AnswerComment.active == True,
                AnswerComment.comment_type == AnswerCommentType.self_evaluation,
                AnswerComment.draft == False,
                Answer.active == True,
                Answer.practice == False,
                Answer.draft == False,
                Answer.assignment_id == assignment.id
            ))

        comparison_total = Comparison.query \
            .with_entities(
                func.count(Comparison.assignment_id).label('comparison_count')
            ) \
            .filter(and_(
                Comparison.completed == True,
                Comparison.assignment_id == assignment.id
            ))

        if params['author']:
            user = User.get_by_uuid_or_404(params['author'])

            user_query = user_query.filter(User.id == user.id)
            self_evaluation_total = self_evaluation_total.filter(AnswerComment.user_id == user.id)
            comparison_total = comparison_total.filter(Comparison.user_id == user.id)
        elif params['group']:
            group = Group.get_active_by_uuid_or_404(params['group'])
            user_query = user_query.filter(UserCourse.group_id == group.id)

            self_evaluation_total = self_evaluation_total \
                .join(UserCourse, and_(
                    AnswerComment.user_id == UserCourse.user_id,
                    UserCourse.course_id == course.id
                )) \
                .filter(UserCourse.group_id == group.id)

            comparison_total = comparison_total \
                .join(UserCourse, and_(
                    Comparison.user_id == UserCourse.user_id,
                    UserCourse.course_id == course.id
                )) \
                .filter(UserCourse.group_id == group.id)

        page = user_query.paginate(params['page'], params['perPage'])
        self_evaluation_total = self_evaluation_total.scalar()
        comparison_total = comparison_total.scalar()

        comparison_sets = []
        if page.total:
            user_ids = [user.id for user in page.items]

            # get all comparisons that group of users created
            comparisons = Comparison.query \
                .filter(and_(
                    Comparison.completed == True,
                    Comparison.assignment_id == assignment.id,
                    Comparison.user_id.in_(user_ids)
                )) \
                .all()

            # retrieve the answer comments
            user_comparison_answers = {}
            for comparison in comparisons:
                user_answers = user_comparison_answers.setdefault(comparison.user_id, set())
                user_answers.add(comparison.answer1_id)
                user_answers.add(comparison.answer2_id)

            conditions = []
            for user_id, answer_set in user_comparison_answers.items():
                conditions.append(and_(
                        AnswerComment.comment_type == AnswerCommentType.evaluation,
                        AnswerComment.user_id == user_id,
                        AnswerComment.answer_id.in_(list(answer_set)),
                        AnswerComment.assignment_id == assignment.id
                ))
                conditions.append(and_(
                    AnswerComment.comment_type == AnswerCommentType.self_evaluation,
                    AnswerComment.user_id == user_id,
                    AnswerComment.assignment_id == assignment.id
                ))

            answer_comments = AnswerComment.query \
                .filter(or_(*conditions)) \
                .filter_by(draft=False) \
                .all()

            # add comparison answer evaluation comments to comparison object
            for comparison in comparisons:
                comparison.answer1_feedback = [comment for comment in answer_comments if
                    comment.user_id == comparison.user_id and
                    comment.answer_id == comparison.answer1_id and
                    comment.comment_type == AnswerCommentType.evaluation
                ]

                comparison.answer2_feedback = [comment for comment in answer_comments if
                    comment.user_id == comparison.user_id and
                    comment.answer_id == comparison.answer2_id and
                    comment.comment_type == AnswerCommentType.evaluation
                ]

            for user in page.items:
                comparison_sets.append({
                    'user': user,
                    'comparisons': [comparison for comparison in comparisons if
                        comparison.user_id == user.id
                    ],
                    'self_evaluations': [comment for comment in answer_comments if
                        comment.user_id == user.id and
                        comment.comment_type == AnswerCommentType.self_evaluation
                    ]
                })


        on_assignment_users_comparisons_get.send(
            self,
            event_name=on_assignment_users_comparisons_get.name,
            user=current_user,
            course_id=course.id,
            data={'assignment_id': assignment.id}
        )

        return {"objects": marshal(comparison_sets, dataformat.get_comparison_set(restrict_user, with_user=True)),
                "comparison_total": comparison_total, "self_evaluation_total": self_evaluation_total,
                "page": page.page, "pages": page.pages, "total": page.total, "per_page": page.per_page}
예제 #9
0
    def get(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)
        require(READ, assignment,
            title="Comparisons Unavailable",
            message="Sorry, your role in this course does not allow you to view comparisons for this assignment.")

        restrict_user = is_user_access_restricted(current_user)

        # get comparisons for current user
        comparisons = Comparison.query \
            .filter(and_(
                Comparison.completed == True,
                Comparison.assignment_id == assignment.id,
                Comparison.user_id == current_user.id
            )) \
            .all()

        # get all self-evaluations and evaluation comments for current user
        answer_comments = AnswerComment.query \
            .join("answer") \
            .filter(and_(
                AnswerComment.active == True,
                AnswerComment.comment_type.in_([AnswerCommentType.self_evaluation, AnswerCommentType.evaluation]),
                AnswerComment.draft == False,
                Answer.active == True,
                Answer.draft == False,
                Answer.assignment_id == assignment.id,
                AnswerComment.user_id == current_user.id
            )) \
            .all()

        # add comparison answer evaluation comments to comparison object
        for comparison in comparisons:
            comparison.answer1_feedback = [comment for comment in answer_comments if
                comment.user_id == comparison.user_id and
                comment.answer_id == comparison.answer1_id and
                comment.comment_type == AnswerCommentType.evaluation
            ]

            comparison.answer2_feedback = [comment for comment in answer_comments if
                comment.user_id == comparison.user_id and
                comment.answer_id == comparison.answer2_id and
                comment.comment_type == AnswerCommentType.evaluation
            ]

        on_assignment_user_comparisons_get.send(
            self,
            event_name=on_assignment_user_comparisons_get.name,
            user=current_user,
            course_id=course.id,
            data={'assignment_id': assignment.id}
        )

        comparison_set = {
            'comparisons': [comparison for comparison in comparisons if
                comparison.user_id == current_user.id
            ],
            'self_evaluations': [comment for comment in answer_comments if
                comment.user_id == current_user.id and
                comment.comment_type == AnswerCommentType.self_evaluation
            ]
        }

        return marshal(comparison_set, dataformat.get_comparison_set(restrict_user, with_user=False))
예제 #10
0
    def post(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)

        if is_user_access_restricted(user):
            abort(
                403,
                title="User Not Saved",
                message="Sorry, your role does not allow you to save this user."
            )

        params = existing_user_parser.parse_args()

        # make sure the user id in the url and the id matches
        if params['id'] != user_uuid:
            abort(
                400,
                title="User Not Saved",
                message=
                "The user's ID does not match the URL, which is required in order to save the user."
            )

        # only update username if user uses compair login method
        if user.uses_compair_login:
            username = params.get("username")
            if username == None:
                abort(
                    400,
                    title="User Not Saved",
                    message=
                    "A username is required. Please enter a username and try saving again."
                )
            username_exists = User.query.filter_by(username=username).first()
            if username_exists and username_exists.id != user.id:
                abort(
                    409,
                    title="User Not Saved",
                    message=
                    "Sorry, this username already exists and usernames must be unique in ComPAIR. Please enter another username and try saving again."
                )

            user.username = username
        elif allow(MANAGE, user):
            #admins can optionally set username for users without a username
            username = params.get("username")
            if username:
                username_exists = User.query.filter_by(
                    username=username).first()
                if username_exists and username_exists.id != user.id:
                    abort(
                        409,
                        title="User Not Saved",
                        message=
                        "Sorry, this username already exists and usernames must be unique in ComPAIR. Please enter another username and try saving again."
                    )
            user.username = username
        else:
            user.username = None

        if allow(MANAGE, user):
            system_role = params.get("system_role", user.system_role.value)
            check_valid_system_role(system_role)
            user.system_role = SystemRole(system_role)

        if allow(MANAGE,
                 user) or user.id == current_user.id or current_app.config.get(
                     'EXPOSE_EMAIL_TO_INSTRUCTOR', False):
            if current_user.system_role != SystemRole.student or current_app.config.get(
                    'ALLOW_STUDENT_CHANGE_EMAIL'):
                user.email = params.get("email", user.email)

            email_notification_method = params.get("email_notification_method")
            check_valid_email_notification_method(email_notification_method)
            user.email_notification_method = EmailNotificationMethod(
                email_notification_method)

        elif params.get("email") or params.get("email_notification_method"):
            abort(
                400,
                title="User Not Saved",
                message=
                "your role does not allow you to change email settings for this user."
            )

        if current_user.system_role != SystemRole.student or current_app.config.get(
                'ALLOW_STUDENT_CHANGE_STUDENT_NUMBER'):
            # only students should have student numbers
            if user.system_role == SystemRole.student:
                student_number = params.get("student_number",
                                            user.student_number)
                student_number_exists = User.query.filter_by(
                    student_number=student_number).first()
                if student_number is not None and student_number_exists and student_number_exists.id != user.id:
                    abort(
                        409,
                        title="User Not Saved",
                        message=
                        "Sorry, this student number already exists and student numbers must be unique in ComPAIR. Please enter another number and try saving again."
                    )
                else:
                    user.student_number = student_number
            else:
                user.student_number = None

        if current_user.system_role != SystemRole.student or current_app.config.get(
                'ALLOW_STUDENT_CHANGE_NAME'):
            user.firstname = params.get("firstname", user.firstname)
            user.lastname = params.get("lastname", user.lastname)

        if current_user.system_role != SystemRole.student or current_app.config.get(
                'ALLOW_STUDENT_CHANGE_DISPLAY_NAME'):
            user.displayname = params.get("displayname", user.displayname)

        model_changes = get_model_changes(user)

        try:
            db.session.commit()
            on_user_modified.send(self,
                                  event_name=on_user_modified.name,
                                  user=current_user,
                                  data={
                                      'id': user.id,
                                      'changes': model_changes
                                  })
        except exc.IntegrityError:
            db.session.rollback()
            abort(
                409,
                title="User Not Saved",
                message=
                "Sorry, this ID already exists and IDs must be unique in ComPAIR. Please try addding another user."
            )

        return marshal_user_data(user)
예제 #11
0
파일: users.py 프로젝트: ubc/acj-versus
    def post(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)

        if is_user_access_restricted(user):
            abort(403, title="User Not Saved", message="Sorry, your role does not allow you to save this user.")

        params = existing_user_parser.parse_args()

        # make sure the user id in the url and the id matches
        if params['id'] != user_uuid:
            abort(400, title="User Not Saved",
                message="The user's ID does not match the URL, which is required in order to save the user.")

        # only update username if user uses compair login method
        if user.uses_compair_login:
            username = params.get("username")
            if username == None:
                abort(400, title="User Not Saved", message="A username is required. Please enter a username and try saving again.")
            username_exists = User.query.filter_by(username=username).first()
            if username_exists and username_exists.id != user.id:
                abort(409, title="User Not Saved", message="Sorry, this username already exists and usernames must be unique in ComPAIR. Please enter another username and try saving again.")

            user.username = username
        elif allow(MANAGE, user):
            #admins can optionally set username for users without a username
            username = params.get("username")
            if username:
                username_exists = User.query.filter_by(username=username).first()
                if username_exists and username_exists.id != user.id:
                    abort(409, title="User Not Saved", message="Sorry, this username already exists and usernames must be unique in ComPAIR. Please enter another username and try saving again.")
            user.username = username
        else:
            user.username = None

        if allow(MANAGE, user):
            system_role = params.get("system_role", user.system_role.value)
            check_valid_system_role(system_role)
            user.system_role = SystemRole(system_role)

        if allow(MANAGE, user) or user.id == current_user.id or current_app.config.get('EXPOSE_EMAIL_TO_INSTRUCTOR', False):
            if current_user.system_role != SystemRole.student or current_app.config.get('ALLOW_STUDENT_CHANGE_EMAIL'):
                user.email = params.get("email", user.email)

            email_notification_method = params.get("email_notification_method")
            check_valid_email_notification_method(email_notification_method)
            user.email_notification_method = EmailNotificationMethod(email_notification_method)

        elif params.get("email") or params.get("email_notification_method"):
            abort(400, title="User Not Saved", message="your role does not allow you to change email settings for this user.")

        if current_user.system_role != SystemRole.student or current_app.config.get('ALLOW_STUDENT_CHANGE_STUDENT_NUMBER'):
            # only students should have student numbers
            if user.system_role == SystemRole.student:
                student_number = params.get("student_number", user.student_number)
                student_number_exists = User.query.filter_by(student_number=student_number).first()
                if student_number is not None and student_number_exists and student_number_exists.id != user.id:
                    abort(409, title="User Not Saved", message="Sorry, this student number already exists and student numbers must be unique in ComPAIR. Please enter another number and try saving again.")
                else:
                    user.student_number = student_number
            else:
                user.student_number = None

        if current_user.system_role != SystemRole.student or current_app.config.get('ALLOW_STUDENT_CHANGE_NAME'):
            user.firstname = params.get("firstname", user.firstname)
            user.lastname = params.get("lastname", user.lastname)

        if current_user.system_role != SystemRole.student or current_app.config.get('ALLOW_STUDENT_CHANGE_DISPLAY_NAME'):
            user.displayname = params.get("displayname", user.displayname)

        model_changes = get_model_changes(user)

        try:
            db.session.commit()
            on_user_modified.send(
                self,
                event_name=on_user_modified.name,
                user=current_user,
                data={'id': user.id, 'changes': model_changes})
        except exc.IntegrityError:
            db.session.rollback()
            abort(409, title="User Not Saved", message="Sorry, this ID already exists and IDs must be unique in ComPAIR. Please try addding another user.")

        return marshal_user_data(user)
예제 #12
0
    def get(self, course_uuid, assignment_uuid):
        course = Course.get_active_by_uuid_or_404(course_uuid)
        assignment = Assignment.get_active_by_uuid_or_404(assignment_uuid)
        require(READ, assignment)

        can_read = allow(READ, Comparison(course_id=course.id))
        restrict_user = is_user_access_restricted(current_user)

        params = answer_comparison_list_parser.parse_args()

        # each pagination entry would be one comparison set by a user for the assignment
        comparison_sets = Comparison.query \
            .with_entities(Comparison.user_id, Comparison.answer1_id, Comparison.answer2_id) \
            .filter_by(assignment_id=assignment.id, completed=True) \
            .group_by(Comparison.user_id, Comparison.answer1_id, Comparison.answer2_id)

        if not can_read:
            comparison_sets = comparison_sets.filter_by(user_id=current_user.id)
        elif params['author']:
            comparison_sets = comparison_sets.filter_by(user_uuid=params['author'])
        elif params['group']:
            subquery = User.query \
                .with_entities(User.id) \
                .join('user_courses') \
                .filter_by(group_name=params['group']) \
                .subquery()
            comparison_sets = comparison_sets.filter(Comparison.user_id.in_(subquery))

        page = comparison_sets.paginate(params['page'], params['perPage'])

        results = []

        if page.total:

            # retrieve the comparisons
            conditions = []
            for user_id, answer1_id, answer2_id in page.items:
                conditions.append(and_(
                    Comparison.user_id == user_id,
                    Comparison.answer1_id == answer1_id,
                    Comparison.answer2_id == answer2_id
                ))
            comparisons = Comparison.query \
                .options(joinedload('answer1')) \
                .options(joinedload('answer2')) \
                .options(joinedload('criterion')) \
                .filter_by(completed=True) \
                .filter(or_(*conditions)) \
                .order_by(Comparison.user_id, Comparison.created) \
                .all()

            # retrieve the answer comments
            user_comparioson_answers = {}
            for (user_id, answer1_id, answer2_id), group_set in groupby(comparisons, attrgetter('user_id', 'answer1_id', 'answer2_id')):
                user_answers = user_comparioson_answers.setdefault(user_id, set())
                user_answers.add(answer1_id)
                user_answers.add(answer2_id)

            conditions = []
            for user_id, answer_set in user_comparioson_answers.items():
                conditions.append(and_(
                        AnswerComment.user_id == user_id,
                        AnswerComment.comment_type == AnswerCommentType.evaluation,
                        AnswerComment.answer_id.in_(list(answer_set))
                ))
                conditions.append(and_(
                    AnswerComment.comment_type == AnswerCommentType.self_evaluation,
                    AnswerComment.user_id == user_id,
                    AnswerComment.assignment_id == assignment.id
                ))

            answer_comments = AnswerComment.query \
                .filter(or_(*conditions)) \
                .filter_by(draft=False) \
                .all()

            for (user_id, answer1_id, answer2_id), group_set in groupby(comparisons, attrgetter('user_id', 'answer1_id', 'answer2_id')):
                group = list(group_set)
                default = group[0]

                comparison_set = {
                    'course_uuid': default.course_uuid,
                    'assignment_uuid': default.assignment_uuid,
                    'user_uuid': default.user_uuid,

                    'comparisons': [comparison for comparison in group],
                    'answer1_uuid': default.answer1_uuid,
                    'answer2_uuid': default.answer2_uuid,
                    'answer1': default.answer1,
                    'answer2': default.answer2,

                    'user_fullname': default.user_fullname,
                    'user_displayname': default.user_displayname,
                    'user_avatar': default.user_avatar,

                    'answer1_feedback': [comment for comment in answer_comments if
                        comment.user_id == user_id and
                        comment.answer_id == default.answer1_id and
                        comment.comment_type == AnswerCommentType.evaluation
                    ],
                    'answer2_feedback': [comment for comment in answer_comments if
                        comment.user_id == user_id and
                        comment.answer_id == default.answer2_id and
                        comment.comment_type == AnswerCommentType.evaluation
                    ],
                    'self_evaluation': [comment for comment in answer_comments if
                        comment.user_id == user_id and
                        comment.comment_type == AnswerCommentType.self_evaluation
                    ],

                    'created': default.created
                }

                results.append(comparison_set)

        on_answer_comparisons_get.send(
            self,
            event_name=on_answer_comparisons_get.name,
            user=current_user,
            course_id=course.id,
            data={'assignment_id': assignment.id}
        )

        return {'objects': marshal(results, dataformat.get_comparison_set(restrict_user)), "page": page.page,
                "pages": page.pages, "total": page.total, "per_page": page.per_page}
예제 #13
0
    def post(self, user_uuid):
        user = User.get_by_uuid_or_404(user_uuid)

        if is_user_access_restricted(user):
            return {'error': "Sorry, you don't have permission for this action."}, 403

        params = existing_user_parser.parse_args()

        # make sure the user id in the url and the id matches
        if params['id'] != user_uuid:
            return {"error": "User id does not match URL."}, 400

        # only update username if user uses compair login method
        if user.uses_compair_login:
            username = params.get("username")
            if username == None:
                return {"error": "Missing required parameter: username."}, 400
            username_exists = User.query.filter_by(username=username).first()
            if username_exists and username_exists.id != user.id:
                return {"error": "This username already exists. Please pick another."}, 409

            user.username = username
        elif allow(MANAGE, user):
            #admins can optionally set username for users without a username
            username = params.get("username")
            if username:
                username_exists = User.query.filter_by(username=username).first()
                if username_exists and username_exists.id != user.id:
                    return {"error": "This username already exists. Please pick another."}, 409
            user.username = username
        else:
            user.username = None

        if allow(MANAGE, user):
            system_role = params.get("system_role", user.system_role.value)
            check_valid_system_role(system_role)
            user.system_role = SystemRole(system_role)

        # only students should have student numbers
        if user.system_role == SystemRole.student:
            student_number = params.get("student_number", user.student_number)
            student_number_exists = User.query.filter_by(student_number=student_number).first()
            if student_number is not None and student_number_exists and student_number_exists.id != user.id:
                return {"error": "This student number already exists. Please pick another."}, 409
            else:
                user.student_number = student_number
        else:
            user.student_number = None

        user.firstname = params.get("firstname", user.firstname)
        user.lastname = params.get("lastname", user.lastname)
        user.displayname = params.get("displayname", user.displayname)

        user.email = params.get("email", user.email)
        changes = get_model_changes(user)

        restrict_user = not allow(EDIT, user)

        try:
            db.session.commit()
            on_user_modified.send(
                self,
                event_name=on_user_modified.name,
                user=current_user,
                data={'id': user.id, 'changes': changes})
        except exc.IntegrityError:
            db.session.rollback()
            current_app.logger.error("Failed to edit user. Duplicate.")
            return {'error': 'A user with the same identifier already exists.'}, 409

        return marshal(user, dataformat.get_user(restrict_user))