def get_log(cls, context, *, after=None, before=None, limit=None, challenge=None, group=None, match=None): if after is not None and before is not None: raise WrongArguments() User.test_permission(context, 'submission.full', 'submission.view') queryset = models.Submission.objects.order_by('-pk') if after is not None: queryset = queryset.filter(pk__lt=after) if before is not None: queryset = queryset.filter(pk__gt=before).reverse() if challenge is not None: queryset = queryset.filter(challenge=challenge) if group is not None: queryset = queryset.filter(group=group) if match is not None: queryset = queryset.filter(flagclear__isnull=not match) queryset = list( queryset.values( 'pk', 'user', 'challenge', 'text', 'time', flag=models.models.F('flagclear__flag'), )[slice(limit)]) if before is not None: queryset.reverse() return queryset
def update(self, **kwargs): User.test_permission(self._context, 'challenge.full') old = self._json_all self._update(**kwargs) new = self._json_all for subscriber in self.subscribers: subscriber(old, new)
def regen_all(cls, context): """重算所有缓存,只有通过命令行提权后才能调用""" User.test_permission(context) for obj in models.Submission.objects.all(): try: obj.group = User.get(context, obj.user).group obj.save() except NotFound: pass for obj in models.FlagClear.objects.all(): try: user = User.get(context, obj.user) obj.group = user.group challenge = Challenge.get(context, obj.challenge) if obj.flag not in range(len(challenge.flags)): raise NotFound obj.save() except NotFound: obj.delete() for challenge in Challenge.get_all(context): cls._regen_challenge_clear(challenge) models.ChallengeFirst.objects.all().delete() models.FlagFirst.objects.all().delete() cls._refill_first() cls._regen_score()
def get_all(cls, context): queryset = models.Trigger.objects.order_by('time') try: User.test_permission(context, 'trigger.full') except PermissionRequired: queryset = queryset.filter(time__lte=context.time) return [cls(context, obj) for obj in queryset]
def create(cls, context, **kwargs): User.test_permission(context, 'trigger.full') self = cls(context, models.Trigger()) self._update(**kwargs) new = self._json_all for subscriber in self.subscribers: subscriber(None, new) return self
def get(self, request): try: User.test_authenticated(Context.from_request(request)) except LoginRequired: return redirect('hub') return TemplateResponse(request, 'profile.html', { 'profile_required': User.profile_required, })
def delete(self): User.test_permission(self._context, 'challenge.full') old = self._json_all self._obj.expr_set.all().delete() self._obj.delete() self._obj = None for subscriber in self.subscribers: subscriber(old, None)
def post(self, request): context = Context.from_request(request) try: User.test_authenticated(context) except LoginRequired: return redirect('hub') for pk in request.POST.getlist('terms'): Terms.get(context, pk=pk).agree(request.user.pk) return redirect('hub')
def get_board(cls, context, *, limit=None, category=None, group=None): if group in User.no_board_groups: User.test_permission(context, 'submission.full', 'submission.view') return list( cls._filter_group(models.Score.objects, group).filter(category=category).order_by( '-score', 'time').values('user', 'score', 'time')[slice(limit)])
def create(cls, context, **kwargs): User.test_permission(context, 'challenge.full') self = cls(context, models.Challenge()) flags = kwargs.pop('flags') self._update(**kwargs) self._update(flags=flags) new = self._json_all for subscriber in self.subscribers: subscriber(None, new) return self
def save_user(self, request, sociallogin, form=None): super().save_user(request, sociallogin, form) user = sociallogin.user User.create( Context(elevated=True), group='other', user=user, email=user.email, ) return user
def flags(self): flags = json.loads(self._obj.flags) try: User.test_permission(self._context, 'challenge.full', 'challenge.view') return flags except PermissionRequired: return [{ 'name': flag['name'], 'score': flag['score'], } for flag in flags]
def get_violations(cls, context, *, challenge=None, group=None): User.test_permission(context, 'submission.full', 'submission.view') queryset = models.FlagViolation.objects if challenge is not None: queryset = queryset.filter(submission__challenge=challenge) if group is not None: queryset = queryset.filter(submission__group=group) return list(queryset.values( 'violation_flag', 'violation_user', user=models.models.F('submission__user'), challenge=models.models.F('submission__challenge'), time=models.models.F('submission__time'), ))
def get_first(cls, context, *, group=None): if group in User.no_board_groups: User.test_permission(context, 'submission.full', 'submission.view') return { 'challenges': list( models.ChallengeFirst.objects.filter(group=group).values( 'challenge', 'user', 'time')), 'flags': list( models.FlagFirst.objects.filter(group=group).values( 'challenge', 'flag', 'user', 'time')), }
def regen_all(cls, context): """重算所有缓存,只有通过命令行提权后才能调用""" User.test_permission(context) models.User.objects.all().delete() models.Expr.objects.all().delete() models.ExprFlag.objects.all().delete() for challenge in cls.get_all(context): for i, flag in enumerate(challenge.flags): if flag['type'] != 'expr': continue challenge._obj.expr_set.create(flag_index=i, expr=flag['flag']) for user in User.get_all(context): if not user.token: continue cls._add_user(user.pk) models.User.objects.create(user=user.pk)
def post(self, request): try: kwargs = json.loads(request.body) kwargs = {k: kwargs[k] for k in kwargs if k in User.update_fields} user = User.get(Context.from_request(request), request.user.pk) user.update(**kwargs) return JsonResponse({}) except WrongFormat as e: return JsonResponse({'error': e.json}, status=400)
def _add_user(cls, user): from .expr_flags import expr_flag if models.User.objects.filter(user=user).exists(): return False token = User.get(Context(elevated=True), user).token for expr_obj in models.Expr.objects.values('expr').distinct(): models.ExprFlag.objects.create( expr=expr_obj['expr'], user=user, flag=expr_flag(expr_obj['expr'], token), ) return True
def _add_expr(cls, expr): from .expr_flags import expr_flag if models.Expr.objects.filter(expr=expr).exists(): return False for user_obj in models.User.objects.all(): token = User.get(Context(elevated=True), user_obj.user).token models.ExprFlag.objects.create( expr=expr, user=user_obj.user, flag=expr_flag(expr, token), ) return True
def frontend(request): return { 'page': Page.get(), 'user_': (User.get(Context.from_request(request), request.user.pk) if request.user.is_authenticated else None), 'groups': User.groups, 'debug': settings.DEBUG, 'no_board_groups': User.no_board_groups, }
def post(self, request): if not self.check(): return redirect('hub') eligible = request.POST['eligible'] if eligible == 'yes': UstcEligible.objects.create(user=request.user, eligible=True) user = User.get( Context.from_request(request).copy(elevated=True), request.user.pk) user.update(group='ustc') elif eligible == 'no': UstcEligible.objects.create(user=request.user, eligible=False) return redirect('hub')
def login(self, **kwargs): account, created = Account.objects.get_or_create( provider=self.provider, identity=self.normalize_identity(), ) self.on_get_account(account) if not account.user: account.user = User.create( Context(elevated=True), group=self.group, **kwargs, ).user account.save() login(self.request, account.user, self.backend)
def get_enabled(cls, context): User.test_authenticated(context) Terms.test_agreed_enabled(context) User.test_profile(context) try: User.test_permission(context, 'challenge.full', 'challenge.view') except PermissionRequired: Trigger.test_can_view_challenges(context) queryset = models.Challenge.objects.filter(enabled=True) return [cls(context, obj) for obj in queryset]
def get(self, request): context = Context.from_request(request) try: return TemplateResponse( request, 'first.html', { 'filters': { 'group': request.GET.get('group', None), }, 'users': {u.pk: u.json for u in User.get_all(context)}, 'challenges': [c.json for c in Challenge.get_enabled(context)], }) except Error as e: messages.error(request, e.message) return redirect('hub')
def get(self, request): context = Context.from_request(request) try: return TemplateResponse( request, 'board.html', { 'filters': { 'category': request.GET.get('category', None), 'group': request.GET.get('group', None), }, 'users': {u.pk: u.display_name for u in User.get_all(context)}, }) except Error as e: messages.error(request, e.message) return redirect('hub')
def get(self, request): if request.user.is_authenticated: if Account.objects.filter(provider='ustc', user=request.user).exists(): try: request.user.ustceligible except UstcEligible.DoesNotExist: return redirect('ustcprofile') context = Context.from_request(request) try: challenges = Challenge.get_enabled(context) challenges = {'value': [obj.json for obj in challenges]} except ProfileRequired as e: messages.info(request, e.message) return redirect('profile') except TermsRequired as e: messages.info(request, e.message) return redirect('terms') except Error as e: challenges = {'error': e.json} try: announcement = Announcement.get_latest(context).json except NotFound: announcement = None if request.user.is_authenticated: user = User.get(context, request.user.pk) if user.group == 'other': ranking = Submission.get_user_ranking(context, request.user.pk) else: ranking = Submission.get_user_ranking(context, request.user.pk, group=user.group) else: ranking = {} return TemplateResponse( request, 'hub.html', { 'announcement': announcement, 'challenges': challenges, 'progress': Submission.get_user_progress( context, request.user.pk), 'ranking': ranking, 'clear_count': Submission.get_clear_count(context), })
def get(cls, context, pk): queryset = models.Challenge.objects.all() try: User.test_permission(context, 'challenge.full', 'challenge.view') except PermissionRequired: User.test_authenticated(context) Terms.test_agreed_enabled(context) User.test_profile(context) Trigger.test_can_view_challenges(context) queryset = queryset.filter(enabled=True) try: return cls(context, queryset.get(pk=pk)) except models.Challenge.DoesNotExist: raise NotFound('题目不存在')
def submit(cls, context, user, challenge, text): if context.user.pk != user: User.test_permission(context) if len(text) > 200: raise WrongFormat('Flag 不应超过 200 个字符') user = User.get(context, user) challenge = Challenge.get(context, challenge) try: latest = (models.Submission.objects.filter( user=user.pk, challenge=challenge.pk).latest('time')) except models.Submission.DoesNotExist: pass else: if latest.time + timedelta(seconds=10) > context.time: raise SlowDown('提交过于频繁,请 10 秒后再试') obj = models.Submission.objects.create( user=user.pk, group=user.group, challenge=challenge.pk, text=text, time=context.time, ) matches, violations = challenge.check_flag_with_violations(text) queryset = models.FlagClear.objects.filter(user=user.pk, challenge=challenge.pk) flags = {i.flag for i in queryset} match_flags = {i['index'] for i in matches} for flag in match_flags - flags: models.FlagClear.objects.create( submission=obj, user=user.pk, group=user.group, challenge=challenge.pk, flag=flag, time=context.time, ) if user.group not in User.no_score_groups: models.FlagFirst.objects.get_or_create( challenge=challenge.pk, flag=flag, group=None, defaults={ 'user': user.pk, 'time': context.time }, ) models.FlagFirst.objects.get_or_create( challenge=challenge.pk, flag=flag, group=user.group, defaults={ 'user': user.pk, 'time': context.time }, ) for f, u in violations: models.FlagViolation.objects.create( submission=obj, violation_flag=f['index'], violation_user=u, ) if match_flags - flags: if (flags | match_flags).issuperset(range(len(challenge.flags))): models.ChallengeClear.objects.create( user=user.pk, group=user.group, challenge=challenge.pk, time=context.time, ) if user.group not in User.no_score_groups: models.ChallengeFirst.objects.get_or_create( challenge=challenge.pk, group=None, defaults={ 'user': user.pk, 'time': context.time }, ) models.ChallengeFirst.objects.get_or_create( challenge=challenge.pk, group=user.group, defaults={ 'user': user.pk, 'time': context.time }, ) score = sum(i['score'] for i in matches if i['index'] not in flags) cls._add_score(user.pk, user.group, context.time, score, challenge.category) return matches
def get_all(cls, context): User.test_permission(context, 'challenge.full', 'challenge.view') return [cls(context, obj) for obj in models.Challenge.objects.all()]
def get(cls, context, pk): User.test_permission(context, 'trigger.full') try: return cls(context, models.Trigger.objects.get(pk=pk)) except models.Trigger.DoesNotExist: raise NotFound()
def delete(self): User.test_permission(self._context, 'trigger.full') self._obj.delete() self._obj = None