def validate_args(self): # check size if request.content_length > len(request.files) * self.util.get_config("storage.size_limit_kilo_bytes") * 1024: return False, bad_request("more than the file size limited") # check each file type for file_name in request.files: if request.files.get(file_name).filename.endswith('jpg'): continue # jpg is not considered in imghdr if imghdr.what(request.files.get(file_name)) is None: return False, bad_request("only images can be uploaded") return True, "passed"
def upload_files(self, user_id, file_type): """Handle uploaded files from http request""" try: self.__validate_upload_files() except Exception as e: self.log.error(e) return bad_request("file size or file type unsupport") file_list = [] storage = RequiredFeature("storage") for file in request.files: file_content = request.files[file] pre_file_name = file_content.filename file_suffix = pre_file_name[pre_file_name.rfind('.'):] new_file_name = self.__generate_file_name(user_id, file_type, file_suffix) self.log.debug("upload file: " + new_file_name) context = Context(file_name=new_file_name, file_type=file_type, content=file_content) context = storage.save(context) # file_name is a random name created by server, pre_file_name is the original name file_info = { "file_name": new_file_name, "pre_file_name": pre_file_name, "url": context.url } file_list.append(file_info) return {"files": file_list}
def update_team(self, kwargs): """Update existing team information :type kwargs: dict :param kwargs: a dict to store update information for team :rtype: dict :return: updated team information in a dict """ if "id" not in kwargs: return bad_request("Please choose a team to update") team = self.__get_team_by_id(kwargs["id"]) if not team: return not_found("team not exists") # avoid duplicate team with same names if "team_name" in kwargs and kwargs["team_name"] != team.name: if self.__get_team_by_name(g.hackathon.id, kwargs["team_name"]): return precondition_failed( "team with the same name exists already") self.__validate_team_permission(g.hackathon.id, team, g.user) self.db.update_object(team, name=kwargs.get("team_name", team.name), description=kwargs.get("description", team.description), git_project=kwargs.get("git_project", team.git_project), logo=kwargs.get("logo", team.logo), update_time=self.util.get_now()) return team.dic()
def post(self): args = request.get_json() if 'name' not in args: return bad_request('template name name invalid') template_name = args['name'] return expr_manager.start_expr(g.user.id, template_name, g.hackathon.name)
def update_team(self, kwargs): """Update existing team information :type kwargs: dict :param kwargs: a dict to store update information for team :rtype: dict :return: updated team information in a dict """ if "id" not in kwargs: return bad_request("Please choose a team to update") team = self.__get_team_by_id(kwargs["id"]) if not team: return not_found("team not exists") # avoid duplicate team with same names if "team_name" in kwargs and kwargs["team_name"] != team.name: if self.__get_team_by_name(g.hackathon.id, kwargs["team_name"]): return precondition_failed("team with the same name exists already") self.__validate_team_permission(g.hackathon.id, team, g.user) self.db.update_object(team, name=kwargs.get("team_name", team.name), description=kwargs.get("description", team.description), git_project=kwargs.get("git_project", team.git_project), logo=kwargs.get("logo", team.logo), update_time=self.util.get_now()) return team.dic()
def update_admin(self, args): """Update hackathon admin :returns ok() if updated successfully bad_request() if "id" not in request body not_found() if specific AdminHackathonRel not found internal_server_error() if DB exception raised """ user_hackathon_id = args.get("id", None) if not user_hackathon_id: return bad_request("invalid user_hackathon_id") user_hackathon = UserHackathon.objects(id=user_hackathon_id).first() if not user_hackathon: return not_found("admin does not exist") try: user_hackathon.update_time = self.util.get_now() if 'role' in args: user_hackathon.role = args['role'] if 'remark' in args: user_hackathon.remark = args['remark'] user_hackathon.save() return ok('update hackathon admin successfully') except Exception as e: self.log.error(e) return internal_server_error(e)
def delete_registration(self, args): """ Delete the registration of a user in a hackathon, also do operation on the user's team. """ if "id" not in args: return bad_request("id not invalid") try: register = self.get_registration_by_id(args["id"]) if register is not None: register.delete() hackathon = register.hackathon self.__update_register_stat(hackathon) team = self.team_manager.get_team_by_user_and_hackathon( register.user, hackathon) if not team: self.log.warn("team of this registered user is not found!") return ok() self.team_manager.quit_team_forcedly(team, register.user) return ok() except Exception as ex: self.log.error(ex) return internal_server_error("failed in delete register: %s" % args["id"])
def check_sub_id(self, subscription_id): azure_key = AzureKey.objects(subscription_id=subscription_id).first() if self.util.is_local(): if azure_key is not None: azure_key.verified = True azure_key.save() return ok("success") if azure_key is None: return internal_server_error( "No available azure key on the server side.") sms = CloudServiceAdapter(azure_key.subscription_id, azure_key.get_local_pem_url(), host=azure_key.management_host) if sms.ping(): azure_key.verified = True azure_key.save() else: return bad_request( "Subscription id is not valid, check whether subscription id is valid and upload the right cer file to azure" ) return ok("success")
def upload_files(self, user_id, file_type): """Handle uploaded files from http request""" try: self.__validate_upload_files() except Exception as e: self.log.error(e) return bad_request("file size or file type unsupport") file_list = [] storage = RequiredFeature("storage") for file in request.files: file_content = request.files[file] pre_file_name = file_content.filename file_suffix = pre_file_name[pre_file_name.rfind('.'):] new_file_name = self.__generate_file_name(user_id, file_type, file_suffix) self.log.debug("upload file: " + new_file_name) context = Context( file_name=new_file_name, file_type=file_type, content=file_content ) context = storage.save(context) # file_name is a random name created by server, pre_file_name is the original name file_info = { "file_name": new_file_name, "pre_file_name": pre_file_name, "url": context.url } file_list.append(file_info) return {"files": file_list}
def get(self): user_id = self.context().user_id if "user_id" in self.context() else None if user_id: return team_manager.get_team_show_list_by_user(user_id) elif user_manager.validate_token(): return team_manager.get_team_show_list_by_user(g.user.id) else: return bad_request("must login or provide a user id")
def post(self): args = request.get_json() if 'name' not in args: return bad_request('template name name invalid') template_name = args['name'] user_id = g.user.id hackathon_name = g.hackathon.name return expr_manager.start_expr(hackathon_name, template_name, user_id)
def get(self): user_id = self.context().user_id if "user_id" in self.context() else None if user_id: return team_manager.get_team_show_list_by_user(user_id) elif user_manager.validate_login(): return team_manager.get_team_show_list_by_user(g.user.id) else: return bad_request("must login or provide a user id")
def authenticate_and_call(*args, **kwargs): if not user_manager.validate_token(): return unauthorized("login required") if not hack_manager.validate_hackathon_name(): return bad_request("hackathon name invalid") if not admin_manager.validate_admin_privilege_http(): return forbidden("access denied") return func(*args, **kwargs)
def delete_registration(self, args): if "id" not in args: return bad_request("id not invalid") try: register = self.db.find_first_object_by(UserHackathonRel, id == args['id']) if register is not None: self.db.delete_object(register) return ok() except Exception as ex: self.log.error(ex) return internal_server_error("failed in delete register: %s" % args["id"])
def get(self): parse = reqparse.RequestParser() parse.add_argument("user_id", type=str, location="args", required=False) args = parse.parse_args() uid = args["user_id"] or None if uid: user = user_manager.get_user_by_id(uid) elif user_manager.validate_login(): user = user_manager.get_user_by_id(g.user.id) else: return bad_request("must login or provide a user id") return user_manager.cleaned_user_dic(user)
def get(self): parse = reqparse.RequestParser() parse.add_argument("user_id", type=str, location="args", required=False) args = parse.parse_args() uid = args["user_id"] or None if uid: user = user_manager.get_user_by_id(uid) elif user_manager.validate_token(): user = user_manager.get_user_by_id(g.user.id) else: return bad_request("must login or provide a user id") return user_manager.cleaned_user_dic(user)
def add_template_for_team(self, args): """Add template to team of the current user by template name template_id must be included in args. Current login user must have a team and HE must be its leader """ if "template_id" not in args: return bad_request("template id invalid") team = self.__get_valid_team_by_user(g.user.id, g.hackathon.id) if not team: return precondition_failed("you don't join any team so you cannot add teamplate") if team.leader.id != g.user.id: return forbidden("team leader required") else: return self.hackathon_template_manager.add_template_to_hackathon(args["template_id"])
def create_team(self, kwargs): """Create new team by given args. user only allow to join or create 1 team. So if user joined or created team before, will be get failed when creating new team. :type kwargs: dict :param kwargs: a dict of required information to create new team :rtype: dict :return: created team information """ user_team_rel = self.__get_team_by_user(g.user.id, g.hackathon.id) if user_team_rel: self.log.debug( "fail to create team since user is already in some team.") return precondition_failed("you must leave the current team first") if "team_name" not in kwargs: return bad_request("Please provide a team name") # check team name to avoid duplicate name team_name = kwargs["team_name"] if self.__get_team_by_name(g.hackathon.id, team_name): return precondition_failed( "The team name is existed, please provide a new name") team = Team(name=team_name, description=kwargs.get("description"), git_project=kwargs.get("git_project"), logo=kwargs.get("logo"), create_time=self.util.get_now(), update_time=self.util.get_now(), leader_id=g.user.id, hackathon_id=g.hackathon.id) self.db.add_object(team) user_team_rel = UserTeamRel(join_time=self.util.get_now(), update_time=self.util.get_now(), status=TeamMemberStatus.Approved, hackathon_id=g.hackathon.id, user_id=g.user.id, team_id=team.id) self.db.add_object(user_team_rel) return team.dic()
def create_team(self, kwargs): """Create new team by given args. user only allow to join or create 1 team. So if user joined or created team before, will be get failed when creating new team. :type kwargs: dict :param kwargs: a dict of required information to create new team :rtype: dict :return: created team information """ user_team_rel = self.__get_team_by_user(g.user.id, g.hackathon.id) if user_team_rel: self.log.debug("fail to create team since user is already in some team.") return precondition_failed("you must leave the current team first") if "team_name" not in kwargs: return bad_request("Please provide a team name") # check team name to avoid duplicate name team_name = kwargs["team_name"] if self.__get_team_by_name(g.hackathon.id, team_name): return precondition_failed("The team name is existed, please provide a new name") team = Team(name=team_name, description=kwargs.get("description"), git_project=kwargs.get("git_project"), logo=kwargs.get("logo"), create_time=self.util.get_now(), update_time=self.util.get_now(), leader_id=g.user.id, hackathon_id=g.hackathon.id) self.db.add_object(team) user_team_rel = UserTeamRel(join_time=self.util.get_now(), update_time=self.util.get_now(), status=TeamMemberStatus.Approved, hackathon_id=g.hackathon.id, user_id=g.user.id, team_id=team.id) self.db.add_object(user_team_rel) return team.dic()
def add_team_show(self, user, context): team = self.__get_team_by_id(context.team_id) if not team: return not_found() self.__validate_team_permission(team.hackathon.id, team, user) try: work = TeamWork(id=uuid.uuid1(), description=context.get("note"), type=context.type, uri=context.uri) team.works.append(work) team.save() except ValidationError as e: if "uri" in e.message: return bad_request("`uri` field must be in uri format") else: raise e return to_dic(work)
def delete_registration(self, args): """ Delete the registration of a user in a hackathon, also do operation on the user's team. """ if "id" not in args: return bad_request("id not invalid") try: register = self.get_registration_by_id(args["id"]) if register is not None: register.delete() hackathon = register.hackathon self.__update_register_stat(hackathon) team = self.team_manager.get_team_by_user_and_hackathon(register.user, hackathon) if not team: self.log.warn("team of this registered user is not found!") return ok() self.team_manager.quit_team_forcedly(team, register.user) return ok() except Exception as ex: self.log.error(ex) return internal_server_error("failed in delete register: %s" % args["id"])
def update_admin(self, args): """Update hackathon admin :returns ok() if updated successfully bad_request() if "id" not in request body not_found() if specific AdminHackathonRel not found internal_server_error() if DB exception raised """ id = args.get("id", None) if not id: return bad_request("invalid id") ahl = self.db.find_first_object(AdminHackathonRel, AdminHackathonRel.id == id) if not ahl: return not_found("admin does not exist") update_items = self.__generate_update_items(args) try: self.db.update_object(ahl, **update_items) return ok('update hackathon admin successfully') except Exception as e: self.log.error(e) return internal_server_error(e)
def check_sub_id(self, subscription_id): azure_key = AzureKey.objects(subscription_id=subscription_id).first() if self.util.is_local(): if azure_key is not None: azure_key.verified = True azure_key.save() return ok("success") if azure_key is None: return internal_server_error("No available azure key on the server side.") sms = CloudServiceAdapter(azure_key.subscription_id, azure_key.get_local_pem_url(), host=azure_key.management_host) if sms.ping(): azure_key.verified = True azure_key.save() else: return bad_request("Subscription id is not valid, check whether subscription id is valid and upload the right cer file to azure") return ok("success")
def post(self): args = request.get_json() if "team_name" not in args: return bad_request("Team name is required") return team_manager.join_team(g.hackathon.id, args["team_name"], g.user)
def authenticate_and_call(*args, **kwargs): if not hack_manager.validate_hackathon_name(): return bad_request("hackathon name invalid") return func(*args, **kwargs)
def delete(self): args = request.get_json() if 'experiment_id' not in args: return bad_request('experiment id invalid') return expr_manager.stop_expr(args['experiment_id'])
def test_validate_updated_args_invalid_id(self): args = {} status, return_info = self.admin_manager.validate_updated_args(args) self.assertFalse(status) self.assertEqual(return_info, bad_request("invalid id"))
def test_create_admin_bad_request(self): args = {} self.assertEqual(self.admin_manager.create_admin(args), bad_request("email invalid"))
def test_create_hackathon_lost_args(self): args = {"a": "b"} hackathon = 'test_hackathon' self.assertEqual(self.register_manager.create_registration(hackathon, args), bad_request("user id invalid"))
def get_hackathon_notice_list(self, body): """ list hackathon notices, notices are paginated, can be filtered by hackathon_name, event and category, can be ordered by update_time, event and category. :type body: Context :param body: valid key/values(all key/values are optional) body = { hackathon_name: string, // filter by hackathon_name, default unfiltered filter_by_user: '******' | 'all', // filter by user, default filter all notice that has specfic receivers category: 'int[,int...]', // filter by category, default unfiltered event: 'int[,int...]', // filter by event, default unfiltered order_by: 'time' | 'event' | 'category', // order by update_time, event, category, default by time page: int, // page number after pagination, start from 1, default 1 per_page: int // items per page, default 1000 } :return: json style text, see util.Utility ::Example: : body = { order_by: 'time', category: '1,2,3', page: 1, per_page: 6 } search first 6 notices ordered by time, filtered by: category in [1,2,3] : body = { hackathon_name: 'hackathon', event: '1', order_by: 'event' } search first 1000 notices ordered by event, filtered by event == 1 and hackathon_name == 'hackathon' """ hackathon_name = body.get("hackathon_name") filter_by_user = body.get("filter_by_user", "") notice_category = body.get("category") notice_event = body.get("event") order_by = body.get("order_by", "time") page = int(body.get("page", 1)) per_page = int(body.get("per_page", 1000)) hackathon_filter = Q() category_filter = Q() event_filter = Q() user_filter = Q(receiver=None) is_read_filter = Q() order_by_condition = '-update_time' if hackathon_name: #list notices that belong to specfic hackathon hackathon = Hackathon.objects( name=hackathon_name).only('name').first() if hackathon: hackathon_filter = Q(hackathon=hackathon) else: return not_found('hackathon_name not found') else: #only list online hackathons' notices or notices that not belong to any hackathon online_hackathon = Hackathon.objects(status=HACK_STATUS.ONLINE) hackathon_filter = Q(hackathon__in=online_hackathon) | Q( hackathon=None) if filter_by_user: # only return notices that are sent to the login user user = None if self.user_manager.validate_login(): user = g.user user_filter = Q(receiver=user) if filter_by_user == 'unread': is_read_filter = Q(is_read=False) else: return bad_request("please login first") if notice_category: notice_category_tuple = tuple( [int(category) for category in notice_category.split(',')]) category_filter = Q(category__in=notice_category_tuple) if notice_event: notice_event_tuple = tuple( [int(event) for event in notice_event.split(',')]) event_filter = Q(event__in=notice_event_tuple) if order_by == 'category': order_by_condition = '+category' elif order_by == 'event': order_by_condition = '+event' else: order_by_condition = '-update_time' pagination = HackathonNotice.objects( hackathon_filter & category_filter & event_filter & user_filter & is_read_filter).order_by(order_by_condition).paginate( page, per_page) def func(hackathon_notice): return hackathon_notice.dic() # return serializable items as well as total count return self.util.paginate(pagination, func)
def test_create_hackathon_lost_args(self): args = {"a": "b"} hackathon = 'test_hackathon' self.assertEqual( self.register_manager.create_registration(hackathon, args), bad_request("user id invalid"))
def post(self): args = request.get_json() if "template_id" not in args: return bad_request("template id invalid") return hackathon_template_manager.add_template_to_hackathon( args['template_id'])
def post(self): args = request.get_json() if "template_id" not in args: return bad_request("template id invalid") return hackathon_template_manager.add_template_to_hackathon(args['template_id'])
def get_hackathon_notice_list(self, body): """ list hackathon notices, notices are paginated, can be filtered by hackathon_name, event and category, can be ordered by update_time, event and category. :type body: Context :param body: valid key/values(all key/values are optional) body = { hackathon_name: string, // filter by hackathon_name, default unfiltered filter_by_user: '******' | 'all', // filter by user, default filter all notice that has specfic receivers category: 'int[,int...]', // filter by category, default unfiltered event: 'int[,int...]', // filter by event, default unfiltered order_by: 'time' | 'event' | 'category', // order by update_time, event, category, default by time page: int, // page number after pagination, start from 1, default 1 per_page: int // items per page, default 1000 } :return: json style text, see util.Utility ::Example: : body = { order_by: 'time', category: '1,2,3', page: 1, per_page: 6 } search first 6 notices ordered by time, filtered by: category in [1,2,3] : body = { hackathon_name: 'hackathon', event: '1', order_by: 'event' } search first 1000 notices ordered by event, filtered by event == 1 and hackathon_name == 'hackathon' """ hackathon_name = body.get("hackathon_name") filter_by_user = body.get("filter_by_user", "") notice_category = body.get("category") notice_event = body.get("event") order_by = body.get("order_by", "time") page = int(body.get("page", 1)) per_page = int(body.get("per_page", 1000)) hackathon_filter = Q() category_filter = Q() event_filter = Q() user_filter = Q(receiver=None) is_read_filter = Q() order_by_condition = '-update_time' if hackathon_name: #list notices that belong to specfic hackathon hackathon = Hackathon.objects(name=hackathon_name).only('name').first() if hackathon: hackathon_filter = Q(hackathon=hackathon) else: return not_found('hackathon_name not found') else: #only list online hackathons' notices or notices that not belong to any hackathon online_hackathon = Hackathon.objects(status=HACK_STATUS.ONLINE) hackathon_filter = Q(hackathon__in=online_hackathon) | Q(hackathon=None) if filter_by_user: # only return notices that are sent to the login user user = None if self.user_manager.validate_login(): user = g.user user_filter = Q(receiver=user) if filter_by_user == 'unread': is_read_filter = Q(is_read=False) else: return bad_request("please login first") if notice_category: notice_category_tuple = tuple([int(category) for category in notice_category.split(',')]) category_filter = Q(category__in=notice_category_tuple) if notice_event: notice_event_tuple = tuple([int(event) for event in notice_event.split(',')]) event_filter = Q(event__in=notice_event_tuple) if order_by == 'category': order_by_condition = '+category' elif order_by == 'event': order_by_condition = '+event' else: order_by_condition = '-update_time' pagination = HackathonNotice.objects( hackathon_filter & category_filter & event_filter & user_filter & is_read_filter ).order_by( order_by_condition ).paginate(page, per_page) def func(hackathon_notice): return hackathon_notice.dic() # return serializable items as well as total count return self.util.paginate(pagination, func)
def test_delete_registration_lost_id(self): args = {'a': 'b'} self.assertEqual(self.register_manager.delete_registration(args), bad_request("id not invalid"))