示例#1
0
class ProjectFileResourceList(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self, uuid):
        project_files_schema.pop('project')
        if current_user.role == 'CLIENT':
            fil = current_user.projects.filter_by(uuid=uuid).first_or_404()
            return pagination.paginate(fil.files, schema, True)

        return pagination.paginate(
            ProjectFile.query.filter(ProjectFile.project.has(uuid=uuid)),
            schema, True)

    def post(self, uuid):
        args = xparser.parse_args(strict=True)
        if current_user.role == 'CLIENT':
            project = current_user.projects.filter_by(uuid=uuid).first_or_404()
        else:
            project = Project.query.filter_by(uuid=uuid).first_or_404()
        for file in args.files:
            data = file_upload(file)
            if data.get('error'):
                return data, 400
        for file in args.files:
            data = file_upload(file, )
            data.get('upload').save(data.get('full_path'))
            project.files.append(
                ProjectFile(attached_file=data.get('filename'),
                            description=args.description))
        return project.save(), 202
class TicketCommentResourceFile(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required]

    def post(self, uuid, pk):
        comment = TicketComment.query.filter(TicketComment.ticket.has(uuid=uuid),
                                             TicketComment.id == pk,
                                             TicketComment.user_id == current_user.id).first_or_404()
        args = xparser.parse_args(strict=True)
        data = file_upload(args.file)
        if data.get('error'):
            return data, 400
        data.get('upload').save(data.get('full_path'))
        delete_file(comment.file)
        comment.file = data.get('filename')
        comment.save()
        return marshal(comment, ticket_comment_schema), 201

    def delete(self, uuid, pk):
        comment = TicketComment.query.filter(TicketComment.ticket.has(uuid=uuid),
                                             TicketComment.id == pk,
                                             TicketComment.user_id == current_user.id).first_or_404()
        data = delete_file(comment.file)
        if data.get('message'):
            return data, 400
        return data
class TeamResourceList(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    def get(self):
        return pagination.paginate(Team, schema, True)

    def post(self):
        parser.add_argument('members',
                            required=True,
                            location='json',
                            type=list)
        args = parser.parse_args(strict=True)
        team_check = {'errors': {}}
        if Team.query.filter_by(name=args.name).first():
            team_check.get('errors').update({'name': 'Name already exist'})
        for i in args.members:
            if not User.query.filter_by(role='TEAM_MEMBER', id=i).first():
                team_check.get('errors').update(
                    {'members':
                     'Cant find some users with role TEAM_MEMBER'}), 400
        if team_check.get('errors'):
            return team_check, 400
        team = Team()
        for i in args.members:
            team.members.append(TeamMember(user_id=i))
        request.json.pop('members')
        obj = schema.load(data=request.json,
                          unknown='exclude',
                          instance=team,
                          session=db.session)
        return obj.save(**args)
示例#4
0
class KycUploadResource(Resource):
    method_decorators = [roles_required(['CLIENT']), jwt_required]
    file_parser = RequestParser(bundle_errors=True)

    # @ns_kyc.marshal_with(mschema)
    def post(self):
        doc = current_user.kyc_doc.status if current_user.kyc_doc else abort(
            404)
        if doc != 'Pending':
            return {
                'message': 'You cant update kyc when not in pending state'
            }, 400
        KycUploadResource.file_parser.add_argument(
            'file',
            required=True,
            location='files',
            type=werkzeug.datastructures.FileStorage)
        args = KycUploadResource.file_parser.parse_args(strict=True)
        kyc = current_user.kyc_doc
        if kyc.file:
            delete_file(kyc.file)
        file = file_upload(args.file)
        if file.get('error'):
            return file, 400
        file.get('upload').save(file.get('full_path'))
        args.update({
            'file':
            url_for('api.protected_dir',
                    filename=file.get('filename'),
                    _external=True)
        })
        kyc.file = file.get('filename')
        return kyc.save(**args), 200
class UserResource(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    @ns_user.marshal_with(user_schema, envelope='data')
    def get(self, pk):
        return User.query.filter(User.id == pk,
                                 User.role != 'ADMIN').first_or_404()

    def put(self, pk):
        user = User.query.filter(User.id == pk,
                                 User.role != 'ADMIN').first_or_404()
        args = parser.parse_args(strict=True)
        check_mail = User.query.filter(User.email == args.email,
                                       User.id != user.id).first()
        check_username = User.query.filter(User.username == args.username,
                                           User.id != user.id).first()
        r = {'errors': {}}
        if check_username:
            r.get('errors').update({'username': '******'})
        if check_mail:
            r.get('errors').update(
                {'email_address': 'email address already exist'})
        if r.get('errors'):
            return r, 400
        user = schema.load(data=request.json,
                           instance=user,
                           session=db.session,
                           unknown='exclude')
        return user.save(**args), 200

    def delete(self, pk):
        user = User.query.filter(User.id == pk,
                                 User.role != 'ADMIN').first_or_404()
        return user.delete(), 202
示例#6
0
class TicketResource(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self, pk):
        if current_user.role == 'CLIENT':
            return schema.dump(
                Ticket.query.filter(
                    Ticket.project.has(user_id=current_user.id),
                    Ticket.id == pk).first_or_404())
        return schema.dump(Ticket.query.get_or_404(pk))

    def put(self, pk):
        parser.parse_args(strict=True)
        ticket = Ticket.query.get_or_404(pk)
        obj = schema.load(data=request.json,
                          session=db.session,
                          unknown='exclude',
                          instance=ticket)
        obj.save()
        return schema.dump(obj)

    def delete(self, pk):
        ticket = Ticket.query.get_or_404(pk)
        return ticket.delete(), 202
示例#7
0
class KYCResource(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER']), jwt_required]

    @ns_kyc.marshal_with(mschema)
    def get(self, pk):
        obj = Kyc.query.get_or_404(pk)
        return obj

    def put(self, pk):
        put_parser = RequestParser(trim=True, bundle_errors=True)
        put_parser.add_argument('status',
                                required=True,
                                location='json',
                                type=str,
                                choices=[
                                    'Approved', 'Pending', 'Disapproved',
                                    'Suspended', 'Processing'
                                ])
        args = put_parser.parse_args(strict=True)
        kyc = Kyc.query.get_or_404(pk)
        kyc.status = args.status
        return kyc.save(**args)

    def delete(self, pk):
        kyc = Kyc.query.get_or_404(pk)
        return kyc.delete(), 202
示例#8
0
class ProjectFileResource(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    @ns_proj_files.marshal_with(project_files_schema, envelope='data')
    def get(self, uuid, pk):
        if current_user.role == 'CLIENT':
            project = current_user.projects.filter_by(uuid=uuid).first_or_404()
            return project.files.filter_by(id=pk).first_or_404()
        proj = Project.query.filter_by(uuid=uuid).first_or_404()
        return proj.files.filter_by(id=pk).first_or_404()

    def delete(self, uuid, pk):
        if current_user.role == 'CLIENT':
            project = current_user.projects.filter_by(uuid=uuid).first_or_404()
            file = project.files.filter_by(id=pk).first_or_404()
            delete_file(file.attached_file)
            return file.delete(), 202
        proj = Project.query.filter_by(uuid=uuid).first_or_404()
        file = proj.files.filter_by(id=pk).first_or_404()
        data = delete_file(file.attached_file)
        if data.get('message'):
            return data, 400
        return data, 202
class ProtectedDirResource(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT', 'TEAM_MEMBER']),
        jwt_required
    ]

    def get(self, filename):
        return send_from_directory(os.path.join(current_app.root_path,
                                                'static', 'protected'),
                                   filename=filename)
class TaskResourceList(Resource):
    method_decorators = [roles_required(['ADMIN', 'TEAM_MEMBER']), jwt_required]

    def get(self):
        return pagination.paginate(Task, schema, True)

    def post(self):
        args = parser.parse_args(strict=True)
        task = Task(**args)
        task.save()
        return schema.dump(task), 201
示例#11
0
class NotificationResourceList(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER']), jwt_required]

    def get(self):
        return pagination.paginate(Notification, schema, True)

    def post(self):
        args = parser.parse_args(strict=True)
        notification = Notification(**args)
        args.update({'schedule_at': str(args.schedule_at)})
        return notification.save(**args), 201
class TagResourceList(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    def get(self):
        return pagination.paginate(Tag, schema, True)

    def post(self):
        args = parser.parse_args(strict=True)
        if Tag.query.filter(Tag.name == args.name).first():
            return {'message': 'Tag name already exist'}
        tag = Tag(**args)
        return tag.save(**args), 201
class TicketCommentResourceList(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required]

    def get(self, uuid):
        return pagination.paginate(TicketComment.query.filter(TicketComment.ticket.has(uuid=uuid)), schema, True)

    def post(self, uuid):
        args = parser.parse_args(strict=True)
        ticket = Ticket.query.filter_by(uuid=uuid).first_or_404()
        args.update({'user_id': current_user.id})
        ticket.comments.append(TicketComment(**args, ))
        ticket.save(**args), 201
        return TicketSchema().dump(ticket)
class TaskResource(Resource):
    method_decorators = [roles_required(['ADMIN', 'TEAM_MEMBER']), jwt_required]

    def get(self, pk):
        return schema.dump(Task.query.get_or_404(pk))

    def put(self, pk):
        parser.parse_args(strict=True)
        task = Task.query.get_or_404(pk)
        obj = schema.load(data=request.json, instance=task, session=db.session, unknown='exclude')
        obj.save()
        return schema.dump(obj)

    def delete(self, pk):
        task = Task.query.get_or_404(pk)
        return task.delete(), 202
示例#15
0
class ProjectCommentResourceList(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'TEAM_MEMBER']), jwt_required
    ]

    def get(self, uuid):
        return pagination.paginate(
            ProjectComment.query.filter(ProjectComment.project.has(uuid=uuid)),
            schema, True)

    def post(self, uuid):
        args = parser.parse_args(strict=True)
        project = Project.query.filter_by(uuid=uuid).first_or_404()
        project.comments.append(ProjectComment(**args,
                                               user_id=current_user.id))
        current_user.save(**args)
        return schema.dump(project.comments, many=True), 201
class TagResource(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    @ns_tag.marshal_with(tag_schema, envelope='data')
    def get(self, pk):
        return Tag.query.get_or_404(pk)

    def put(self, pk):
        args = parser.parse_args(strict=True)
        if Tag.query.filter(Tag.name == args.name, Tag.id != pk).first():
            return {'message': 'Tag name already exist'}
        tag = Tag.query.get_or_404(pk)
        etag = schema.load(data=request.json, session=db.session, unknown='exclude', instance=tag)
        return etag.save(**args), 200

    def delete(self, pk):
        tag = Tag.query.get_or_404(pk)
        return tag.delete(), 202
示例#17
0
class UserNotificationResource(Resource):
    method_decorators = [
        roles_required(['CLIENT', 'ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self):
        return pagination.paginate(current_user.notifications,
                                   notification_schema)

    def put(self):
        xparser = RequestParser(trim=True, bundle_errors=True)
        xparser.add_argument('id', type=int, location='json')
        xparser.add_argument('read', type=inputs.boolean, location='json')
        args = xparser.parse_args(strict=True)
        notify = current_user.notifications.filter_by(
            id=args.id).first_or_404()
        notify.read = True
        return notify.save(**args), 202
class UserTagResource(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    def put(self):
        par = RequestParser(trim=True, bundle_errors=True)
        par.add_argument('user', required=True, type=int, location='json')
        par.add_argument('tags', required=True, type=list, location='json')
        args = par.parse_args(strict=True)
        user = User.query.get(args.user)
        if not user:
            return {'message': 'user not found'}, 400
        user.tags = []
        for i in args.tags:
            tag = Tag.query.get(i)
            if not tag:
                return {'message': 'Tag not found'}, 400
            else:
                user.tags.append(tag)
        return user.save(**args), 200
示例#19
0
class NotificationResource(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER']), jwt_required]

    @ns_notify.marshal_with(notification_schema)
    def get(self, pk):
        return Notification.query.get_or_404(pk)

    def put(self, pk):
        args = parser.parse_args(strict=True)
        notification = Notification.query.get_or_404(pk)
        obj = schema.load(data=request.json,
                          session=db.session,
                          instance=notification,
                          unknown='exclude')
        print(obj.user_id)
        args.update({'schedule_at': str(args.schedule_at)})
        return obj.save(**args)

    def delete(self, pk):
        notification = Notification.query.get_or_404(pk)
        return notification.delete(), 202
class UserResourceList(Resource):
    method_decorators = [roles_required([
        'ADMIN',
    ]), jwt_required]

    def get(self):
        return pagination.paginate(User, schema, True)

    def post(self):
        args = parser.parse_args(strict=True)
        user = User(**args)
        pwd = secrets.token_hex(5)
        user.set_password(pwd)
        user.confirmed = True
        send_mail_rq.queue(
            NEW_ACC.format(
                username=user.username,
                password=pwd,
            ), [args.email], 'Welcome')
        return User.user_exist(args) if User.user_exist(args) else user.save(
            **args)
示例#21
0
class TicketResourceList(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self):
        if current_user.role == 'CLIENT':
            return pagination.paginate(
                Ticket.query.filter(
                    Ticket.project.has(user_id=current_user.id)), schema, True)
        return pagination.paginate(Ticket, schema, True)

    def post(self):
        parser.parse_args(strict=True)
        ticket = Ticket()
        obj = schema.load(data=request.json,
                          instance=ticket,
                          session=db.session,
                          unknown='exclude')
        obj.save()
        return schema.dump(obj), 201
示例#22
0
class ClientKYCResource(Resource):
    method_decorators = [roles_required(['CLIENT']), jwt_required]

    @ns_kyc.marshal_with(mschema)
    def get(self):
        return current_user.kyc_doc if current_user.kyc_doc else abort(404)

    def post(self):
        args = parser.parse_args(strict=True)
        if not current_user.kyc_doc:
            kyc = Kyc(**args)
            kyc.user_id = current_user.id
            return kyc.save(**args)
        return {'message': 'Resource already exist'}, 409

    def put(self):
        if current_user.kyc_doc:
            if current_user.kyc_doc.status != 'Pending':
                return {
                    'message': 'You cant update kyc when not in pending state'
                }, 400
            args = parser.parse_args(strict=True)
            kyc = schema.load(data=request.json,
                              instance=current_user.kyc_doc,
                              session=db.session,
                              unknown='exclude')
            return kyc.save(**args), 200
        else:
            return abort(404)

    def delete(self):
        doc = current_user.kyc_doc
        if doc:
            if doc.status != 'Pending':
                return {
                    'message': 'You cant update kyc when not in pending state'
                }, 400
            delete_file(doc.file)
            return doc.delete(), 202
        return abort(404)
示例#23
0
class ProjectCommentResource(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    @ns_proj_comment.marshal_with(project_comment_schema)
    def get(self, uuid, pk):
        return ProjectComment.query.filter(
            ProjectComment.id == pk,
            ProjectComment.project.has(uuid=uuid)).first_or_404()

    def put(self, uuid, pk):
        comment = ProjectComment.query.filter(
            ProjectComment.id == pk,
            ProjectComment.project.has(uuid=uuid)).first_or_404()
        parser.add_argument('hide',
                            required=False,
                            type=inputs.boolean,
                            location='json')
        parser.add_argument('user_id',
                            required=True,
                            type=int,
                            location='json')
        parser.add_argument('project_id',
                            required=True,
                            type=int,
                            location='json')

        args = parser.parse_args(strict=True)
        obj = schema.load(data=request.json,
                          session=db.session,
                          unknown='exclude',
                          instance=comment)
        return obj.save(**args)

    def delete(self, uuid, pk):
        comment = current_user.project_comments.filter(
            ProjectComment.id == pk,
            ProjectComment.project.has(uuid=uuid)).first_or_404()
        return comment.delete(), 202
class TicketCommentResource(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required]

    def get(self, uuid, pk):
        return schema.dump(TicketComment.query.filter(TicketComment.id == pk,
                                                      TicketComment.ticket.has(uuid=uuid)).first_or_404())

    def put(self, uuid, pk):
        parser.parse_args(strict=True)
        request.json.update({'ticket_id': Ticket.query.filter_by(uuid=uuid).first_or_404().id})
        comment = TicketComment.query.filter(TicketComment.id == pk,
                                             TicketComment.ticket.has(uuid=uuid)).first_or_404()
        obj = schema.load(data=request.json, session=db.session, unknown='exclude', instance=comment)
        obj.save()
        return schema.dump(obj)

    def delete(self, uuid, pk):
        comment = TicketComment.query.filter(TicketComment.ticket.has(uuid=uuid), TicketComment.id == pk,
                                             TicketComment.user_id == current_user.id).first_or_404()
        if current_user.role == 'ADMIN':
            comment = TicketComment.query.filter(TicketComment.ticket.has(uuid=uuid),
                                                 TicketComment.id == pk).first_or_404()
        return comment.delete(), 202
class TeamResource(Resource):
    method_decorators = [roles_required(['ADMIN']), jwt_required]

    @ns_team.marshal_with(team_schema, envelope='data')
    def get(self, pk):
        return Team.query.get(pk)

    def put(self, pk):
        parser.add_argument('members',
                            required=True,
                            location='json',
                            type=list)
        args = parser.parse_args(strict=True)
        team_check = {'errors': {}}
        if Team.query.filter(Team.name == args.name, Team.id != pk).first():
            team_check.get('errors').update({'name': 'Name already exist'})
        for i in args.members:
            if not User.query.filter_by(role='TEAM_MEMBER', id=i).first():
                team_check.get('errors').update(
                    {'members':
                     'Cant find some users with role TEAM_MEMBER'}), 400
        if team_check.get('errors'):
            return team_check, 400
        team = Team.query.get_or_404(pk)
        team.members.delete()
        for i in args.members:
            team.members.append(TeamMember(user_id=i))
        request.json.pop('members')
        obj = schema.load(data=request.json,
                          unknown='exclude',
                          instance=team,
                          session=db.session)
        return obj.save(**args)

    def delete(self, pk):
        team = Team.query.get_or_404(pk)
        return team.delete(), 202
示例#26
0
class ProjectCommentResourceFile(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'TEAM_MEMBER']), jwt_required
    ]

    # @roles_required(['ADMIN', 'USER', 'TEAM_MEMBER'])
    # @jwt_required
    def post(self, uuid, pk):
        comment = current_user.project_comments.filter(
            ProjectComment.id == pk,
            ProjectComment.project.has(uuid=uuid)).first_or_404()
        args = xparser.parse_args(strict=True)
        data = file_upload(args.file)
        if data.get('error'):
            return data, 400
        data.get('upload').save(data.get('full_path'))
        delete_file(comment.file)
        comment.file = data.get('filename')
        for team in comment.project.project_team:
            rq_notify_team(
                team.users, "Project Notification",
                f"A new Project file has been uploaded on <a href='{request.url}'>Comment</a>"
            )
        return comment.save(filename=comment.file, id=comment.id), 201

    # @roles_required(['ADMIN'])
    # @jwt_required
    def delete(self, uuid, pk):
        # if current_user.role != 'ADMIN':
        comment = current_user.project_comments.filter(
            ProjectComment.id == pk,
            ProjectComment.project.has(uuid=uuid)).first_or_404()
        msg = delete_file(comment.file)
        comment.file = ""
        comment.save()
        return msg, 202
class ProjectResourceList(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self):
        if current_user.role == 'CLIENT':
            return pagination.paginate(current_user.projects, schema, True)
        return pagination.paginate(current_user.projects, schema, True)

    def post(self):
        if current_user.role == 'CLIENT':
            parser.remove_argument('status')
            args = parser.parse_args(strict=True)
            if current_user.projects.filter_by(name=args.name).first():
                return {'message': 'Please project name already exist'}, 400
            current_user.projects.append(Project(**args))
            args.update({'due_date': str(args.due_date)})
            return current_user.save(**args), 201
        parser.add_argument('start_date',
                            required=True,
                            location='json',
                            type=inputs.date_from_iso8601)
        parser.add_argument('teams', required=True, type=list, location='json')
        args = parser.parse_args(strict=True)
        # args.update({'start_date': str(args.start_date)})
        # args.update({'due_date': str(args.due_date)})
        collection = []
        for team in args.teams:
            collection.append(Team.query.get(team))
        args.pop('teams')
        proj = Project(**args)
        proj.project_team = collection
        current_user.projects.append(proj)
        current_user.save(**args)
        return schema.dump(proj), 201
示例#28
0
class KYCResourceList(Resource):
    method_decorators = [roles_required(['ADMIN', 'USER']), jwt_required]

    def get(self):
        return pagination.paginate(Kyc, schema, True)
class UserProfileResource(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT', 'TEAM_MEMBER']),
        jwt_required
    ]

    def put(self, option):
        profile_parser = RequestParser(trim=True, bundle_errors=True)
        if option == 'general':
            profile_parser.add_argument('username',
                                        required=True,
                                        type=string,
                                        location='json')
            profile_parser.add_argument('full_name',
                                        required=True,
                                        type=string,
                                        location='json')
            profile_parser.add_argument('gender',
                                        required=True,
                                        type=str,
                                        choices=['Male', 'Female', 'Others'],
                                        help='Gender is required',
                                        location='json')
            args = profile_parser.parse_args(strict=True)
            if User.query.filter(User.username == args.username,
                                 User.id != current_user.id).first():
                return {
                    'message':
                    'Username already exist, please use different one'
                }, 400
            current_user.full_name = args.full_name
            current_user.gender = args.gender
            return current_user.save(**args)

        if option == 'pwd':
            profile_parser.add_argument('old_pwd',
                                        required=True,
                                        type=str,
                                        location='json')
            profile_parser.add_argument(
                'new_pwd',
                type=inputs.regex('[A-Za-z0-9@#$%^&+=]{8,}'),
                required=True,
                location='json',
                help='Password must have a minimum of eight characters.')
            profile_parser.add_argument(
                'confirm_pwd',
                type=inputs.regex('[A-Za-z0-9@#$%^&+=]{8,}'),
                required=True,
                location='json',
                help='Password must have a minimum of eight characters.')
            args = profile_parser.parse_args(strict=True)
            if not bcrypt.check_password_hash(current_user.password,
                                              args.old_pwd):
                return {
                    'message': 'Old password doesnt match current password'
                }, 400
            if not safe_str_cmp(args.confirm_pwd, args.new_pwd):
                return {"message": 'passwords dont match'}
            current_user.password = bcrypt.generate_password_hash(
                args.new_pwd).decode()
            current_user.save()
            send_mail_rq.queue('Your password was changed!',
                               [current_user.email], 'Password Changed')
            return {'message': 'Your password has been updated successfully'}
        if option == 'email':
            profile_parser.add_argument('pwd',
                                        required=True,
                                        type=str,
                                        location='json')
            profile_parser.add_argument('old_email',
                                        required=True,
                                        type=inputs.email(),
                                        help='Email address is required',
                                        location='json')
            profile_parser.add_argument('new_email',
                                        required=True,
                                        type=inputs.email(),
                                        help='Email address is required',
                                        location='json')
            args = profile_parser.parse_args(strict=True)
            if not bcrypt.check_password_hash(current_user.password, args.pwd):
                return abort(401)
            token = current_user.create_token(
                payload={'email': args.new_email})
            url = url_for('api.auth_change_email', token=token, _external=True)
            send_mail_rq.queue(
                CHANGE_EMAIL.format(name=current_user.full_name, url=url),
                [args.new_email], 'Change Email')
            return {'message': 'Email has been sent'}
        if option == 'img':
            profile_parser.add_argument(
                'files',
                required=True,
                location='files',
                type=werkzeug.datastructures.FileStorage)
            args = profile_parser.parse_args(strict=True)
            file = img_upload(args.file)
            if file.get('message'):
                return file, 400
            current_user.img = file.get('filename')
            file.get('upload').save(file.get('full_path'))
            return current_user.save(filename=current_user.img), 201
        return abort(404)
class ProjectResource(Resource):
    method_decorators = [
        roles_required(['ADMIN', 'USER', 'CLIENT']), jwt_required
    ]

    def get(self, pk):
        if current_user.role == 'CLIENT':
            return marshal(
                current_user.projects.filter_by(id=pk).first_or_404(),
                project_schema)
        return schema.dump(Project.query.get_or_404(pk))

    def put(self, pk):
        if current_user.role == 'CLIENT':
            proj = current_user.projects.filter_by(id=pk).first_or_404()
            parser.remove_argument('status')
            args = parser.parse_args(strict=True)
            args.update({'due_date': str(args.due_date)})
            if current_user.projects.filter(Project.name == args.name,
                                            Project.id != pk).first():
                return {'message': 'Please project name already exist'}, 400
            proj = schema.load(data=request.json,
                               instance=proj,
                               unknown='exclude',
                               session=db.session)
            rq_notify.queue(
                message=
                f'Project <a href="{request.url}">Project by {current_user.full_name}</a> has been updated',
                title='Project has been updated')
            return proj.save(**args)

        parser.add_argument('start_date',
                            required=True,
                            location='json',
                            type=inputs.date_from_iso8601)
        parser.add_argument('teams', required=True, type=list, location='json')
        args = parser.parse_args(strict=True)
        args.update({'start_date': str(args.start_date)})
        args.update({'due_date': str(args.due_date)})
        proj = Project.query.get_or_404(pk)
        if Project.query.filter(Project.name == args.name,
                                Project.id != pk).first():
            return {'message': 'Please project name already exist'}, 400
        proj.project_team = []
        collection = []
        for team in args.teams:
            collection.append(Team.query.get(team))
        proj = schema.load(data=request.json,
                           instance=proj,
                           unknown='exclude',
                           session=db.session)
        proj.project_team = collection
        proj.save()
        return schema.dump(proj)

    def delete(self, pk):
        if current_user.role == 'CLIENT':
            proj = current_user.projects.filter_by(id=pk).first_or_404()
            return proj.delete(), 202
        proj = Project.query.get_or_404(pk)
        return proj.delete(), 202