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)
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
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
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
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
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
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
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
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)
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
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)
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
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
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