def _render_disqualification_reason(self, request, submission): prev = super(SimilarityDisqualificationMixin, self) \ ._render_disqualification_reason(request, submission) if is_contest_admin(request): q_expression = Q(submissions__submission=submission) else: # Do not split this filter as it spans many-to-many relationship q_expression = Q(submissions__submission=submission, submissions__guilty=True) similarities = SubmissionsSimilarityGroup.objects \ .filter(q_expression) \ .select_related('submissions') if not similarities: return prev submission_contexts = {} for group in similarities: for entry in group.submissions.all(): submission_contexts[entry.submission] = \ submission_template_context(request, entry.submission) template = ('similarsubmits/programming_similar_submissions_admin.html' if is_contest_admin(request) else 'similarsubmits/programming_similar_submissions.html') context = RequestContext(request, { 'similarities': similarities, 'main_submission_id': submission.id, 'submission_contexts': submission_contexts, }) return prev + render_to_string(template, context_instance=context)
def can_see_teams_list(request): if not Team.objects.filter(contest=request.contest).exists(): return False try: cfg = TeamsConfig.objects.get(contest=request.contest) except TeamsConfig.DoesNotExist: return is_contest_admin(request) return is_contest_admin(request) | \ (cfg.teams_list_visible == 'PUBLIC') | \ ((cfg.teams_list_visible == 'YES') & not_anonymous(request))
def livedata_events_view(request, round_id): user_is_participant = Q( submission__user__participant__contest_id=request.contest.id, submission__user__participant__status="ACTIVE" ) submission_ignored = Q(submission__kind="IGNORED") reports = ( SubmissionReport.objects.filter(user_is_participant) .exclude(submission_ignored) .select_related("submission") .prefetch_related("scorereport_set") ) if (is_contest_admin(request) or is_contest_observer(request)) and "from" in request.GET: # Only admin/observer is allowed to specify 'from' parameter. start_time = datetime.datetime.utcfromtimestamp(int(request.GET["from"])).replace(tzinfo=utc) reports = reports.filter(creation_date__gte=start_time) round = get_object_or_404(request.contest.round_set.all(), pk=round_id) contest_start = round.start_date reports = reports.filter(submission__problem_instance__round=round) if is_contest_admin(request): freeze_time = None else: freeze_time = request.contest.controller.get_round_freeze_time(round) return [ { "submissionId": "START", "reportId": "START", "teamId": "START", "taskId": "START", "submissionTimestamp": int(dateformat.format(request.timestamp, "U")), "judgingTimestamp": int(dateformat.format(contest_start, "U")), "result": "CTRL", } ] + [ { "submissionId": report.submission_id, "reportId": report.pk, "teamId": report.submission.user_id, "taskId": report.submission.problem_instance_id, "submissionTimestamp": int(dateformat.format(report.submission.date, "U")), "judgingTimestamp": int(dateformat.format(report.creation_date, "U")), "result": report.score_report.status if freeze_time is None or report.submission.date < freeze_time else RESULT_FOR_FROZEN_SUBMISSION, } for report in reports.order_by("creation_date") if report.score_report is not None ]
def livedata_events_view(request, round_id): user_is_participant = \ Q(submission__user__participant__contest_id=request.contest.id, submission__user__participant__status='ACTIVE') submission_ignored = Q(submission__kind='IGNORED') reports = SubmissionReport.objects \ .filter(user_is_participant) \ .exclude(submission_ignored) \ .select_related('submission') \ .prefetch_related('scorereport_set') if (is_contest_admin(request) or is_contest_observer(request)) and \ 'from' in request.GET: # Only admin/observer is allowed to specify 'from' parameter. start_time = datetime.datetime.utcfromtimestamp( int(request.GET['from'])).replace(tzinfo=utc) reports = reports.filter(creation_date__gte=start_time) round = get_object_or_404(request.contest.round_set.all(), pk=round_id) contest_start = round.start_date reports = reports.filter(submission__problem_instance__round=round) if is_contest_admin(request): freeze_time = None else: freeze_time = request.contest.controller.get_round_freeze_time(round) return [{ 'submissionId': 'START', 'reportId': 'START', 'teamId': 'START', 'taskId': 'START', 'submissionTimestamp': int(dateformat.format(request.timestamp, 'U')), 'judgingTimestamp': int(dateformat.format(contest_start, 'U')), 'result': 'CTRL', }] + [{ 'submissionId': report.submission_id, 'reportId': report.pk, 'teamId': report.submission.user_id, 'taskId': report.submission.problem_instance_id, 'submissionTimestamp': int(dateformat.format(report.submission.date, 'U')), 'judgingTimestamp': int(dateformat.format(report.creation_date, 'U')), 'result': report.score_report.status if freeze_time is None or report.submission.date < freeze_time else RESULT_FOR_FROZEN_SUBMISSION, } for report in reports.order_by('creation_date') if report.score_report is not None]
def contest_files_view(request): contest_files = ContestAttachment.objects.filter(contest=request.contest) \ .filter(Q(round__isnull=True) | Q(round__in=visible_rounds(request))) \ .select_related('round') if not is_contest_admin(request): contest_files = contest_files.filter(Q(pub_date__isnull=True) | Q(pub_date__lte=request.timestamp)) round_file_exists = contest_files.filter(round__isnull=False).exists() problem_instances = visible_problem_instances(request) problem_ids = [pi.problem_id for pi in problem_instances] problem_files = ProblemAttachment.objects \ .filter(problem_id__in=problem_ids) \ .select_related('problem') add_category_field = round_file_exists or problem_files.exists() rows = [{ 'category': cf.round if cf.round else '', 'name': cf.download_name, 'description': cf.description, 'link': reverse('contest_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': cf.id}), 'pub_date': cf.pub_date } for cf in contest_files] rows += [{ 'category': pf.problem, 'name': pf.download_name, 'description': pf.description, 'link': reverse('problem_attachment', kwargs={'contest_id': request.contest.id, 'attachment_id': pf.id}), 'pub_date': None } for pf in problem_files] rows.sort(key=itemgetter('name')) return TemplateResponse(request, 'contests/files.html', {'files': rows, 'files_on_page': getattr(settings, 'FILES_ON_PAGE', 100), 'add_category_field': add_category_field, 'show_pub_dates': True})
def thread_view(request, contest_id, category_id, thread_id): (forum, category, thread, lock) = get_forum_objects(request, category_id, thread_id, lock_required=True) msgs = get_msgs(forum, request) if (request.user.is_authenticated() and not request.contest.forum.is_locked(request.timestamp)) or \ is_contest_admin(request): if request.method == "POST": form = PostForm(request, request.POST) if form.is_valid(): instance = form.save(commit=False) instance.author = request.user instance.thread = thread instance.add_date = request.timestamp instance.save() return redirect('forum_thread', contest_id=contest_id, category_id=category.id, thread_id=thread.id) else: form = PostForm(request) return TemplateResponse(request, 'forum/thread.html', {'forum': forum, 'category': category, 'thread': thread, 'form': form, 'msgs': msgs, 'is_locked': lock}) else: return TemplateResponse(request, 'forum/thread.html', {'forum': forum, 'category': category, 'thread': thread, 'msgs': msgs, 'is_locked': lock})
def delete_post_view(request, category_id, thread_id, post_id): (category, thread, post) = get_forum_ctp(category_id, thread_id, post_id) is_admin = is_contest_admin(request) if not ( # we assert following: is_admin or ( post.author == request.user # you can remove a post only if there is no post added after yours and not thread.post_set.filter(add_date__gt=post.add_date).exists() and post.can_be_removed() ) ): raise PermissionDenied else: choice = confirmation_view(request, 'forum/confirm_delete.html', {'elem': post}) if not isinstance(choice, bool): return choice if choice: post.delete() if not thread.post_set.exists(): thread.delete() return redirect('forum_category', contest_id=request.contest.id, category_id=category.id) return redirect('forum_thread', contest_id=request.contest.id, category_id=category.id, thread_id=thread.id)
def messages_template_context(request, messages): replied_ids = frozenset(m.top_reference_id for m in messages) new_ids = new_messages(request, messages).values_list("id", flat=True) if is_contest_admin(request): unanswered = unanswered_questions(messages) else: unanswered = [] to_display = [ { "message": m, "link_message": m.top_reference if m.top_reference in messages else m, "needs_reply": m in unanswered, "read": m.id not in new_ids, } for m in messages if m.id not in replied_ids ] def key(entry): return entry["needs_reply"], entry["message"].date to_display.sort(key=key, reverse=True) return to_display
def render_submission_footer(self, request, submission): super_footer = super(ProgrammingContestController, self). \ render_submission_footer(request, submission) queryset = Submission.objects \ .filter(problem_instance__contest=request.contest) \ .filter(user=submission.user) \ .filter(problem_instance=submission.problem_instance) \ .exclude(pk=submission.pk) \ .order_by('-date') \ .select_related() if not is_contest_admin(request): cc = request.contest.controller queryset = cc.filter_my_visible_submissions(request, queryset) show_scores = bool(queryset.filter(score__isnull=False)) if not queryset.exists(): return super_footer return super_footer + render_to_string( 'programs/other_submissions.html', context_instance=RequestContext(request, { 'submissions': [submission_template_context(request, s) for s in queryset], 'show_scores': show_scores, 'main_submission_id': submission.id, 'submissions_on_page': getattr(settings, 'SUBMISSIONS_ON_PAGE', 15)}))
def process_view(self, request, view_func, view_args, view_kwargs): if not hasattr(request, 'user'): raise ImproperlyConfigured( "The OiForceDnsIpAuthMiddleware middleware requires the" " 'django.contrib.auth.middleware.AuthenticationMiddleware'" " earlier in MIDDLEWARE_CLASSES.") if not request.user.is_anonymous() and \ not hasattr(request.user, 'backend'): raise ImproperlyConfigured( "The OiForceDnsIpAuthMiddleware middleware requires the" " 'oioioi.base.middleware.AnnotateUserBackendMiddleware'" " earlier in MIDDLEWARE_CLASSES.") if not hasattr(request, 'contest'): raise ImproperlyConfigured( "The OiForceDnsIpAuthMiddleware middleware requires the" " 'oioioi.contests.middleware.CurrentContestMiddleware'" " earlier in MIDDLEWARE_CLASSES.") if not request.contest: return if not isinstance(request.contest.controller, OIOnsiteContestController): return if not request.user.is_authenticated(): return if is_contest_admin(request): return if not Participant.objects.filter(user=request.user, contest=request.contest, status='ACTIVE'): return backend_path = request.user.backend if backend_path != 'oioioi.ipdnsauth.backends.IpDnsBackend': auth.logout(request) return TemplateResponse(request, 'oi/access_blocked.html', {'auth_backend': backend_path})
def add_contest_message_view(request): is_admin = is_contest_admin(request) if request.method == 'POST': form = AddContestMessageForm(request, request.POST) if form.is_valid(): instance = form.save(commit=False) instance.author = request.user if is_admin: instance.kind = 'PUBLIC' else: instance.kind = 'QUESTION' instance.pub_date = None instance.date = request.timestamp instance.save() if instance.kind == 'QUESTION': new_question_signal.send(sender=Message, request=request, instance=instance) log_addition(request, instance) return redirect('contest_messages', contest_id=request.contest.id) else: initial = {} for field in ('category', 'topic', 'content'): if field in request.GET: initial[field] = request.GET[field] form = AddContestMessageForm(request, initial=initial) if is_admin: title = _("Add news") else: title = _("Ask question") return TemplateResponse(request, 'questions/add.html', {'form': form, 'title': title, 'is_news': is_admin})
def thread_view(request, category_id, thread_id): category, thread = get_forum_ct(category_id, thread_id) forum, lock = request.contest.forum, forum_is_locked(request) msgs = get_msgs(request) post_set = thread.post_set.select_related('author').all() if (request.user.is_authenticated() and not lock) or \ is_contest_admin(request): if request.method == "POST": form = PostForm(request, request.POST) if form.is_valid(): instance = form.save(commit=False) instance.author = request.user instance.thread = thread instance.add_date = request.timestamp instance.save() return redirect('forum_thread', contest_id=request.contest.id, category_id=category.id, thread_id=thread.id) else: form = PostForm(request) return TemplateResponse(request, 'forum/thread.html', {'forum': forum, 'category': category, 'thread': thread, 'form': form, 'msgs': msgs, 'is_locked': lock, 'post_set': post_set}) else: return TemplateResponse(request, 'forum/thread.html', {'forum': forum, 'category': category, 'thread': thread, 'msgs': msgs, 'is_locked': lock, 'post_set': post_set})
def navbar_messages_generator(request): if request.contest is None: return {} is_admin = is_contest_admin(request) messages = visible_messages(request) visible_ids = messages.values_list('id', flat=True) if is_admin: messages = unanswered_questions(messages) else: messages = new_messages(request, messages) count = messages.count() if count: text = ungettext('%(count)d NEW MESSAGE', '%(count)d NEW MESSAGES', count) % {'count': count} if count == 1: m = messages.get() link = reverse('message', kwargs={ 'contest_id': request.contest.id, 'message_id': m.top_reference_id if m.top_reference_id in visible_ids else m.id }) else: link = reverse('contest_messages', kwargs={'contest_id': request.contest.id}) return {'link': link, 'text': text, 'id': 'contest_new_messages'} else: return {'link': None, 'text': None, 'id': 'contest_new_messages'}
def add_contest_message_view(request, contest_id): is_admin = is_contest_admin(request) if request.method == "POST": form = AddContestMessageForm(request, request.POST) if form.is_valid(): instance = form.save(commit=False) instance.author = request.user if is_admin: instance.kind = "PUBLIC" else: instance.kind = "QUESTION" instance.date = request.timestamp instance.save() if instance.kind == "QUESTION": new_question_signal.send(sender=Message, request=request, instance=instance) log_addition(request, instance) return redirect("contest_messages", contest_id=contest_id) else: form = AddContestMessageForm(request) if is_admin: title = _("Add announcement") else: title = _("Ask question") return TemplateResponse(request, "questions/add.html", {"form": form, "title": title, "is_announcement": is_admin})
def delete_post_view(request, category_id, thread_id, post_id): (category, thread, post) = get_forum_ctp(category_id, thread_id, post_id) is_admin = is_contest_admin(request) if not is_admin and \ (post.author != request.user or (post.author == request.user and (thread.post_set.filter(add_date__gt=post.add_date).exists() or not post.can_be_removed()))): # author: if there are other posts added later or timedelta is gt 15min # if user is not the author of the post or forum admin raise PermissionDenied else: choice = confirmation_view(request, 'forum/confirm_delete.html', {'elem': post}) if not isinstance(choice, bool): return choice if choice: post.delete() if not thread.post_set.exists(): thread.delete() return redirect('forum_category', contest_id=request.contest.id, category_id=category.id) return redirect('forum_thread', contest_id=request.contest.id, category_id=category.id, thread_id=thread.id)
def has_change_permission(self, request, obj=None): if obj: return False # is_contest_observer() is required in here, because otherwise # observers get a 403 response. Any actions that modify submissions # will be blocked in get_actions() return is_contest_admin(request) or is_contest_observer(request)
def edit_post_view(request, category_id, thread_id, post_id): (category, thread, post) = get_forum_ctp(category_id, thread_id, post_id) is_admin = is_contest_admin(request) if not (post.author == request.user or is_admin): raise PermissionDenied if request.method == 'POST': form = PostForm(request, request.POST, instance=post) if form.is_valid(): instance = form.save(commit=False) instance.approved = False instance.last_edit_date = request.timestamp instance.save() return redirect('forum_thread', contest_id=request.contest.id, category_id=category.id, thread_id=thread.id) else: form = PostForm(request, instance=post) return TemplateResponse(request, 'forum/edit_post.html', { 'forum': request.contest.forum, 'category': category, 'thread': thread, 'form': form, 'post': post, 'msgs': get_msgs(request) })
def download_user_all_output_view(request, submission_report_id): submission_report = get_object_or_404(SubmissionReport, id=submission_report_id) _check_generate_out_permission(request, submission_report) testreports = TestReport.objects.filter( submission_report=submission_report) if not all(bool(report.output_file) for report in testreports): raise Http404 if not is_contest_admin(request): for report in testreports: _check_generated_out_visibility_for_user(report) zipfd, tmp_zip_filename = tempfile.mkstemp() with zipfile.ZipFile(os.fdopen(zipfd, 'wb'), 'w') as zip: for report in testreports: arcname = _userout_filename(report) testfd, tmp_test_filename = tempfile.mkstemp() fileobj = os.fdopen(testfd, 'wb') try: shutil.copyfileobj(report.output_file, fileobj) fileobj.close() zip.write(tmp_test_filename, arcname) finally: os.unlink(tmp_test_filename) name = submission_report.submission.problem_instance.problem.short_name return stream_file(File(open(tmp_zip_filename, 'rb'), name=name + '_' + str(submission_report.submission.user) + '_' + str(submission_report.id) + '_user_outs.zip'))
def test_view(request, package_id): tp = get_object_or_404(TestsPackage, id=package_id) if not is_contest_admin(request) and not tp.is_visible(request.timestamp): raise PermissionDenied file_name = '%s.zip' % tp.name file_name = file_name.encode('utf-8') return stream_file(tp.package, name=file_name)
def dangling_problems_processor(request): if not getattr(request, 'contest', None): return {} if not is_contest_admin(request): return {} def generator(): dangling_pis = ProblemInstance.objects.filter(contest=request.contest, round__isnull=True) count = dangling_pis.count() if not count: return '' elif count == 1: pi = dangling_pis.get() link = reverse('oioioiadmin:contests_probleminstance_change', args=(pi.id,)) if request.path == link: return '' else: link = reverse('oioioiadmin:contests_probleminstance_changelist') text = ungettext('%(count)d PROBLEM WITHOUT ROUND', '%(count)d PROBLEMS WITHOUT ROUNDS', count) % {'count': count} return make_navbar_badge(link, text) return {'extra_navbar_right_dangling_problems': lazy(generator, unicode)()}
def add_or_update_problem(request, contest, template): if 'problem' in request.GET: existing_problem = \ get_object_or_404(Problem, id=request.GET['problem']) if contest and not existing_problem.probleminstance_set.filter( contest=contest).exists(): raise Http404 if not can_admin_problem(request, existing_problem): raise PermissionDenied else: existing_problem = None if not request.user.has_perm('problems.problems_db_admin'): if contest and (not is_contest_admin(request)): raise PermissionDenied navbar_links = navbar_links_registry.template_context(request) context = {'existing_problem': existing_problem, 'navbar_links': navbar_links} tab_kwargs = { 'contest': contest, 'existing_problem': existing_problem } tab_link_params = request.GET.dict() def build_link(tab): tab_link_params['key'] = tab.key return request.path + '?' + six.moves.urllib.parse.urlencode( tab_link_params) return tabbed_view(request, template, context, problem_sources(request), tab_kwargs, build_link)
def filter_visible_reports(self, request, submission, queryset): if is_contest_admin(request): return queryset else: return queryset.filter(status='ACTIVE', kind__in=self.get_visible_reports_kinds(request, submission))
def logo_processor(request): if not getattr(request, 'contest', None): return {} if is_contest_admin(request): return {} @memoized def generator(): try: instance = ContestLogo.objects.get(contest=request.contest) url = reverse('logo_image_view', kwargs={'contest_id': request.contest.id}) link = instance.link except ContestLogo.DoesNotExist: url = request.contest.controller.default_contestlogo_url() link = request.contest.controller.default_contestlogo_link() if not url: return '' if not link: link = reverse('default_contest_view', kwargs={'contest_id': request.contest.id}) context = Context({'url': url, 'link': link}) template = loader.get_template('contestlogo/logo.html') return template.render(context) return {'extra_menu_top_contestlogo': lazy(generator, unicode)()}
def visible_messages(request, author=None, category=None, kind=None): rounds_ids = [round.id for round in visible_rounds(request)] q_expression = Q(round_id__in=rounds_ids) if author: q_expression = q_expression & Q(author=author) if category: # pylint: disable=unpacking-non-sequence category_type, category_id = category if category_type == 'p': q_expression = q_expression & Q(problem_instance__id=category_id) elif category_type == 'r': q_expression = q_expression & Q(round__id=category_id, problem_instance=None) if kind: q_expression = q_expression & Q(kind=kind) messages = Message.objects.filter(q_expression).order_by('-date') if not is_contest_admin(request): q_expression = Q(kind='PUBLIC') if request.user.is_authenticated: q_expression = q_expression \ | (Q(author=request.user) & Q(kind='QUESTION')) \ | Q(top_reference__author=request.user) q_time = Q(date__lte=request.timestamp) \ & ((Q(pub_date__isnull=True) | Q(pub_date__lte=request.timestamp))) \ & ((Q(top_reference__isnull=True)) | Q(top_reference__pub_date__isnull=True) | Q(top_reference__pub_date__lte=request.timestamp)) messages = messages.filter(q_expression, q_time) return messages.select_related('top_reference', 'author', 'problem_instance', 'problem_instance__problem')
def can_see_round(self, request, round): if is_contest_admin(request): return True rtimes = self.get_round_times(request, round) if has_any_active_round(request): return rtimes.is_active(request.timestamp) return super(OIOnsiteContestController, self) \ .can_see_round(request, round)
def forum_exists_and_visible(request): # checks whether the forum exists and # - is locked & visible # - is not locked # - user is contest admin return forum_exists(request) and (not (request.contest.forum.is_locked(request.timestamp) and not request.contest.forum.visible)) or (is_contest_admin(request))
def can_edit_registration(self, request, participant): if self.form_class is None: return False if is_contest_admin(request): return True if participant.status == 'BANNED': return False return bool(request.user == participant.user)
def queryset(self, request): queryset = super(ProblemAdmin, self).queryset(request) combined = queryset.none() if request.user.has_perm('problems.problems_db_admin'): combined |= queryset.filter(contest__isnull=True) if is_contest_admin(request): combined |= queryset.filter(contest=request.contest) return combined
def test_utils(self): ofactory = partial(self.factory, self.observer) cfactory = partial(self.factory, self.cadmin) ufactory = partial(self.factory, User.objects.get(username='******')) self.assertFalse(can_enter_contest(ufactory(self.during))) self.assertTrue(is_contest_admin(cfactory(self.during))) self.assertTrue(can_enter_contest(cfactory(self.during))) self.assertTrue(is_contest_observer(ofactory(self.during))) self.assertTrue(can_enter_contest(ofactory(self.during)))
def get_testrun_report_or_404(request, submission, testrun_report_id=None): qs = TestRunReport.objects.filter(submission_report__submission=submission) if is_contest_admin(request) and testrun_report_id is not None: qs = qs.filter(id=testrun_report_id) else: qs = qs.filter(submission_report__status='ACTIVE') return get_object_or_404(qs)
def get_list_display(self, request): items = super(ProblemPackageAdmin, self).get_list_display(request) + [ self.actions_field(request.contest) ] if not is_contest_admin(request): disallowed_items = [ 'created_by', 'actions_field', ] items = [item for item in items if item not in disallowed_items] return items
def can_see_round(self, request, round): """Determines if the current user is allowed to see the given round. If not, everything connected with this round will be hidden. The default implementation checks round dates. """ if is_contest_admin(request): return True rtimes = self.get_round_times(request, round) return not rtimes.is_future(request.timestamp)
def can_make_complaint(request): if not request.user.is_authenticated(): return False if is_contest_admin(request): return False try: cconfig = request.contest.complaints_config return cconfig.enabled and request.timestamp >= cconfig.start_date \ and request.timestamp <= cconfig.end_date except ComplaintsConfig.DoesNotExist: return False
def contest_attachment_view(request, attachment_id): attachment = get_object_or_404(ContestAttachment, contest_id=request.contest.id, id=attachment_id) if (attachment.round and attachment.round not in visible_rounds(request)) or \ (not is_contest_admin(request) and attachment.pub_date and attachment.pub_date > request.timestamp): raise PermissionDenied return stream_file(attachment.content, attachment.download_name)
def registration_notice_fragment(request): rc = request.contest.controller.registration_controller() if isinstance(rc, PARegistrationController) \ and request.user.is_authenticated() \ and not is_contest_admin(request) \ and not is_participant(request) \ and rc.can_register(request): return render_to_string('pa/registration-notice.html', context_instance=RequestContext(request)) else: return None
def forum_exists_and_visible(request): # checks whether the forum exists and # - is locked & visible # - is not locked # - user is contest admin # TODO maybe logic error (exists and visible or admin), # should be exists and (visible or admin)? return (forum_exists(request) and (not (request.contest.forum.is_locked(request.timestamp) and not request.contest.forum.visible)) or (is_contest_admin(request)))
def get_readonly_fields(self, request, obj=None): result = super(TermsAcceptedPhraseInline, self).get_readonly_fields(request, obj) if not is_contest_admin( request ) or not request.contest.controller.registration_controller( ).can_change_terms_accepted_phrase(request): result = result + ('text', ) return result
def test_utils_off(self): user = User.objects.get(pk=1001) contest = Contest.objects.get(pk="uc") request = RequestFactory().request() request.contest = contest request.user = user self.assertFalse(is_contest_admin(request)) self.assertFalse(is_contest_basicadmin(request)) self.assertFalse(is_contest_observer(request))
def get_testrun_report_or_404( request, submission, testrun_report_id=None, model=TestRunReport ): qs = model.objects.filter(submission_report__submission=submission) if is_contest_admin(request) and testrun_report_id is not None: qs = qs.filter(id=testrun_report_id) else: qs = qs.filter(submission_report__status='ACTIVE') return get_object_or_404(qs)
def get_queryset(self, request): queryset = super(ProblemAdmin, self).get_queryset(request) if request.user.is_anonymous(): combined = queryset.none() else: combined = request.user.problem_set.all() if request.user.has_perm('problems.problems_db_admin'): combined |= queryset.filter(contest__isnull=True) if is_contest_admin(request): combined |= queryset.filter(contest=request.contest) return combined
def can_see_source(self, request, submission): """Check if submission's source should be visible. :type submission: oioioi.contest.Submission Consider using filter_visible_sources instead, especially for batch queries. """ qs = Submission.objects.filter(id=submission.id) if not (is_contest_admin(request) or is_contest_observer(request)) \ and is_model_submission(submission): return False return self.filter_visible_sources(request, qs).exists()
def _testreports_to_generate_outs(request, testreports): """Gets tests' ids from ``testreports`` without generated or processing right now outs. Returns list of tests' ids. """ test_ids = [] for testreport in testreports: download_control, created = UserOutGenStatus.objects. \ select_for_update().get_or_create(testreport=testreport) if not created: if not is_contest_admin(request): # out generated by admin is now visible for user download_control.visible_for_user = True download_control.save() # making sure, that output really exists or is processing right now if bool(testreport.output_file) or download_control.status == '?': # out already generated or is processing, omit continue else: download_control.status = '?' download_control.save() elif bool(testreport.output_file): # out already generated but without UserOutGenStatus object # so probably automatically by system download_control.visible_for_user = True download_control.status = 'OK' download_control.save() continue else: download_control.status = '?' # invisible to the the user when first generated by the admin download_control.visible_for_user = \ not is_contest_admin(request) download_control.save() test_ids.append(testreport.test.id) return test_ids
def render_disqualifications(self, request, user, submissions): """Renders all disqualifications of the given user to HTML, which may be put anywhere on the site. This method should process only submission from ``submissions``. """ if not (self.is_user_disqualified(request, user) or (is_contest_admin(request) and self.user_has_disqualification_history(request, user))): return None disqualified_submissions = [] for submission in submissions: if self.is_submission_disqualified(submission) or \ (is_contest_admin(request) and self.has_disqualification_history(submission)): disqualified_submissions.append({ 'submission': submission, 'reason': self._render_disqualification_reason(request, submission) }) contestwide = self._render_contestwide_disqualification_reason( request, user) if not disqualified_submissions and not contestwide: return None if is_contest_admin(request): template = 'disqualification/submissions-admin.html' else: template = 'disqualification/submissions.html' return render_to_string( template, context_instance=RequestContext( request, { 'submissions': disqualified_submissions, 'contestwide': contestwide, }))
def get_contest_participant_info_list(self, request, user): """Returns a list of tuples (priority, info). Each entry represents a fragment of HTML with information about the user's participation in the contest. This information will be visible for contest admins. It can be any information an application wants to add. The fragments are sorted by priority (descending) and rendered in that order. The default implementation returns basic info about the contestant: his/her full name, e-mail, the user id, his/her submissions and round time extensions. To add additional info from another application, override this method. For integrity, include the result of the parent implementation in your output. """ res = [(100, render_to_string('contests/basic_user_info.html', { 'request': request, 'target_user_name': self.get_user_public_name(request, user), 'target_user': user, 'user': request.user}))] exts = RoundTimeExtension.objects.filter(user=user, round__contest=request.contest) if exts.exists(): res.append((99, render_to_string('contests/roundtimeextension_info.html', { 'request': request, 'extensions': exts, 'user': request.user}))) if is_contest_admin(request) or is_contest_observer(request): submissions = Submission.objects.filter( problem_instance__contest=request.contest, user=user) \ .order_by('-date').select_related() if submissions.exists(): submission_records = [submission_template_context(request, s) for s in submissions] context = { 'submissions': submission_records, 'show_scores': True } rendered_submissions = render_to_string( 'contests/user_submissions_table.html', context_instance=RequestContext(request, context)) res.append((50, rendered_submissions)) return res
def download_user_one_output_view(request, testreport_id): testreport = get_object_or_404(TestReport, id=testreport_id) if not is_contest_admin(request): _check_generated_out_visibility_for_user(testreport) submission_report = testreport.submission_report _check_generate_out_permission(request, submission_report) if not bool(testreport.output_file): raise Http404 return stream_file(testreport.output_file, _userout_filename(testreport))
def can_see_problem_statistics(self, request, pi): controller = pi.controller rtimes = rounds_times(request, self.contest) can_see_problem = controller.can_see_problem(request, pi) if pi.round: can_see_round_results = rtimes[pi.round].public_results_visible( request.timestamp) else: can_see_round_results = False can_observe = is_contest_admin(request) or is_contest_observer(request) return can_see_problem and (can_see_round_results or can_observe)
def filter_visible_sources(self, request, queryset): """Determines which sources the user could see. This usually involves cross-user privileges, like publicizing sources. Default implementations delegates to :meth:`~ContestController.filter_my_visible_submissions`, except for admins and observers, which get full access. Queryset's model should be oioioi.contest.Submission """ if is_contest_admin(request) or is_contest_observer(request): return queryset return self.filter_my_visible_submissions(request, queryset)
def can_see_problem(self, request, problem_instance): """Determines if the current user is allowed to see the given problem. If not, the problem will be hidden from all lists, so that its name should not be visible either. The default implementation checks if the user can see the given round (calls :meth:`can_see_round`). """ if not problem_instance.round: return False if is_contest_admin(request): return True return self.can_see_round(request, problem_instance.round)
def _out_generate_status(self, request, testreport): try: if is_contest_admin(request) or \ testreport.userout_status.visible_for_user: # making sure, that output really exists or is processing if bool(testreport.output_file) or \ testreport.userout_status.status == '?': return testreport.userout_status.status except UserOutGenStatus.DoesNotExist: if testreport.output_file: return 'OK' return None
def can_see_source(self, request, submission): """Determines if the current user is allowed to see source of ``submission``. This usually involves cross-user privileges, like publicizing sources. Default implementations delegates to :meth:`~ContestController.filter_my_visible_submissions`, except for admins and observers, which get full access. """ if is_contest_admin(request) or is_contest_observer(request): return True queryset = Submission.objects.filter(id=submission.id) return self.filter_my_visible_submissions(request, queryset).exists()
def _rounds_for_ranking(self, request, key=CONTEST_RANKING_KEY): can_see_all = is_contest_admin(request) or is_contest_observer(request) ccontroller = self.contest.controller queryset = self.contest.round_set.all() if key != CONTEST_RANKING_KEY: queryset = queryset.filter(id=key) if can_see_all: for round in queryset: yield round else: for round in queryset: rtimes = ccontroller.get_round_times(request, round) if not rtimes.is_future(request.timestamp): yield round
def can_admin_instance_of_problem(request, problem): """Checks if the user has admin permission in a ProblemInstace of the given Problem. If request.contest is not None then ProblemInstaces from this contest are taken into account, problem.main_problem_instance otherwise. If there is no ProblemInstace of problem in request.contest then the function returns False. If the user has permission to admin problem then the function will always return True. """ if can_admin_problem(request, problem): return True return is_contest_admin(request) and ProblemInstance.objects \ .filter(problem=problem, contest=request.contest).exists()
def view(self, request, contest, existing_problem=None): form = self.make_form(request, contest, existing_problem) if contest: contest.controller.adjust_upload_form(request, existing_problem, form) if request.method == 'POST': if form.is_valid(): try: # We need to make sure that the package is saved in the # database before the Celery task starts. with transaction.atomic(): original_filename, file_manager = \ self.get_package_file(request, contest, form, existing_problem) with file_manager as path: package = self.create_package_instance(request, contest, path, existing_problem, original_filename) env = self.create_env(request, contest, form, path, package, existing_problem, original_filename) if contest: contest.controller.fill_upload_environ(request, form, env) package.save() async_task = unpackmgr_job.s(env) async_result = async_task.freeze() ProblemPackage.objects.filter(id=package.id).update( celery_task_id=async_result.task_id) async_task.delay() if request.user.is_superuser or (request.contest and is_contest_admin(request)): messages.success(request, _("Package queued for processing.")) return self._redirect_response(request) messages.success(request, _("Package queued for processing. It will appear in " "problem list when ready. Please be patient.")) return TemplateResponse(request, self.template_name, {'form': form}) # pylint: disable=broad-except except Exception, e: logger.error("Error processing package", exc_info=True, extra={'omit_sentry': True}) form._errors['__all__'] = form.error_class([smart_str(e)])
def all_messages_view(request): def make_entry(m): return { 'message': m, 'replies': [], 'timestamp': m.get_user_date(), # only for messages ordering 'is_new': m in new_msgs, 'has_new_message': m in new_msgs, # only for messages ordering 'needs_reply': m in unanswered, } form, vmsg_kwargs = process_filter_form(request) vmessages = visible_messages(request, **vmsg_kwargs) new_msgs = frozenset(new_messages(request, vmessages)) unanswered = unanswered_questions(vmessages) tree = {m.id: make_entry(m) for m in vmessages if m.top_reference is None} for m in vmessages: if m.id in tree: continue entry = make_entry(m) if m.top_reference_id in tree: parent = tree[m.top_reference_id] parent['replies'].append(entry) parent['timestamp'] = max(parent['timestamp'], entry['timestamp']) parent['has_new_message'] = max(parent['has_new_message'], entry['has_new_message']) else: tree[m.id] = entry if is_contest_admin(request): sort_key = lambda x: (x['needs_reply'], x['has_new_message'], x[ 'timestamp']) else: sort_key = lambda x: (x['has_new_message'], x['needs_reply'], x[ 'timestamp']) tree_list = sorted(list(tree.values()), key=sort_key, reverse=True) for entry in tree_list: entry['replies'].sort(key=sort_key, reverse=True) if request.user.is_authenticated: mark_messages_read(request.user, vmessages) return TemplateResponse(request, 'questions/tree.html', { 'tree_list': tree_list, 'form': form, })
def adjust_submission_form(self, request, form, problem_instance): super(TeamsMixinForContestController, self).adjust_submission_form( request, form, problem_instance ) try: tm = TeamMembership.objects.get( user=request.user, team__contest=request.contest ) if not is_contest_admin(request): form.fields['user'] = UserSelectionField( initial=tm.team.user, label=_("Team name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), help_text=_( "You are in the team, so submission will" " be sent as the team." ), ) def clean_user(): user = form.cleaned_data['user'] try: tm = TeamMembership.objects.get( user=request.user, team__contest=request.contest ) if user != tm.team.user: raise forms.ValidationError( _("You can't submit a" " solution for another team!") ) return user except TeamMembership.DoesNotExist: raise forms.ValidationError(_("Team does not exist")) form.clean_user = clean_user else: form.fields['team'] = forms.CharField( initial=tm.team.name, label=_("Team name"), widget=forms.TextInput(attrs={'readonly': 'readonly'}), help_text=_( "You are in the team, but you are also the " "admin, so you can send solution as the " "team user or as yourself." ), ) except TeamMembership.DoesNotExist: pass
def serialize_ranking(self, request, key): controller = request.contest.controller rounds = list(self._rounds_for_ranking(request, key)) # If at least one visible round is not trial we don't want to show # trial rounds in default ranking. if key == CONTEST_RANKING_KEY: not_trial = [r for r in rounds if not r.is_trial] if not_trial: rounds = not_trial freeze_times = [ controller.get_round_freeze_time(round) for round in rounds ] pis = list( ProblemInstance.objects.filter(round__in=rounds).select_related( 'problem').prefetch_related('round')) rtopis = defaultdict(lambda: []) for pi in pis: rtopis[pi.round].append(pi) users = self.filter_users_for_ranking(request, key, User.objects.all()) results = [] ccontroller = self.contest.controller frozen = False for round, freeze_time in zip(rounds, freeze_times): rpis = rtopis[round] rtimes = ccontroller.get_round_times(request, round) if freeze_time is None or \ is_contest_admin(request) or \ rtimes.results_visible(request.timestamp) or \ request.timestamp <= freeze_time: results += UserResultForProblem.objects \ .filter(problem_instance__in=rpis, user__in=users) \ .prefetch_related('problem_instance__round') else: results += self._get_old_results(request, freeze_time, rpis, users) frozen = True data = self._get_users_results(pis, results, rounds, users) self._assign_places(data, itemgetter('sum')) return {'rows': data, 'problem_instances': pis, 'frozen': frozen}
def message_view(request, message_id): message = get_object_or_404(Message, id=message_id, contest_id=request.contest.id) vmessages = visible_messages(request) if not vmessages.filter(id=message_id): raise PermissionDenied if message.top_reference_id is None: replies = list(vmessages.filter(top_reference=message)) replies.sort(key=Message.get_user_date) else: replies = [] if is_contest_admin(request) and message.kind == 'QUESTION' and \ message.can_have_replies: if request.method == 'POST': form = AddReplyForm(request, request.POST) if request.POST.get('just_reload') != 'yes' and form.is_valid(): instance = form.save(commit=False) instance.top_reference = message instance.author = request.user instance.date = request.timestamp instance.save() log_addition(request, instance) return redirect('contest_messages', contest_id=request.contest.id) elif request.POST.get('just_reload') == 'yes': form.is_bound = False else: form = AddReplyForm(request, initial={ 'topic': _("Re: ") + message.topic, }) else: form = None if request.user.is_authenticated: mark_messages_read(request.user, [message] + replies) return TemplateResponse( request, 'questions/message.html', { 'message': message, 'replies': replies, 'form': form, 'reply_to_id': message.top_reference_id or message.id, 'timestamp': request_time_seconds(request) })
def adjust_submission_form(self, request, form): size_limit = self.get_submission_size_limit() def validate_file_size(file): if file.size > size_limit: raise ValidationError(_("File size limit exceeded.")) def validate_language(file): ext = self._get_language(file) if ext not in self.get_allowed_extensions(): raise ValidationError(_( "Unknown or not supported file extension.")) form.fields['file'] = forms.FileField(allow_empty_file=False, validators=[validate_file_size, validate_language], label=_("File"), help_text=_("Language is determined by the file extension." " It has to be one of: %s.") % (', '.join(self.get_allowed_extensions()),) ) if is_contest_admin(request): form.fields['user'] = forms.CharField(label=_("User"), initial=request.user.username) def clean_user(): username = form.cleaned_data['user'] if username == request.user.username: return request.user qs = User.objects.filter(username=username) try: if request.user.is_superuser: return qs.get() else: return self.registration_controller() \ .filter_participants(qs) \ .get() except User.DoesNotExist: raise forms.ValidationError(_( "User does not exist or " "you do not have enough privileges")) form.clean_user = clean_user form.fields['kind'] = forms.ChoiceField(choices=[ ('NORMAL', _("Normal")), ('IGNORED', _("Ignored"))], initial=form.kind, label=_("Kind"))
def _render_contestwide_disqualification_reason(self, request, user): """Renders part with reason of the given user disqualification not directly associated with any particular submission. This method is only used internally. """ reasons = Disqualification.objects.filter(user=user, contest=request.contest, submission__isnull=True) if not is_contest_admin(request): reasons = reasons.filter(guilty=True) if not reasons: return None return render_to_string('disqualification/reason.html', request=request, context={'reasons': reasons})
def filter_my_visible_submissions(self, request, queryset): """Returns the submissions which the user should see in the "My submissions" view. The default implementation returns all submissions belonging to the user for the problems that are visible. Should return the updated queryset. """ if not request.user.is_authenticated(): return queryset.none() qs = queryset.filter(user=request.user) \ .filter(problem_instance__in=visible_problem_instances(request)) if is_contest_admin(request): return qs else: return qs.filter(date__lte=request.timestamp)