def handle(self, challenges_dir, dry_run=False, **options): self.challenges_dir = challenges_dir self.media_dir = pathlib.Path(settings.MEDIA_ROOT) self.dry_run = dry_run context = Context(elevated=True) old_challenges = {i.name: i for i in Challenge.get_all(context)} new_challenges = {} for path in challenges_dir.iterdir(): if not path.is_dir() or path.name.startswith('.'): continue # noinspection PyBroadException try: challenge = self.parse_challenge(path) except Exception as e: msg = traceback.format_exception_only(type(e), e)[0].strip() self.stdout.write(self.style.ERROR(f'{path.name}: {msg}')) else: if challenge['enabled']: new_challenges[challenge['name']] = challenge self.stdout.write(f'Parsed {len(new_challenges)} challenges') for name in new_challenges: if name in old_challenges: if not dry_run: old_challenges[name].update(**new_challenges[name]) self.stdout.write(f'{name}: ' + self.style.WARNING('updated')) else: if not dry_run: Challenge.create(context, **new_challenges[name]) self.stdout.write(f'{name}: ' + self.style.SUCCESS('created')) for name in old_challenges: if name not in new_challenges: if not dry_run: old_challenges[name].delete() self.stdout.write(f'{name}: ' + self.style.NOTICE('deleted'))
def _challenge_event(cls, old, new): context = Context(elevated=True) if old is None: return if new is None: models.ChallengeClear.objects.filter(challenge=old['pk']).delete() models.FlagClear.objects.filter(challenge=old['pk']).delete() models.ChallengeFirst.objects.filter(challenge=old['pk']).delete() models.FlagFirst.objects.filter(challenge=old['pk']).delete() if old['enabled']: cls._regen_score() return if len(new['flags']) != len(old['flags']): models.FlagClear.objects.filter(challenge=old['pk'], flag__gte=len( new['flags'])).delete() cls._regen_challenge_clear(Challenge.get(context, old['pk'])) models.ChallengeFirst.objects.filter(challenge=old['pk']).delete() models.FlagFirst.objects.filter(challenge=old['pk']).delete() cls._refill_first() if not old['enabled'] and not new['enabled']: return if new['enabled'] != old['enabled']: cls._regen_score() return if new['category'] != old['category']: cls._regen_score() return old_flag_scores = [i['score'] for i in old['flags']] new_flag_scores = [i['score'] for i in new['flags']] if new_flag_scores != old_flag_scores: cls._regen_score() return
def _regen_score(cls): models.Score.objects.all().delete() cs = {i.pk: i.json for i in Challenge.get_all(Context(elevated=True))} for i in models.FlagClear.objects.order_by('time').iterator(): if cs[i.challenge]['enabled']: cls._add_score(i.user, i.group, i.time, cs[i.challenge]['flags'][i.flag]['score'], cs[i.challenge]['category'])
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 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 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 post(self, request): body = json.loads(request.body) method = body['method'] args = body.get('args', {}) try: method = getattr(self, f'do_{method}') value = method(Context.from_request(request), **args) return JsonResponse({'value': value}) except Error as e: return JsonResponse({'error': e.json}, status=400)
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 initialize(self, context): self.context = Context( server=context.server, config=context.config, importer=context.modules.importer, request_handler=self ) RepositoryMixin.initialize(self, self.context) self.remote_ip = self.request.headers.get('X-Forwarded-For', self.request.headers.get('X-Real-Ip', self.request.remote_ip))
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 get(self, request): try: return TemplateResponse( request, self.template, { **site.each_context(request), **self.get_extra_context(Context.from_request(request)), 'title': self.title, }) except Error as e: messages.error(request, e.message) return redirect('hub')
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 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 post(self, request): try: matches = Submission.submit(Context.from_request(request), request.user.pk, request.POST['challenge'], request.POST['flag'].strip()) if matches: messages.success(request, '答案正确') else: messages.error(request, '答案错误') except Error as e: messages.info(request, e.message) 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(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): 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 _refill_first(cls): """尝试把 ChallengeFirst 和 FlagFirst 中的空位都填上""" for challenge in Challenge.get_all(Context(elevated=True)): for group in {None, *User.groups}.difference( models.ChallengeFirst.objects .filter(challenge=challenge.pk) .values_list('group', flat=True) ): try: first = ( cls._filter_group(models.ChallengeClear.objects, group) .filter(challenge=challenge.pk) .earliest('time') ) models.ChallengeFirst.objects.create( challenge=challenge.pk, group=group, user=first.user, time=first.time, ) except models.ChallengeClear.DoesNotExist: pass for flag in range(len(challenge.flags)): for group in {None, *User.groups}.difference( models.FlagFirst.objects .filter(challenge=challenge.pk, flag=flag) .values_list('group', flat=True) ): try: first = ( cls._filter_group(models.FlagClear.objects, group) .filter(challenge=challenge.pk, flag=flag) .earliest('time') ) models.FlagFirst.objects.create( challenge=challenge.pk, flag=flag, group=group, user=first.user, time=first.time, ) except models.FlagClear.DoesNotExist: pass
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 set_group(apps, schema_editor): Submission = apps.get_model('submission', 'Submission') db_alias = schema_editor.connection.alias for obj in Submission.objects.using(db_alias).all(): obj.group = User.get(Context(elevated=True), obj.user).group obj.save()
from server.context import Context from server import di di.cxt = Context() from server.api import task_bp, file_bp, web_bp, user_bp, visit_bp, status_bp app = di.cxt.app app.register_blueprint(task_bp, url_prefix='/tasks') app.register_blueprint(file_bp, url_prefix='/files') app.register_blueprint(web_bp, url_prefix='/webs') app.register_blueprint(user_bp, url_prefix='/users') app.register_blueprint(visit_bp, url_prefix='/visits') app.register_blueprint(status_bp, url_prefix='/status')
def get(self, request): context = Context.from_request(request) return TemplateResponse(request, 'announcements.html', { 'announcements': [i.json for i in Announcement.get_all(context)], })
def get_context(server_parameters, config, importer): return Context( server=server_parameters, config=config, importer=importer )
def handle(self, fake_complex_challenges, fake_simple_challenges, fake_users, fake_submissions, game_started_seconds, **options): root = User.create( Context(elevated=True), group='other', nickname='root', ).user root.is_staff = True root.is_superuser = True root.save() root.refresh_from_db() Account.objects.create(provider='debug', identity='root', user=root) c1 = Challenge.create( Context(root), name='签到题', category='checkin', detail='签到题描述', url='https://example.com/{token}', prompt='flag{hackergame}', index=-100, enabled=True, flags=[{ 'name': '', 'score': 10, 'type': 'text', 'flag': 'flag{hackergame}', }], ) Submission.submit(Context(root), root.pk, c1.pk, 'flag{hackergame}') for i in range(1, fake_complex_challenges + 1): Challenge.create( Context(root), name=f'复杂题 {i}', category='complex', detail='<code>flag{FLAG_INDEX}</code> 或 ' '<code>flag{FLAG_INDEX:USER_ID}</code>', url='', prompt='flag{...}', index=random.randrange(100), enabled=random.choice((False, True, True, True, True)), flags=[{ 'name': f'flag {j}', 'score': random.randrange(100), 'type': ('expr', 'text')[j % 2], 'flag': ("f'flag{{%s:{token.partition(\":\")[0]}}}'" % j, f'flag{{{j}}}')[j % 2], } for j in range(random.randrange(1, 4))], ) for i in range(1, fake_simple_challenges + 1): Challenge.create( Context(root), name=f'简单题 {i}', category='simple', detail='', url='', prompt=('flag{0}', 'flag{0:USER_ID}')[i % 2], index=random.randrange(100), enabled=random.choice((False, True, True, True, True)), flags=[{ 'name': '', 'score': random.randrange(100), 'type': ('text', 'expr')[i % 2], 'flag': ('flag{0}', "'flag{0:'+token.partition(':')[0]+'}'")[i % 2], }], ) terms = Terms.create(Context(root), name='条款', content='1 2 3 ...', enabled=True) now = timezone.now() timestamps = [] for i in range(fake_submissions): delta = random.randrange(game_started_seconds) timestamps.append(now - timezone.timedelta(seconds=delta)) timestamps.sort() Trigger.create(Context(root), time=min(timestamps), state=True) groups = list(set(User.groups.keys()) - {'staff', 'banned'}) for i in range(fake_users): print('user', i, end='\r') u = User.create( Context(elevated=True), group=random.choice(groups), nickname='用户 ' * 8 + str(i), name='姓名', sno='PB11111111', tel='123456789', email='*****@*****.**', gender=random.choice(('female', 'male')), qq='12345', school='foo', grade='1', ) Terms.get(Context(u.user), terms.pk).agree(u.pk) Account.objects.create(provider='debug', identity=f'{i}', user=u.user) users = [i.pk for i in User.get_all(Context(root))] challenges = [i.pk for i in Challenge.get_all(Context(root))] for i in range(fake_submissions): print('submission', i, end='\r') try: u = random.choice(users) c = random.choice(challenges) fs = len(Challenge.get(Context(root), c).flags) Submission.submit( Context( User.get(Context(root), u).user, timestamps[i] ), u, c, f'flag{{{random.choice(range(fs))}:{u}}}' ) Submission.submit( Context( User.get(Context(root), u).user, timestamps[i] + timezone.timedelta(seconds=20) ), u, c, f'flag{{{random.choice(range(fs))}}}' ) except (NotFound, SlowDown): pass Challenge.create( Context(root), name='难题', category='hard', detail='难题描述', url='https://example.com/{token}', prompt='flag{hackergame}', index=100, enabled=True, flags=[{ 'name': '', 'score': 100, 'type': 'text', 'flag': 'flag{hackergame}', }], )
def handle(self, *args, **options): context = Context(elevated=True) Challenge.regen_all(context) Submission.regen_all(context)
def get(self, request): terms = Terms.get_enabled(Context.from_request(request)) return TemplateResponse(request, 'terms.html', {'terms': terms})