From 28b30e0e786647f7d6b8f9afd87ed20da243d105 Mon Sep 17 00:00:00 2001 From: Tomasz Kwiatkowski <41270545+geoff128@users.noreply.github.com> Date: Mon, 1 Apr 2024 21:41:41 +0200 Subject: [PATCH] Contest archiving update (#357) * Fix translation block in confirm_archive_contest.html * Remove unused utility function * Disallow adding problems, time extensions when archived --- oioioi/contests/admin.py | 31 +++++++++++++++++++ oioioi/contests/forms.py | 2 +- .../contests/probleminstance/change_list.html | 2 ++ .../contests/confirm_archive_contest.html | 14 +++++---- oioioi/contests/utils.py | 10 ------ oioioi/problems/utils.py | 9 ++++-- oioioi/problems/views.py | 10 +++++- oioioi/timeline/views.py | 4 +-- 8 files changed, 60 insertions(+), 22 deletions(-) diff --git a/oioioi/contests/admin.py b/oioioi/contests/admin.py index 147cd17cc..35b1c05b8 100644 --- a/oioioi/contests/admin.py +++ b/oioioi/contests/admin.py @@ -50,6 +50,7 @@ can_admin_contest, get_inline_for_contest, is_contest_admin, + is_contest_archived, is_contest_basicadmin, is_contest_observer, ) @@ -380,11 +381,20 @@ def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): + if is_contest_archived(request): + return False return is_contest_basicadmin(request) def has_delete_permission(self, request, obj=None): + if is_contest_archived(request): + return False return self.has_change_permission(request, obj) + def has_view_permission(self, request, obj=None): + if is_contest_archived(request): + return is_contest_basicadmin(request) + return super(ProblemInstanceAdmin, self).has_view_permission(request, obj) + def _problem_change_href(self, instance): came_from = reverse('oioioiadmin:contests_probleminstance_changelist') came_from_arg = urllib.parse.urlencode({'came_from': came_from}) @@ -493,6 +503,9 @@ def inline_actions(self, instance): return result def actions_field(self, instance): + request = self._request_local.request + if is_contest_archived(request): + return _("Unarchive the contest to change this problem.") return make_html_links(self.inline_actions(instance)) actions_field.short_description = _("Actions") @@ -565,6 +578,13 @@ def get_queryset(self, request): return qs + def changelist_view(self, request, extra_context=None): + extra_context = extra_context or {} + extra_context['show_add_button'] = not is_contest_archived(request) + return super(ProblemInstanceAdmin, self).changelist_view( + request, extra_context=extra_context + ) + contest_site.contest_register(ProblemInstance, ProblemInstanceAdmin) @@ -973,14 +993,25 @@ class RoundTimeExtensionAdmin(admin.ModelAdmin): search_fields = ['user__username', 'user__last_name'] def has_add_permission(self, request): + if is_contest_archived(request): + return False return is_contest_admin(request) def has_change_permission(self, request, obj=None): + if is_contest_archived(request): + return False return is_contest_admin(request) def has_delete_permission(self, request, obj=None): + if is_contest_archived(request): + return False return self.has_change_permission(request, obj) + def has_view_permission(self, request, obj=None): + if is_contest_archived(request): + return is_contest_admin(request) + return super().has_view_permission(request, obj) + def user_login(self, instance): if not instance.user: return '' diff --git a/oioioi/contests/forms.py b/oioioi/contests/forms.py index b4cf40e41..8d60604d9 100644 --- a/oioioi/contests/forms.py +++ b/oioioi/contests/forms.py @@ -106,7 +106,7 @@ class ProblemInstanceForm(forms.ModelForm): def __init__(self, *args, **kwargs): instance = kwargs.get('instance') super(ProblemInstanceForm, self).__init__(*args, **kwargs) - if instance: + if instance and not instance.contest.is_archived: self.fields['round'].queryset = instance.contest.round_set self.fields['round'].required = True diff --git a/oioioi/contests/templates/admin/contests/probleminstance/change_list.html b/oioioi/contests/templates/admin/contests/probleminstance/change_list.html index 99cb69268..9eb15b323 100644 --- a/oioioi/contests/templates/admin/contests/probleminstance/change_list.html +++ b/oioioi/contests/templates/admin/contests/probleminstance/change_list.html @@ -2,5 +2,7 @@ {% load i18n %} {% block object-tools-items %} +{% if show_add_button %} {% trans "Add problem" %} +{% endif %} {% endblock %} diff --git a/oioioi/contests/templates/contests/confirm_archive_contest.html b/oioioi/contests/templates/contests/confirm_archive_contest.html index 8d40d36b5..7aeff2425 100644 --- a/oioioi/contests/templates/contests/confirm_archive_contest.html +++ b/oioioi/contests/templates/contests/confirm_archive_contest.html @@ -5,14 +5,16 @@ {% block confirmation_header %}{% trans "Confirm contest archive" %}{% endblock %} {% block confirmation_form_explanation %}
- {% trans "Contest archiving will make contest \"read only\" which means nobody will be able to: " %} + {% blocktrans %} + Archiving will make the contest 'read-only', which means nobody will be able to:
diff --git a/oioioi/contests/utils.py b/oioioi/contests/utils.py index 59d5a2dd3..414276d79 100644 --- a/oioioi/contests/utils.py +++ b/oioioi/contests/utils.py @@ -303,16 +303,6 @@ def administered_contests(request): ] -@request_cached -def administered_unarchived_contests(request): - """Returns a list of unarchived contests for which the logged - user has contest_admin permission for. - """ - return [ - contest for contest in administered_contests(request) if not contest.is_archived - ] - - @make_request_condition @request_cached def is_contest_admin(request): diff --git a/oioioi/problems/utils.py b/oioioi/problems/utils.py index 90005b1d8..4dbdbd810 100644 --- a/oioioi/problems/utils.py +++ b/oioioi/problems/utils.py @@ -224,8 +224,12 @@ def generate_add_to_contest_metadata(request): "add to contest" functionality in problemset. """ - administered = administered_contests(request) - # If user doesn't own any contest we won't show the option. + administered = [ + contest + for contest in administered_contests(request) + if not contest.is_archived + ] + # If user doesn't own any unarchived contest we won't show the option. if administered: show_add_button = True else: @@ -239,6 +243,7 @@ def generate_add_to_contest_metadata(request): contest for contest in rcontests if request.user.has_perm('contests.contest_admin', contest) + and not contest.is_archived ] return show_add_button, administered_recent_contests diff --git a/oioioi/problems/views.py b/oioioi/problems/views.py index bd5390c4f..c296a97f3 100644 --- a/oioioi/problems/views.py +++ b/oioioi/problems/views.py @@ -142,6 +142,9 @@ def download_package_traceback_view(request, package_id): def add_or_update_problem(request, contest, template): + if contest and contest.is_archived: + raise PermissionDenied + if 'problem' in request.GET: existing_problem = get_object_or_404(Problem, id=request.GET['problem']) if ( @@ -612,6 +615,11 @@ def problemset_add_to_contest_view(request, site_key): raise Http404 administered = administered_contests(request) administered = sorted(administered, key=lambda x: x.creation_date, reverse=True) + administered = [ + contest + for contest in administered + if not contest.is_archived + ] problemset_tabs = generate_problemset_tabs(request) problemset_tabs.append( { @@ -677,7 +685,7 @@ def get_report_row_begin_HTML_view(request, submission_id): @transaction.non_atomic_requests def problemset_add_or_update_problem_view(request): if not can_add_to_problemset(request): - if request.contest: + if request.contest and not request.contest.is_archived: url = ( reverse('add_or_update_problem') + '?' diff --git a/oioioi/timeline/views.py b/oioioi/timeline/views.py index fbe353986..a4f514c39 100644 --- a/oioioi/timeline/views.py +++ b/oioioi/timeline/views.py @@ -13,7 +13,7 @@ from oioioi.contests.date_registration import date_registry from oioioi.contests.menu import contest_admin_menu_registry from oioioi.contests.models import Round -from oioioi.contests.utils import contest_exists, is_contest_admin +from oioioi.contests.utils import contest_exists, is_contest_admin, is_contest_archived def _get_date_id(registry_item): @@ -52,7 +52,7 @@ def _translate_field(field, obj): _("Timeline"), lambda request: reverse('timeline_view', kwargs={'contest_id': request.contest.id}), ) -@enforce_condition(contest_exists & is_contest_admin) +@enforce_condition(contest_exists & is_contest_admin & ~is_contest_archived) def timeline_view(request): registry = date_registry.tolist(request.contest.id) group_registry = _make_group_registry(registry)