def hackathon1(user1): new_hack = Hackathon( name="hackathon1", display_name="hackathon for test", ) new_hack.save() admin = UserHackathon(user=user1, hackathon=new_hack, remark='creator') admin.save() return new_hack
def __create_hackathon(self, creator, context): """Insert hackathon and creator(admin of course) to database We enforce that default config are used during the creation :type context: Context :param context: context of the args to create a new hackathon :rtype: Hackathon :return hackathon instance """ new_hack = Hackathon( name=context.name, display_name=context.display_name, ribbon=context.get("ribbon"), description=context.get("description"), short_description=context.get("short_description"), location=context.get("location"), banners=context.get("banners", []), status=HackathonStatus.INIT, creator=creator, type=context.get("type", HackathonType.HACKATHON), config=context.get("config", Context()).to_dict(), tags=context.get("tags", []), event_start_time=context.get("event_start_time"), event_end_time=context.get("event_end_time"), registration_start_time=context.get("registration_start_time"), registration_end_time=context.get("registration_end_time"), judge_start_time=context.get("judge_start_time"), judge_end_time=context.get("judge_end_time")) # basic xss prevention if new_hack.description: # case None type new_hack.description = self.cleaner.clean_html( new_hack.description) new_hack.save() # add the current login user as admin and creator try: admin = UserHackathon(user=creator, hackathon=new_hack, role=HackathonPlayerType.ADMIN, status=HackathonPlayerStatus.AUTO_PASSED, remark='creator') admin.save() except Exception as ex: # TODO: send out a email to remind administrator to deal with this problems self.log.error(ex) raise InternalServerError( "fail to create the default administrator") return new_hack
def unlike_hackathon(self, user, hackathon): user_hackathon = UserHackathon.objects(user=user, hackathon=hackathon).first() if user_hackathon: user_hackathon.like = False user_hackathon.save() # sync the like count like_count = UserHackathon.objects(hackathon=hackathon, like=True).count() self.update_hackathon_stat(hackathon, HackathonStat.LIKE, like_count) return ok()
def delete_hackathon(self): """delete hackathon :return hackathon in dict if updated successfully. """ hackathon = g.hackathon try: UserHackathon.objects(hackathon=hackathon).delete() self.log.debug("delete hackathon:" + hackathon.name) hackathon.delete() hackathon.save() return ok() except Exception as e: self.log.error(e) return internal_server_error("fail to delete hackathon" + hackathon.name)
def get_hackathon_list(self, args): # get values from request's QueryString page = int(args.get("page", 1)) per_page = int(args.get("per_page", 20)) order_by = args.get("order_by", "create_time") status = args.get("status") name = args.get("name") # build query by search conditions and order_by status_filter = Q() name_filter = Q() condition_filter = Q() order_by_condition = '-id' if status: status_filter = Q(status=status) if name: name_filter = Q(name__contains=name) if order_by == 'create_time': # 最新发布 order_by_condition = '-create_time' elif order_by == 'event_start_time': # 即将开始 order_by_condition = '-event_start_time' elif order_by == 'registered_users_num': # 人气热点 # hackathons with zero registered users would not be shown. hot_hackathon_stat = HackathonStat.objects( type=HackathonStat.REGISTER, count__gt=0).order_by('-count') hot_hackathon_list = [ stat.hackathon.id for stat in hot_hackathon_stat ] condition_filter = Q(id__in=hot_hackathon_list) else: order_by_condition = '-id' # perform db query with pagination pagination = Hackathon.objects(status_filter & name_filter & condition_filter).order_by( order_by_condition).paginate( page, per_page) hackathon_list = pagination.items hackathon_stat = HackathonStat.objects(hackathon__in=hackathon_list) user = None user_hackathon = [] team = [] if self.user_manager.validate_token(): user = g.user user_hackathon = UserHackathon.objects( user=user, hackathon__in=hackathon_list) team = Team.objects(members__user=user, hackathon__in=hackathon_list) def func(hackathon): return self.__fill_hackathon_detail(hackathon, user, hackathon_stat, user_hackathon, team) # return serializable items as well as total count return self.util.paginate(pagination, func)
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 create_registration(self, hackathon, user, args): """Register hackathon for user Will add a new record in table UserRegistrationRel if precondition fulfilled """ self.log.debug("create_register: %r" % args) user_id = args['user_id'] check_login_provider = self.__is_user_hackathon_login_provider(user, hackathon) if check_login_provider["fail"]: return login_provider_error( "hackathon registration not login provider", friendly_message="当前黑客松活动只是使用" + ",".join(check_login_provider["provides"]) + "账户才能报名", provides=",".join(check_login_provider["provides"])) if self.is_user_registered(user.id, hackathon): self.log.debug("user %s already registered on hackathon %s" % (user_id, hackathon.id)) return self.get_registration_detail(user, hackathon) if self.admin_manager.is_hackathon_admin(hackathon.id, user.id): return precondition_failed("administrator cannot register the hackathon", friendly_message="管理员或裁判不能报名") if hackathon.registration_start_time and hackathon.registration_start_time > self.util.get_now(): return precondition_failed("hackathon registration not opened", friendly_message="报名尚未开始") if hackathon.registration_end_time and hackathon.registration_end_time < self.util.get_now(): return precondition_failed("hackathon registration has ended", friendly_message="报名已经结束") if self.__is_hackathon_filled_up(hackathon): return precondition_failed("hackathon registers reach the upper threshold", friendly_message="报名人数已满") try: is_auto_approve = hackathon.config.get(HackathonConfig.AUTO_APPROVE, True) status = HackathonPlayerStatus.AUTO_PASSED if is_auto_approve else HackathonPlayerStatus.UNAUDIT args.pop("user_id") args.pop("hackathon_id") user_hackathon = UserHackathon.objects(user=user, hackathon=hackathon).first() if not user_hackathon: user_hackathon = UserHackathon.objects.create( user=user, hackathon=hackathon, status=status, **args) else: # visitor -> competitor user_hackathon.role = HackathonPlayerType.COMPETITOR user_hackathon.status = status user_hackathon.save() # create a team as soon as user registration approved(auto or manually) if is_auto_approve: self.team_manager.create_default_team(hackathon, user) self.__ask_for_dev_plan(hackathon, user) self.__update_register_stat(hackathon) return user_hackathon.dic() except Exception as e: self.log.error(e) return internal_server_error("fail to create register")
def get_userlike_all_hackathon(self, user_id): user_hackathon_rels = UserHackathon.objects(user=user_id).all() def get_user_hackathon_detail(user_hackathon_rel): dict = user_hackathon_rel.dic() dict["hackathon_info"] = user_hackathon_rel.hackathon.dic() return dict return [get_user_hackathon_detail(rel) for rel in user_hackathon_rels]
def __update_register_stat(self, hackathon): count = UserHackathon.objects( hackathon=hackathon.id, status__in=[HackathonPlayerStatus.AUDIT_PASSED, HackathonPlayerStatus.AUTO_PASSED], role=HackathonPlayerType.COMPETITOR, # TODO deleted=False).count() self.hackathon_manager.update_hackathon_stat(hackathon, HackathonStat.REGISTER, count)
def get_user_hackathon_list_with_detail(self, user_id): user_hackathon_rels = UserHackathon.objects( user=user_id, role=HackathonPlayerType.COMPETITOR).all() def get_user_hackathon_detail(user_hackathon_rel): dict = user_hackathon_rel.dic() dict["hackathon_info"] = user_hackathon_rel.hackathon.dic() return dict return [get_user_hackathon_detail(rel) for rel in user_hackathon_rels]
def get_hackathon_registration_list(self, hackathon_id, num=None): """Get registered users list :rtype: list :return all registered usrs if num is None else return the specific number of users order by create_time desc """ registers = UserHackathon.objects(hackathon=hackathon_id, role=HackathonPlayerType.COMPETITOR).order_by('-create_time')[:num] return [self.__get_registration_with_profile(x) for x in registers]
def get_user_details(user): user_info = self.user_display_info(user) user_hackathon = UserHackathon.objects(hackathon=hackathon, user=user).first() user_info[ "role"] = user_hackathon.role if user_hackathon else HackathonPlayerType.VISITOR user_info[ "remark"] = user_hackathon.remark if user_hackathon else "" return user_info
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_id(args.get("id")) if user is None: return not_found("user not found") if self.register_manager.is_user_registered(user.id, g.hackathon): return precondition_failed("Cannot add a registered user as admin", friendly_message="该用户已报名参赛,不能再被选为裁判或管理员。请先取消其报名") try: user_hackathon = UserHackathon.objects(user=user.id, hackathon=g.hackathon.id).first() if user_hackathon is None: uhl = UserHackathon( user=user, hackathon=g.hackathon, role=args.get("role"), status=HackathonPlayerStatus.AUTO_PASSED, remark=args.get("remark") ) uhl.save() else: user_hackathon.role = args.get("role") user_hackathon.remark = args.get("remark") user_hackathon.save() return ok() except Exception as e: self.log.error(e) return internal_server_error("create admin failed")
def validate_admin_privilege_http(self): """Check the admin authority on hackathon for http request Which means both user_id and hackathon_id are come from http request headers. So token and hackathon_name must be included in headers and must be validated before calling this method :rtype: bool :return True if specific user has admin privilidge on specific hackathon otherwise False """ if g.user.is_super: return True return UserHackathon.objects(role=HackathonPlayerType.ADMIN, hackathon=g.hackathon, user=g.user).count() > 0
def get_entitled_hackathons_list(self, user): """Get hackathon id list that specific user is entitled to manage :rtype: list :return list of hackathon simple """ if not user.is_super: hack_list = UserHackathon.objects(user=user, role=HackathonPlayerType.ADMIN).distinct("hackathon") hack_list.sort(key=lambda s: s.create_time, reverse=True) else: hack_list = Hackathon.objects().all().order_by("-create_time") all_hackathon = [h.dic() for h in hack_list] return all_hackathon
def get_admins_by_hackathon(self, hackathon): """Get all admins of a hackathon :type hackathon: Hackathon :param hackathon: instance of Hackathon :rtype: list :return list of administrators including the detail information """ user_hackathon_rels = UserHackathon.objects(hackathon=hackathon, role__in=[HackathonPlayerType.ADMIN, HackathonPlayerType.JUDGE]).all() def get_admin_details(rel): dic = rel.dic() dic["user_info"] = self.user_manager.user_display_info(rel.user) return dic return [get_admin_details(rel) for rel in user_hackathon_rels]
def delete_admin(self, user_hackathon_id): """Delete admin on a hackathon creator of the hackathon cannot be deleted. :returns ok() if succeeds or it's deleted before. precondition_failed if try to delete the creator """ user_hackathon = UserHackathon.objects(id=user_hackathon_id).first() if not user_hackathon: return ok() hackathon = user_hackathon.hackathon if hackathon and hackathon.creator == user_hackathon.user: return precondition_failed("hackathon creator can not be deleted") user_hackathon.delete() return ok()
def __is_hackathon_filled_up(self, hackathon): """Check whether all seats are occupied or not :return False if not all seats occupied or hackathon has no limit at all otherwise True """ # TODO maximum = self.hackathon_manager.get_basic_property(hackathon, HackathonConfig.MAX_ENROLLMENT, 0) if maximum == 0: # means no limit return False else: # count of audited users current_num = UserHackathon.objects( hackathon=hackathon.id, status__in=[HackathonPlayerStatus.AUDIT_PASSED, HackathonPlayerStatus.AUTO_PASSED], role=HackathonPlayerType.COMPETITOR).count() return current_num >= maximum
def is_hackathon_admin(self, hackathon_id, user_id): """Check whether user is admin of specific hackathon :type hackathon_id: string or object_id :param hackathon_id: id of hackathon :type user_id: string or object_id :param user_id: the id of user to be checked :rtype: bool :return True if specific user has admin privilidge on specific hackathon otherwise False """ if User.objects(id=user_id, is_super=True).count(): return True return UserHackathon.objects( user=user_id, hackathon=hackathon_id, role=HackathonPlayerType.ADMIN).count() > 0
def like_hackathon(self, user, hackathon): user_hackathon = UserHackathon.objects(hackathon=hackathon, user=user).first() if user_hackathon and user_hackathon.like: return ok() if not user_hackathon: user_hackathon = UserHackathon( hackathon=hackathon, user=user, role=HackathonPlayerType.VISITOR, status=HackathonPlayerStatus.UNAUDIT, like=True, remark="") user_hackathon.save() if not user_hackathon.like: user_hackathon.like = True user_hackathon.save() # increase the count of users that like this hackathon self.increase_hackathon_stat(hackathon, HackathonStat.LIKE, 1) return ok()
def __get_hackathon_stat(self, hackathon): stats = HackathonStat.objects(hackathon=hackathon).all() result = {"hackathon_id": str(hackathon.id), "online": 0, "offline": 0} for item in stats: result[item.type] = item.count reg_list = UserHackathon.objects( hackathon=hackathon, role=HackathonPlayerType.COMPETITOR, deleted=False, status__in=[ HackathonPlayerStatus.AUTO_PASSED, HackathonPlayerStatus.AUDIT_PASSED ]).only("user").no_dereference().all() reg_list = [uh.user.id for uh in reg_list] reg_count = len(reg_list) if reg_count > 0: online_count = User.objects(id__in=reg_list, online=True).count() result["online"] = online_count result["offline"] = reg_count - online_count return result
def __get_hackathon_detail(self, hackathon, user=None): """Return hackathon info as well as its details including configs, stat, organizers, like if user logon""" detail = hackathon.dic() detail["stat"] = {"register": 0, "like": 0} for stat in HackathonStat.objects(hackathon=hackathon): if stat.type == HackathonStat.REGISTER: detail["stat"]["register"] = stat.count elif stat.type == HackathonStat.LIKE: detail["stat"]["like"] = stat.count if user: user_hackathon = UserHackathon.objects(hackathon=hackathon, user=user).first() if user_hackathon and user_hackathon.like: detail['like'] = user_hackathon.like detail["user"] = self.user_manager.user_display_info(user) detail["user"]["is_admin"] = user.is_super or ( user_hackathon and user_hackathon.role == HackathonPlayerType.ADMIN) # TODO: we need to review those items one by one to decide the API output # asset = self.db.find_all_objects_by(UserHackathonAsset, user_id=user.id, hackathon_id=hackathon.id) # if asset: # detail["asset"] = [o.dic() for o in asset] if user_hackathon and user_hackathon.role == HackathonPlayerType.COMPETITOR: detail["registration"] = user_hackathon.dic() team = Team.objects(hackathon=hackathon, members__user=user).first() if team: detail["team"] = team.dic() return detail
def __email_notify_dev_plan_submitted(self, team): # send emails to all admins of this hackathon when one team dev plan is submitted. admins = UserHackathon.objects( hackathon=team.hackathon, role=HackathonPlayerType.ADMIN).distinct("user") email_title = self.util.safe_get_config( "email.email_templates.dev_plan_submitted_notify.title", None) file_name = self.util.safe_get_config( "email.email_templates.dev_plan_submitted_notify.default_file_name", None) sender = self.util.safe_get_config("email.default_sender", "") # todo remove receivers_forced receivers_forced = self.util.safe_get_config("email.receivers_forced", []) try: if email_title and file_name: path = abspath("%s/.." % dirname(realpath(__file__))) f = open(path + "/resources/email/" + file_name, "r") email_content = f.read() email_title = email_title % (team.name.encode("utf-8")) email_content = email_content.replace( "{{team_name}}", team.name.encode("utf-8")) email_content = email_content.replace("{{team_id}}", str(team.id)) email_content = email_content.replace( "{{hackathon_name}}", team.hackathon.name.encode("utf-8")) f.close() else: self.log.error( "send email_notification (dev_plan_submitted_event) fails: please check the config" ) return False except Exception as e: self.log.error(e) return False # isNotified: whether at least one admin has been notified by emails. isNotified = False for admin in admins: isSent = False primary_emails = [ email.email for email in admin.emails if email.primary_email ] nonprimary_emails = [ email.email for email in admin.emails if not email.primary_email ] # send notification to all primary-mailboxes. if not len(primary_emails) == 0: isSent = self.util.send_emails(sender, primary_emails, email_title, email_content) # if fail to send emails to primary-mailboxes, sent email to one non-primary mailboxes. if not isSent and not len(nonprimary_emails) == 0: for nonpri_email in nonprimary_emails: if self.util.send_emails(sender, [nonpri_email], email_title, email_content): isSent = True break isNotified = isNotified or isSent # todo remove this code self.util.send_emails(sender, receivers_forced, email_title, email_content) self.log.debug(team.name + ": dev_plan email notification result: " + str(isNotified)) return isNotified
def get_registration_by_user_and_hackathon(self, user_id, hackathon_id): return UserHackathon.objects(user=user_id, hackathon=hackathon_id, role=HackathonPlayerType.COMPETITOR).first()
def get_registration_by_id(self, registration_id): return UserHackathon.objects(id=registration_id).first()