def kick_or_leave(self, operator, team_id, user_id): try: team = Team.objects(id=team_id, members__user=user_id).first() except ValidationError: return not_found() if not team: return not_found() mem = filter(lambda x: str(x.user.id) == user_id, team.members) assert len(mem) < 2 if not mem: return not_found() mem = mem[0] hackathon = team.hackathon user = mem.user if str(team.leader.id) == user_id: # if the user to be leaved or kicked is team leader return precondition_failed("leader cannot leave team") if str(operator.id) == user_id: # leave team team.members.remove(mem) team.save() self.create_default_team(hackathon, user) else: # kick somebody else self.__validate_team_permission(hackathon.id, team, operator) team.members.remove(mem) team.save() self.create_default_team(hackathon, user) return ok()
def grant_award_to_team(self, hackathon, context): team = self.__get_team_by_id(context.team_id) if not team: return not_found("team not found") award = self.db.find_first_object_by(Award, id=context.award_id) if not award: return not_found("award not found") if team.hackathon_id != hackathon.id or award.hackathon_id != hackathon.id: return precondition_failed("hackathon doesn't match") exist = self.db.find_first_object_by(TeamAward, team_id=context.team_id, award_id=context.award_id) if not exist: exist = TeamAward( team_id=context.team_id, hackathon_id=hackathon.id, award_id=context.award_id, reason=context.get("reason"), level=award.level, ) self.db.add_object(exist) else: exist.reason = context.get("reason", exist.reason) self.db.commit() return self.__award_with_detail(exist)
def join_team(self, user, team_id): """Join a team will create a record on user_team_rel table which status will be 0. :type user: User :param user: the user to join a team :rtype: dict :return: if user already joined team or team not exist, return bad request. Else, return a dict of joined details. """ if self.db.find_first_object_by(UserTeamRel, user_id=user.id, team_id=team_id): return ok("You already joined this team.") team = self.__get_team_by_id(team_id) if not team: return not_found() cur_team = self.__get_valid_team_by_user(user.id, team.hackathon_id) if cur_team and cur_team.team.user_team_rels.count() > 1: return precondition_failed("Team leader cannot join another team for team member count greater than 1") if not self.register_manager.is_user_registered(user.id, team.hackathon): return precondition_failed("user not registerd") candidate = UserTeamRel(join_time=self.util.get_now(), update_time=self.util.get_now(), status=TeamMemberStatus.Init, hackathon_id=team.hackathon.id, user_id=user.id, team_id=team.id) self.db.add_object(candidate) return candidate.dic()
def join_team(self, user, team_id): """Join a team will create a record on user_team_rel table which status will be 0. :type user: User :rtype: dict :return: if user already joined team or team not exist, return bad request. Else, return a dict of joined details. """ if Team.objects(id=team_id, members__user=user.id).count(): return ok("You already joined this team.") team = self.__get_team_by_id(team_id) if not team: return not_found() cur_team = self.__get_valid_team_by_user(user.id, team.hackathon.id) if cur_team and cur_team.members.count() > 1: return precondition_failed("Team leader cannot join another team for team member count greater than 1") if not self.register_manager.is_user_registered(user.id, team.hackathon): return precondition_failed("user not registerd") mem = TeamMember( join_time=self.util.get_now(), status=TEAM_MEMBER_STATUS.INIT, user=user) team.members.append(mem) team.save() return to_dic(mem)
def score_team(self, judge, ctx): team = self.__get_team_by_id(ctx.team_id) if not team: return not_found("team not found") if not self.admin_manager.is_hackathon_admin(team.hackathon.id, judge.id): return forbidden() score = filter(lambda x: x.judge.id == judge.id, team.scores) assert len(score) < 2 if score: score = score[0] score.score = ctx.score score.reason = ctx.get("reason") score.update_time = self.util.get_now() else: score = TeamScore( score=ctx.score, judge=judge, reason=ctx.get("reason")) team.scores.append(score) team.save() return self.__response_get_score(judge, team.scores)
def get_and_check_host_server(self, host_server_id): """ first get the docker host DB object for a hackathon, and check whether the container_count is correct through "Docker Restful API", if not, update this value in the database. :param host_server_id: the id of host_server in DB :type host_server_id: Integer :return: A object of docker_host_server :rtype: DockerHostServer object or None """ host_server = DockerHostServer.objects(id=host_server_id).first() if host_server is None: self.log.warn('get docker_host fail, not find host server by id:' + host_server_id) return not_found("docker host server not found") ping = self.docker.ping(host_server) if not ping: host_server.state = DockerHostServerStatus.UNAVAILABLE host_server.save() else: try: containers = self.docker.list_containers(host_server) if len(containers) != host_server.container_count: host_server.container_count = len(containers) host_server.save() except Exception as e: self.log.error("Failed in sync container count") self.log.error(e) return self.__check_docker_host_server(host_server).dic()
def promote_leader(self, hackathon_id, team_name, new_leader_id): """ team leader promote some one from team to become team leader :type hackathon_id: int :param hackathon_id: hackathon id :type team_name: str|unicode :param team_name: team name :type new_leader_id: int :param new_leader_id: id of user who will become new leader of the team :rtype: bool :return: if promote success, return ok. if not ,return bad request. """ team = self.__get_team_by_name(hackathon_id, team_name) if not team: return not_found("team doesn't exist") self.__validate_team_permission(hackathon_id, team, g.user) # check new leader and old leader in same team member = team.user_team_rels.filter_by(user_id=new_leader_id).first() if not member: return precondition_failed("Please promote someone in the same team.") if member.status != TeamMemberStatus.Approved: return precondition_failed("The member is not approved yet") team.leader_id = new_leader_id self.db.commit() self.log.debug(team.leader.name + " has been promote to leader.") return team.dic()
def update_user_profile(self, args): """ Update user profile with fields and values specified in 'args' :param args: (key=value) paris, whose keys match the column name of DB table user_profile and values are corresponding column values :type args: dict :return: a record of related user profile in DB table user_profile :rtype: class UserProfile object :raise: raise error when something goes wrong with DB operation :type: internal server error """ self.log.debug("update_user_profile") try: u_id = args["user_id"] user_profile = self.db.find_first_object_by(UserProfile, user_id=u_id) if user_profile: self.db.update_object(user_profile, **args) return user_profile.dic() else: return not_found("fail to update user profile") except Exception as e: self.log.debug(e) return internal_server_error("failed to update user profile")
def join_team(self, hackathon_id, team_name, user): """Join a team will create a record on user_team_rel table which status will be 0. :type hackathon_id: int :param hackathon_id: hackathon id :type team_name: str | unicode :param team_name: team name :type user: User :param user: the user to join a team :rtype: dict :return: if user already joined team or team not exist, return bad request. Else, return a dict of joined details. """ if self.db.find_first_object_by(UserTeamRel, hackathon_id=hackathon_id, user_id=g.user.id): return precondition_failed("You have joined another team, please quit first.") team = self.__get_team_by_name(hackathon_id, team_name) if team: candidate = UserTeamRel(join_time=self.util.get_now(), update_time=self.util.get_now(), status=TeamMemberStatus.Init, hackathon_id=hackathon_id, user_id=user.id, team_id=team.id) self.db.add_object(candidate) return candidate.dic() else: return not_found("team not found !")
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 delete_hackathon_notice(self, notice_id): hackathon_notice = HackathonNotice.objects(id=notice_id).first() if not hackathon_notice: return not_found('Hackathon notice not found') hackathon_notice.delete() return ok()
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 """ team = self.__get_team_by_id(kwargs["id"]) if not team: return not_found("team not exists") # avoid duplicate team with same names if "name" in kwargs and kwargs["name"] != team.name: if self.__get_team_by_name(g.hackathon.id, kwargs["name"]): return precondition_failed("team with the same name exists already") self.__validate_team_permission(g.hackathon.id, team, g.user) # hackathon.modify(**update_items) # team.name = kwargs.get("name", team.name) # team.description = kwargs.get("description", team.description) # team.logo = kwargs.get("logo", team.logo) kwargs.pop("id", None) # id should not be included team.modify(**kwargs) team.update_time = self.util.get_now() team.save() return self.__team_detail(team)
def start_expr(self, hackathon_name, template_name, user_id): """ A user uses a template to start a experiment under a hackathon :param hackathon_name: :param template_name: :param user_id: :return: """ hack_temp = self.__check_template_status(hackathon_name, template_name) if hack_temp is None: return not_found('hackathon or template is not existed') hackathon = hack_temp[0] # if not self.register_manager.is_user_registered(user_id, hackathon): # return forbidden("user not registered or not approved") if hackathon.event_end_time < self.util.get_now(): self.log.warn("hackathon is ended. The expr starting process will be stopped") return precondition_failed('hackathen is ended') template = hack_temp[1] if user_id > 0: expr = self.__check_expr_status(user_id, hackathon, template) if expr is not None: return self.__report_expr_status(expr) # new expr return self.__start_new_expr(hackathon, template, user_id)
def get(self): parse = reqparse.RequestParser() parse.add_argument("id", type=str, location="args", required=True) # register_id args = parse.parse_args() rel = register_manager.get_registration_by_id(args["id"]) return rel.dic() if rel is not None else not_found("not found")
def get(self): user_id = g.user.id info = user_profile_manager.get_user_profile(user_id) if info is not None: return info.dic() else: return not_found("User doesn't have profile info yet.")
def update_team_member_status(self, operator, user_team_rel_id, status): """ update user's status on selected team. if current user doesn't have permission, return bad request. Else, update user's status :type status: int :param status: the status of the team member, see TeamMemberStatus in constants.py :rtype: bool :return: if update success, return ok. if not , return bad request. """ rel = self.db.find_first_object_by(UserTeamRel, id=user_team_rel_id) if not rel: return not_found() team = rel.team self.__validate_team_permission(rel.hackathon_id, team, operator) if rel.user_id == team.leader_id: return precondition_failed("cannot update status of team leader") if status == TeamMemberStatus.Approved: # disable previous team first self.db.delete_all_objects_by(UserTeamRel, hackathon_id=rel.hackathon_id, user_id=rel.user_id, status=TeamMemberStatus.Approved) self.db.delete_all_objects_by(Team, hackathon_id=rel.hackathon_id, leader_id=rel.user_id) rel.status = TeamMemberStatus.Approved rel.update_time = self.util.get_now() self.db.commit() return ok("approved") if status == TeamMemberStatus.Denied: self.db.delete_object(rel) return ok("Your request has been denied, please rejoin another team.")
def update_host_server(self, args): """ update a docker host_server's information for a hackathon. :param hackathon_id: the id of hackathon in DB :type hackathon_id: Integer :return: ok() if succeed. not_found(...) if fail to update the docker_host's information """ vm = DockerHostServer.objects(id=args.id).first() if vm is None: self.log.warn('delete docker_host fail, not find hostserver_id:' + args.id) return not_found("", "host_server not found") vm.vm_name = args.get("vm_name", vm.vm_name) vm.public_dns = args.get("public_dns", vm.public_dns) vm.public_ip = args.get("public_ip", vm.public_ip) vm.private_ip = args.get("private_ip", vm.private_ip) vm.container_max_count = int(args.get("container_max_count", vm.container_max_count)) vm.public_docker_api_port = int(args.get("public_docker_api_port", vm.public_docker_api_port)) vm.private_docker_api_port = int(args.get("private_docker_api_port", vm.private_docker_api_port)) vm.disabled = args.get("disabled", vm.disabled) if self.docker.ping(vm): vm.state = DockerHostServerStatus.DOCKER_READY else: vm.state = DockerHostServerStatus.UNAVAILABLE vm.save() return self.__check_docker_host_server(vm).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 send_email_azure(self, kwargs): # team information team = self.__get_team_by_id(kwargs["id"]) if not team: return not_found("team not exists") azure = team.azure if not azure.strip(): if Azure.objects(status="0").count() == 0: return ok("请联系管理员.") azure_info = Azure.objects(status="0").first() else: azure_info = Azure.objects(account=azure).first() if not azure_info: return ok("请联系管理员!") primary_emails = [] for i in xrange(0, len(team.members)): mem = team.members[i] resp = self.user_manager.user_display_info(mem.user) primary_emails.append(resp['emails'][0]['email']) Azure.objects(account=azure_info.account).update_one(status="1") Team.objects(id=team.id).update_one(azure=azure_info.account) sender = '' email_title = '' email_content = '' return self.util.send_emails(sender, primary_emails, email_title, email_content)
def add_admin(self, args): """Add a new administrator on a hackathon :type args: dict :param args: http request body in json format :return hackathon response 'ok' if successfully added. 'not_found' if email is invalid or user not found. 'internal_server_error' if any other unexpected exception caught """ user = self.user_manager.get_user_by_email(args.get("email")) if user is None: return not_found("user not found") try: ahl = self.db.find_first_object(AdminHackathonRel, AdminHackathonRel.user_id == user.id, AdminHackathonRel.hackathon_id == g.hackathon.id) if ahl is None: ahl = AdminHackathonRel( user_id=user.id, role_type=args.get("role_type", ADMIN_ROLE_TYPE.ADMIN), hackathon_id=g.hackathon.id, remarks=args.get("remarks"), create_time=self.util.get_now() ) self.db.add_object(ahl) return ok() except Exception as e: self.log.error(e) return internal_server_error("create admin failed")
def test_create_admin_email_missed(self): args = {'email': '*****@*****.**'} db_adapter = Mock() db_adapter.find_first_object.return_value = None am = AdminManager(db_adapter) self.assertEqual(am.create_admin(args), not_found("email does not exist in DB")) db_adapter.find_first_object.assert_called_once_with(UserEmail, ANY)
def heart_beat(self, expr_id): expr = Experiment.objects(id=expr_id, status=EStatus.RUNNING).first() if expr is None: return not_found('Experiment is not running') expr.last_heart_beat_time = self.util.get_now() expr.save() return ok()
def heart_beat(self, expr_id): expr = self.db.find_first_object_by(Experiment, id=expr_id, status=EStatus.RUNNING) if expr is None: return not_found('Experiment is not running') expr.last_heart_beat_time = self.util.get_now() self.db.commit() return ok()
def get(self): parse = reqparse.RequestParser() parse.add_argument('team_id', type=str, location='args', required=True) args = parse.parse_args() ret = team_manager.get_team_members(args["team_id"]) if not ret: return not_found() return ret
def get_score(self, user, team_id): team = self.__get_team_by_id(team_id) if not team: return not_found("team not found") if not self.admin_manager.is_hackathon_admin(team.hackathon.id, user.id): return {} return self.__response_get_score(user, team.scores)
def test_validate_updated_args_ahl_not_found(self): args = {'id': 7} db_adapter = Mock() db_adapter.find_first_object.return_value = None am = AdminManager(db_adapter) status, return_info = am.validate_updated_args(args) self.assertFalse(status) self.assertEqual(return_info, not_found("ahl does not exist")) db_adapter.find_first_object.assert_called_once_with(AdminHackathonRel, ANY)
def get_template_info_by_id(self, template_id): """Query template basic info from DB by its id :type template_id: int :param template_id: unique id of Template """ template = self.db.get_object(Template, template_id) if template: return template.dic() return not_found("template cannot be found by id %s" % template_id)
def update_hackathon_notice(self, body): hackathon_notice = HackathonNotice.objects(id=body.get('id')).first() if not hackathon_notice: return not_found("hackathon_notice not found") hackathon_notice.content = body.get("content", hackathon_notice.content) hackathon_notice.link = body.get("link", hackathon_notice.link) hackathon_notice.save(validate=False) return hackathon_notice.dic()
def delete_template_from_hackathon(self, template_id): template = Template.objects(id=template_id).first() if template is None: return not_found("template does not exist") if template in g.hackathon.templates: g.hackathon.templates.remove(template) g.hackathon.save() # self.db.delete_object(htr) return self.get_templates_with_detail_by_hackathon(g.hackathon)
def cancel_team_award(self, hackathon, team_id, award_id): team = self.__get_team_by_id(team_id) if not team: return not_found() for award in team.awards: if str(award) == award_id: team.awards.remove(award) team.save() break return ok()
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 load_user(self, user_id): '''get user for flask_login user_loader''' user = self.get_user_by_id(user_id) dic = user.dic() if user else not_found() dic["is_super"] = self.is_super_admin(user) return dic
def get_expr_status(self, expr_id): expr = self.db.find_first_object_by(Experiment, id=expr_id) if expr is not None: return self.__report_expr_status(expr) else: return not_found('Experiment Not found')
def update_team_member_status(self, operator, team_id, user_id, status): """ update user's status on selected team. if current user doesn't have permission, return bad request. Else, update user's status :type status: int :param status: the status of the team member, see TEAM_MEMBER_STATUS in constants.py :rtype: bool :return: if update success, return ok. if not , return bad request. """ team = self.__get_team_by_id(team_id) if not team: return not_found() mem = filter(lambda x: str(x.user.id) == user_id, team.members) assert len(mem) < 2 if not mem: return not_found() mem = mem[0] # #NOTE1# we have to re-check this here # because of this situation: # A is in a single-person team TeamA, and request join TeamB # after that, C join TeamA and now TeamA has two members, # this is not allowed when status == TEAM_MEMBER_STATUS.APPROVED cur_team = self.__get_valid_team_by_user(mem.user.id, team.hackathon.id) if cur_team and cur_team.members.count() > 1: return precondition_failed("Team leader cannot join another team for team member count greater than 1") self.__validate_team_permission(team.hackathon.id, team, operator) if mem.user.id == team.leader.id: return precondition_failed("cannot update status of team leader") if status == TEAM_MEMBER_STATUS.APPROVED: # disable previous team first # NOTE: # Do we also have to delete status that is not TEAM_MEMBER_STATUS.APPROVED? # i.e., if A request join both TeamB and TeamC, TeamC approve join first, then TeamB approved, # this will cause A leave TeamB and join TeamC. # is this the desired behaviour? Team.objects(hackathon=team.hackathon.id).update(__raw__={ "$pull": { "members": { "user": user_id, "status": TEAM_MEMBER_STATUS.APPROVED}}}) # because only team leader with single team can make join request # so we don't have to make default team for other members in this team # we make the check in #NOTE1# so this is always true Team.objects(hackathon=team.hackathon.id, leader=mem.user.id).delete() mem.status = TEAM_MEMBER_STATUS.APPROVED mem.update_time = self.util.get_now() team.save() return ok("approved") if status == TEAM_MEMBER_STATUS.DENIED: user = mem.user hackathon = team.hackathon team.members.remove(mem) team.save() self.create_default_team(hackathon, user) return ok("Your request has been denied, please rejoin another team.")
def get(self): context = self.context() template = template_library.get_template_info_by_id(context.id) if template: return template.dic() return not_found("template cannot be found by id %s" % context.id)
def get_hackathon_notice(self, notice_id): hackathon_notice = HackathonNotice.objects(id=notice_id).first() if not hackathon_notice: return not_found("hackathon_notice not found") return hackathon_notice.dic()
def get(self): parse = reqparse.RequestParser() parse.add_argument('id', type=int, location='args', required=False) args = parse.parse_args() template = template_manager.get_template_by_id(args['id']) return template.dic() if template is not None else not_found("not found")
def get_expr_status_and_confirm_starting(self, expr_id): expr = Experiment.objects(id=expr_id).first() if expr: return self.__report_expr_status(expr, isToConfirmExprStarting=True) else: return not_found('Experiment Not found')
def get_my_current_team(self, hackathon, user): team = self.__get_valid_team_by_user(user.id, hackathon.id) return self.__team_detail(team, user) if team else not_found("user has no team", friendly_message="组队异常,请联系管理员!")
def load_user(self, user_id): '''get user for flask_login user_loader''' user = self.get_user_by_id(user_id) dic = user.dic() if user else not_found() return dic
def test_update_register_not_found(self, get_method): args = {"id": 1} get_method.return_value = None self.assertEqual(self.register_manager.update_registration(args), not_found("registration not found"))