Beispiel #1
0
    def retrieve(self, request, pk):
        """Get the user data of the requested user.

        Arguments:
        request -- request data
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the user doesn't exists
        On success:
            success -- with the user data
        """
        if int(pk) == 0:
            pk = request.user.id

        user = User.objects.get(pk=pk)

        if request.user == user or request.user.is_superuser:
            serializer = OwnUserSerializer(user, many=False)
        elif permissions.is_user_supervisor_of(request.user, user):
            serializer = UserSerializer(user, many=False)
        else:
            return response.forbidden('You are not allowed to view this users information.')

        return response.success({'user': serializer.data})
Beispiel #2
0
    def destroy(self, request, pk):
        """Delete a user.

        Arguments:
        request -- request data
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the user does not exist
        On success:
            success -- deleted message
        """
        if not request.user.is_superuser:
            return response.forbidden('You are not allowed to delete a user.')

        if int(pk) == 0:
            pk = request.user.id

        user = User.objects.get(pk=pk)

        if len(User.objects.filter(is_superuser=True)) == 1:
            return response.bad_request('There is only 1 superuser left and therefore cannot be deleted')

        user.delete()
        return response.deleted(description='Sucesfully deleted user.')
Beispiel #3
0
    def destroy(self, request, *args, **kwargs):
        """Delete an existing comment from an entry.

        Arguments:
        request -- request data
        pk -- comment ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the comment or author does not exist
            forbidden -- when the user cannot delete the assignment
        On success:
            success -- with a message that the comment was deleted

        """
        comment_id, = utils.required_typed_params(kwargs, (int, 'pk'))
        comment = Comment.objects.get(pk=comment_id)
        journal = comment.entry.node.journal

        request.user.check_can_view(journal)

        if not (request.user.is_superuser or request.user.id == comment.author.id):
            return response.forbidden(description='You are not allowed to delete this comment.')

        comment.delete()
        return response.success(description='Successfully deleted comment.')
Beispiel #4
0
    def linkable(self, request):
        """Get linkable courses.

        Gets all courses that the current user either participates in or is allowed to edit the course details of.
        A user can then link this course to Canvas.

        Arguments:
        request -- request data

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the course does not exist
            forbidden -- when the user is not in the course
        On success:
            success -- with a message that the course was deleted
        """
        if not (request.user.is_teacher or request.user.is_superuser):
            return response.forbidden(
                "You are not allowed to get linkable courses.")

        unlinked_courses = Course.objects.filter(
            participation__user=request.user.id,
            participation__role__can_edit_course_details=True)
        serializer = serialize.CourseSerializer(unlinked_courses, many=True)
        data = serializer.data
        for i, course in enumerate(data):
            data[i]['lti_couples'] = len(
                Lti_ids.objects.filter(course=course['id']))
        return response.success({'courses': data})
Beispiel #5
0
    def partial_update(self, request, *args, **kwargs):
        """Update instance details.

        Arguments:
        request -- request data
            data -- the new data for the journal

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- User not allowed to edit instance
            bad_request -- when there is invalid data in the request
        On success:
            success -- with the new instance details
        """
        if not request.user.is_superuser:
            return response.forbidden(
                'You are not allowed to edit instance details.')

        try:
            instance = Instance.objects.get(pk=1)
        except Instance.DoesNotExist:
            instance = factory.make_instance()

        req_data = request.data
        serializer = InstanceSerializer(instance, data=req_data, partial=True)
        if not serializer.is_valid():
            response.bad_request()
        serializer.save()

        return response.success({'instance': serializer.data})
Beispiel #6
0
    def partial_update(self, request, *args, **kwargs):
        """Update the preferences of a user.

        Arguments:
        request -- request data
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when the user is not superuser or pk is not the same as the logged in user
            not found -- when the user doesnt exist
            bad request -- when the data is invalid
        On success:
            success -- with the updated preferences
        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))
        if not (request.user.pk == pk or request.user.is_superuser):
            return response.forbidden('You are not allowed to change this users preferences.')

        preferences = Preferences.objects.get(user=pk)
        serializer = PreferencesSerializer(preferences, data=request.data, partial=True)

        if not serializer.is_valid():
            return response.bad_request('Invalid preference data provided.')

        serializer.save()

        return response.success({'preferences': serializer.data})
Beispiel #7
0
    def process_exception(self, request, exception):
        # Generic exception
        if isinstance(exception, VLEBadRequest):
            return response.bad_request(str(exception))

        # Django exceptions
        elif isinstance(exception, ObjectDoesNotExist):
            return response.not_found('{0} does not exist.'.format(
                str(exception).split()[0]))
        elif isinstance(exception, ValidationError):
            return response.validation_error(exception)

        # Variable exceptions
        elif isinstance(exception, VLEMissingRequiredKey):
            return response.key_error(*exception.keys)
        elif isinstance(exception, VLEMissingRequiredField):
            return response.bad_request(str(exception))
        elif isinstance(exception, VLEParamWrongType):
            return response.value_error(str(exception))

        # Permission exceptions
        elif isinstance(exception, VLEParticipationError):
            return response.forbidden(str(exception))
        elif isinstance(exception, VLEPermissionError):
            return response.forbidden(str(exception))
        elif isinstance(exception, VLEUnverifiedEmailError):
            return response.forbidden(str(exception))

        # Programming exceptions
        elif isinstance(exception, VLEProgrammingError):
            return response.internal_server_error(str(exception))
        elif isinstance(exception, SMTPAuthenticationError):
            return response.internal_server_error(
                'Mailserver is not configured correctly, please contact a server admin.'
            )

        # LTI exceptions
        elif isinstance(exception, jwt.exceptions.ExpiredSignatureError):
            return response.forbidden(
                'The LTI instance link has expired, 15 minutes have passed. Please try again.'
            )
        elif isinstance(exception, jwt.exceptions.InvalidSignatureError):
            return response.unauthorized(
                'Invalid LTI parameters given. Please retry from your LTI instance or notify a server admin.'
            )
Beispiel #8
0
    def destroy(self, request, *args, **kwargs):
        """Delete an entry and the node it belongs to.

        Arguments:
        request -- request data
        pk -- entry ID

        Returns:
        On failure:
            not found -- when the course does not exist
            unauthorized -- when the user is not logged in
            forbidden -- when the user is not in the course
        On success:
            success -- with a message that the course was deleted
        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))

        entry = Entry.objects.get(pk=pk)
        journal = entry.node.journal
        assignment = journal.assignment

        if journal.user == request.user:
            request.user.check_permission(
                'can_have_journal', assignment,
                'You are not allowed to delete entries.')
            if entry.is_graded():
                return response.forbidden(
                    'You are not allowed to delete graded entries.')
            if entry.is_locked():
                return response.forbidden(
                    'You are not allowed to delete locked entries.')
            if assignment.is_locked():
                return response.forbidden(
                    'You are not allowed to delete entries in a locked assignment.'
                )
        elif not request.user.is_superuser:
            return response.forbidden(
                'You are not allowed to delete someone else\'s entry.')
        if journal.needs_lti_link():
            return response.forbidden(journal.outdated_link_warning_msg)

        if entry.node.type != Node.ENTRYDEADLINE:
            entry.node.delete()
        entry.delete()
        return response.success(description='Successfully deleted entry.')
Beispiel #9
0
def update_lti_groups(request, jwt_params):
    user = request.user
    lti_params = decode_lti_params(jwt_params)
    if user != User.objects.get(lti_id=lti_params['user_id']):
        return response.forbidden(
            "The user specified that should be logged in according to the request is not the logged in user."
        )

    role = lti.roles_to_list(lti_params)
    course = lti.update_lti_course_if_exists(lti_params, user, role)
    if course:
        return response.success()
    else:
        return response.bad_request('Course not found')
Beispiel #10
0
    def GDPR(self, request, pk):
        """Get a zip file of all the userdata.

        Arguments:
        request -- request data
        pk -- user ID to download the files from

        Returns
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when its not a superuser nor their own data
        On success:
            success -- a zip file of all the userdata with all their files
        """
        if int(pk) == 0:
            pk = request.user.id

        user = User.objects.get(pk=pk)

        # Check the right permissions to get this users data, either be the user of the data or be an admin.
        if not (request.user.is_superuser or request.user.id == pk):
            return response.forbidden(
                'You are not allowed to view this user\'s data.')

        profile = UserSerializer(user).data
        journals = Journal.objects.filter(user=pk)
        journal_dict = {}
        for journal in journals:
            # Select the nodes of this journal but only the ones with entries.
            entry_ids = Node.objects.filter(journal=journal).exclude(
                entry__isnull=True).values_list('entry', flat=True)
            entries = Entry.objects.filter(id__in=entry_ids)
            # Serialize all entries and put them into the entries dictionary with the assignment name key.
            journal_dict.update({
                journal.assignment.name:
                EntrySerializer(entries,
                                context={
                                    'user': request.user,
                                    'comments': True
                                },
                                many=True).data
            })

        archive_path, archive_name = file_handling.compress_all_user_data(
            user, {
                'profile': profile,
                'journals': journal_dict
            })

        return response.file(archive_path, archive_name)
Beispiel #11
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing journal.

        Arguments:
        request -- request data
            data -- the new data for the journal
        pk -- journal ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the journal does not exist
            forbidden -- User not allowed to edit this journal
            unauthorized -- when the user is unauthorized to edit the journal
            bad_request -- when there is invalid data in the request
        On success:
            success -- with the new journal data

        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))
        journal = Journal.objects.get(pk=pk)

        request.user.check_can_view(journal.assignment)

        req_data = request.data
        published, = utils.optional_params(request.data, 'published')
        if published:
            request.user.check_permission('can_publish_grades',
                                          journal.assignment)
            req_data.pop('published', None)
            return self.publish(request, journal)

        bonus_points, = utils.optional_typed_params(request.data,
                                                    (float, 'bonus_points'))
        if bonus_points is not None:
            request.user.check_permission('can_grade', journal.assignment)
            req_data.pop('bonus_points', None)
            journal.bonus_points = bonus_points
            journal.save()
            lti_grade.replace_result(journal)
            return response.success(
                {'journal': JournalSerializer(journal).data})

        if not request.user.is_superuser:
            return response.forbidden(
                'You are not allowed to edit this journal.')

        return self.admin_update(request, journal)
Beispiel #12
0
def get_lti_params_from_jwt(request, jwt_params):
    """Handle the controlflow for course/assignment create, connect and select.

    Returns the data needed for the correct entry place.
    """
    user = request.user
    lti_params = decode_lti_params(jwt_params)
    if user != User.objects.get(lti_id=lti_params['user_id']):
        return response.forbidden(
            "The user specified that should be logged in according to the request is not the logged in user."
        )

    role = lti.roles_to_lti_roles(lti_params)
    # convert LTI param for True to python True
    lti_params['custom_assignment_publish'] = lti_params.get(
        'custom_assignment_publish', 'false') == 'true'

    # If the course is already created, update that course, else return new course variables
    course = lti.update_lti_course_if_exists(lti_params, user, role)
    if course is None:
        return get_new_course_response(lti_params, role)

    # If the assignment is already created, update that assignment, else return new assignment variables
    assignment = lti.update_lti_assignment_if_exists(lti_params)
    if assignment is None:
        return get_new_assignment_response(lti_params, course, role)

    # Select a journal
    if user.has_permission('can_have_journal', assignment):
        journal = lti.select_create_journal(lti_params, user, assignment)

    return response.success(
        payload={
            'params': {
                'state':
                get_finish_state(user, assignment, lti_params),
                'cID':
                course.pk,
                'aID':
                assignment.pk,
                'jID':
                journal.pk if user.
                has_permission('can_have_journal', assignment) else None,
            }
        })
Beispiel #13
0
    def list(self, request):
        """Get all users.

        Arguments:
        request -- request data

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
        On succes:
            success -- with the course data

        """
        if not request.user.is_superuser:
            return response.forbidden('Only administrators are allowed to request all user data.')

        serializer = UserSerializer(User.objects.all(), many=True)
        return response.success({'users': serializer.data})
Beispiel #14
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing journal.

        Arguments:
        request -- request data
            data -- the new data for the journal
        pk -- journal ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the journal does not exist
            forbidden -- User not allowed to edit this journal
            unauthorized -- when the user is unauthorized to edit the journal
            bad_request -- when there is invalid data in the request
        On success:
            success -- with the new journal data

        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))
        journal = Journal.objects.get(pk=pk)

        request.user.check_can_view(journal)

        published, = utils.optional_params(request.data, 'published')
        if published:
            request.user.check_permission('can_publish_grades',
                                          journal.assignment)
            return self.publish(request, journal)

        if not request.user.is_superuser:
            return response.forbidden(
                'You are not allowed to edit this journal.')

        req_data = request.data
        if 'published' in req_data:
            del req_data['published']
        serializer = JournalSerializer(journal, data=req_data, partial=True)
        if not serializer.is_valid():
            response.bad_request()
        serializer.save()

        return response.success({'journal': serializer.data})
Beispiel #15
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing comment.

        Arguments:
        request -- request data
            text -- comment text
        pk -- comment ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the comment does not exist
            forbidden -- when the user is not allowed to comment
            unauthorized -- when the user is unauthorized to edit the assignment
        On success:
            success -- with the updated comment

        """
        comment_id, = utils.required_typed_params(kwargs, (int, 'pk'))

        comment = Comment.objects.get(pk=comment_id)
        journal = comment.entry.node.journal
        assignment = journal.assignment

        request.user.check_permission('can_comment', assignment)
        request.user.check_can_view(journal)

        if not comment.can_edit(request.user):
            return response.forbidden(
                'You are not allowed to edit this comment.')

        comment.last_edited_by = request.user
        comment.save()
        text, = utils.required_params(request.data, 'text')
        serializer = CommentSerializer(comment,
                                       data={'text': text},
                                       partial=True)
        if not serializer.is_valid():
            return response.bad_request()
        serializer.save()
        return response.success({'comment': serializer.data})
Beispiel #16
0
    def retrieve(self, request, pk):
        """Get the preferences of the requested user.

        Arguments:
        request -- request data
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the user doesn't exist
        On success:
            success -- with the preferences data
        """
        pk = int(pk)
        if not (request.user.pk == pk or request.user.is_superuser):
            return response.forbidden('You are not allowed to view this users preferences.')

        preferences = Preferences.objects.get(user=pk)
        serializer = PreferencesSerializer(preferences)

        return response.success({'preferences': serializer.data})
Beispiel #17
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing user.

        Arguments:
        request -- request data
            jwt_params -- jwt params to get the lti information from
                user_id -- id of the user
                user_image -- user image
                roles -- role of the user
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when the user is not superuser or pk is not the same as the logged in user
            not found -- when the user doesnt exists
            bad request -- when the data is invalid
        On success:
            success -- with the updated user
        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))
        if pk == 0:
            pk = request.user.pk
        if not (request.user.pk == pk or request.user.is_superuser):
            return response.forbidden()

        user = User.objects.get(pk=pk)

        lti_id, user_email, user_full_name, user_image, is_teacher = get_lti_params(
            request, 'user_id', 'custom_user_email', 'custom_user_full_name',
            'custom_user_image')

        if user_image is not None:
            user.profile_picture = user_image
        if user_email:
            if User.objects.filter(email=user_email).exclude(
                    pk=user.pk).exists():
                return response.bad_request(
                    '{} is taken by another account. Link to that account or contact support.'
                    .format(user_email))

            user.email = user_email
            user.verified_email = True
        if user_full_name is not None:
            user.full_name = user_full_name
        if is_teacher:
            user.is_teacher = is_teacher

        if lti_id is not None:
            if User.objects.filter(lti_id=lti_id).exists():
                return response.bad_request(
                    'User with this lti id already exists.')
            elif (bool(lti_id) and not bool(user_email)
                  and user_full_name == settings.LTI_TEST_STUDENT_FULL_NAME
                  or user.is_test_student):
                return response.forbidden(
                    'You are not allowed to link a test account to an existing account.'
                )
            user.lti_id = lti_id

        user.save()
        if user.lti_id is not None:
            pp, = utils.optional_params(request.data, 'profile_picture')
            data = {'profile_picture': pp if pp else user.profile_picture}
        else:
            data = request.data
        serializer = OwnUserSerializer(user, data=data, partial=True)
        if not serializer.is_valid():
            return response.bad_request()
        serializer.save()
        return response.success({'user': serializer.data})
Beispiel #18
0
    def create(self, request):
        """Create a new entry.

        Deletes remaining temporary user files if successful.

        Arguments:
        request -- the request that was send with
            journal_id -- the journal id
            template_id -- the template id to create the entry with
            node_id -- optional: the node to bind the entry to (only for entrydeadlines)
            content -- the list of {tag, data} tuples to bind data to a template field.
        """
        journal_id, template_id, content_list = utils.required_params(
            request.data, "journal_id", "template_id", "content")
        node_id, = utils.optional_params(request.data, "node_id")

        journal = Journal.objects.get(pk=journal_id, user=request.user)
        assignment = journal.assignment
        template = Template.objects.get(pk=template_id)

        request.user.check_permission('can_have_journal', assignment)

        if assignment.is_locked():
            return response.forbidden(
                'The assignment is locked, entries can no longer be edited/changed.'
            )

        if journal.needs_lti_link():
            return response.forbidden(journal.outdated_link_warning_msg)

        # Check if the template is available
        if not (node_id or assignment.format.template_set.filter(
                archived=False, preset_only=False, pk=template.pk).exists()):
            return response.forbidden('Entry template is not available.')

        entry_utils.check_fields(template, content_list)

        # Node specific entry
        if node_id:
            node = Node.objects.get(pk=node_id, journal=journal)
            entry = entry_utils.add_entry_to_node(node, template)
        # Template specific entry
        else:
            entry = factory.make_entry(template)
            node = factory.make_node(journal, entry)

        for content in content_list:
            field_id, = utils.required_typed_params(content, (int, 'id'))
            data, = utils.required_params(content, 'data')
            field = Field.objects.get(pk=field_id)

            created_content = factory.make_content(node.entry, data, field)

            if field.type in field.FILE_TYPES:  # Image, file or PDF
                user_file = file_handling.get_temp_user_file(
                    request.user, assignment, content['data'])
                if user_file is None and field.required:
                    node.entry.delete()
                    # If there is a newly created node, delete that as well
                    if not node_id:
                        node.delete()
                    return response.bad_request(
                        'One of your files was not correctly uploaded, please try again.'
                    )
                elif user_file:
                    file_handling.make_permanent_file_content(
                        user_file, created_content, node)

        # Notify teacher on new entry
        if (node.journal.sourcedid
                and node.entry.vle_coupling == Entry.NEED_SUBMISSION):
            lti_tasks.needs_grading.delay(node.pk)

        # Delete old user files
        file_handling.remove_temp_user_files(request.user)

        return response.created({
            'added':
            entry_utils.get_node_index(journal, node, request.user),
            'nodes':
            timeline.get_nodes(journal, request.user),
            'entry':
            serialize.EntrySerializer(entry, context={
                'user': request.user
            }).data
        })
Beispiel #19
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing entry.

        Arguments:
        request -- request data
            data -- the new data for the course
        pk -- assignment ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the entry does not exist
            forbidden -- User not allowed to edit this entry
            unauthorized -- when the user is unauthorized to edit the entry
            bad_request -- when there is invalid data in the request
        On success:
            success -- with the new entry data

        """
        content_list, = utils.required_typed_params(request.data,
                                                    (list, 'content'))
        entry_id, = utils.required_typed_params(kwargs, (int, 'pk'))
        entry = Entry.objects.get(pk=entry_id)
        graded = entry.is_graded()
        journal = entry.node.journal
        assignment = journal.assignment

        if assignment.is_locked():
            return response.forbidden(
                'The assignment is locked, entries can no longer be edited/changed.'
            )
        request.user.check_permission('can_have_journal', assignment)
        if not (journal.user == request.user or request.user.is_superuser):
            return response.forbidden(
                'You are not allowed to edit someone else\'s entry.')
        if graded:
            return response.bad_request(
                'You are not allowed to edit graded entries.')
        if entry.is_locked():
            return response.bad_request(
                'You are not allowed to edit locked entries.')
        if journal.needs_lti_link():
            return response.forbidden(journal.outdated_link_warning_msg)

        # Check for required fields
        entry_utils.check_fields(entry.template, content_list)

        # Attempt to edit the entries content.
        for content in content_list:
            field_id, = utils.required_typed_params(content, (int, 'id'))
            data, = utils.required_params(content, 'data')
            field = Field.objects.get(pk=field_id)

            old_content = entry.content_set.filter(field=field)
            if old_content.exists():
                old_content = old_content.first()
                if old_content.field.pk != field_id:
                    return response.bad_request(
                        'The given content does not match the accompanying field type.'
                    )
                if not data:
                    old_content.delete()
                    continue

                entry_utils.patch_entry_content(request.user, entry,
                                                old_content, field, data,
                                                assignment)
            # If there was no content in this field before, create new content with the new data.
            # This can happen with non-required fields, or when the given data is deleted.
            else:
                factory.make_content(entry, data, field)

        file_handling.remove_temp_user_files(request.user)

        return response.success({
            'entry':
            serialize.EntrySerializer(entry, context={
                'user': request.user
            }).data
        })
Beispiel #20
0
    def partial_update(self, request, *args, **kwargs):
        """Update an existing user.

        Arguments:
        request -- request data
            jwt_params -- jwt params to get the lti information from
                user_id -- id of the user
                user_image -- user image
                roles -- role of the user
        pk -- user ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when the user is not superuser or pk is not the same as the logged in user
            not found -- when the user doesnt exists
            bad request -- when the data is invalid
        On success:
            success -- with the updated user
        """
        pk, = utils.required_typed_params(kwargs, (int, 'pk'))
        if pk == 0:
            pk = request.user.pk
        if not (request.user.pk == pk or request.user.is_superuser):
            return response.forbidden()

        user = User.objects.get(pk=pk)

        lti_id, user_email, user_full_name, user_image, is_teacher = get_lti_params(
            request, 'user_id', 'custom_user_email', 'custom_user_full_name', 'custom_user_image')

        if user_image is not None:
            user.profile_picture = user_image
        if user_email is not None:
            user.email = user_email
            user.verified_email = True
        if user_full_name is not None:
            user.first_name, user.last_name = lti.split_fullname(user_full_name)
        if is_teacher:
            user.is_teacher = is_teacher

        if lti_id is not None:
            if User.objects.filter(lti_id=lti_id).exists():
                return response.bad_request('User with this lti id already exists.')
            user.lti_id = lti_id

        user.save()
        if user.lti_id is not None:
            gn, cn, pp = utils.optional_params(
                request.data, 'grade_notifications', 'comment_notifications', 'profile_picture')
            data = {
                'grade_notifications': gn if gn else user.grade_notifications,
                'comment_notifications': cn if cn else user.comment_notifications,
                'profile_picture': pp if pp else user.profile_picture
            }
        else:
            data = request.data
        serializer = OwnUserSerializer(user, data=data, partial=True)
        if not serializer.is_valid():
            return response.bad_request()
        serializer.save()
        return response.success({'user': serializer.data})