mirror of
https://github.com/DMOJ/online-judge.git
synced 2024-11-25 16:32:37 +08:00
Protect stateful admin endpoints against CSRF
This commit is contained in:
parent
2b36e045c7
commit
8cebcedfa2
@ -8,8 +8,10 @@ from django.http import Http404, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import path, reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import gettext_lazy as _, ngettext
|
||||
from django.views.decorators.http import require_POST
|
||||
from reversion.admin import VersionAdmin
|
||||
|
||||
from django_ace import AceWidget
|
||||
@ -73,7 +75,7 @@ class ContestProblemInline(SortableInlineAdminMixin, admin.TabularInline):
|
||||
def rejudge_column(self, obj):
|
||||
if obj.id is None:
|
||||
return ''
|
||||
return format_html('<a class="button rejudge-link" href="{0}">{1}</a>',
|
||||
return format_html('<a class="button rejudge-link action-link" href="{0}">{1}</a>',
|
||||
reverse('admin:judge_contest_rejudge', args=(obj.contest.id, obj.id)), _('Rejudge'))
|
||||
|
||||
|
||||
@ -272,6 +274,7 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
|
||||
path('<int:contest_id>/judge/<int:problem_id>/', self.rejudge_view, name='judge_contest_rejudge'),
|
||||
] + super(ContestAdmin, self).get_urls()
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def rejudge_view(self, request, contest_id, problem_id):
|
||||
contest = get_object_or_404(Contest, id=contest_id)
|
||||
if not self.has_change_permission(request, contest):
|
||||
@ -285,6 +288,7 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
|
||||
len(queryset)) % len(queryset))
|
||||
return HttpResponseRedirect(reverse('admin:judge_contest_change', args=(contest_id,)))
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def rate_all_view(self, request):
|
||||
if not request.user.has_perm('judge.contest_rating'):
|
||||
raise PermissionDenied()
|
||||
@ -296,6 +300,7 @@ class ContestAdmin(NoBatchDeleteMixin, VersionAdmin):
|
||||
rate_contest(contest)
|
||||
return HttpResponseRedirect(reverse('admin:judge_contest_changelist'))
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def rate_view(self, request, id):
|
||||
if not request.user.has_perm('judge.contest_rating'):
|
||||
raise PermissionDenied()
|
||||
|
@ -4,9 +4,11 @@ from django.forms import ModelForm, TextInput
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import path, reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_POST
|
||||
from reversion.admin import VersionAdmin
|
||||
|
||||
from django_ace import AceWidget
|
||||
@ -85,18 +87,21 @@ class JudgeAdmin(VersionAdmin):
|
||||
judge.disconnect(force=force)
|
||||
return HttpResponseRedirect(reverse('admin:judge_judge_changelist'))
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def disconnect_view(self, request, id):
|
||||
judge = get_object_or_404(Judge, id=id)
|
||||
if not self.has_change_permission(request, judge):
|
||||
raise PermissionDenied()
|
||||
return self.disconnect_judge(id)
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def terminate_view(self, request, id):
|
||||
judge = get_object_or_404(Judge, id=id)
|
||||
if not self.has_change_permission(request, judge):
|
||||
raise PermissionDenied()
|
||||
return self.disconnect_judge(id, force=True)
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def disable_view(self, request, id):
|
||||
judge = get_object_or_404(Judge, id=id)
|
||||
if not self.has_change_permission(request, judge):
|
||||
|
@ -9,8 +9,10 @@ from django.db.models import Q
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import path, reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import gettext, gettext_lazy as _, ngettext, pgettext
|
||||
from django.views.decorators.http import require_POST
|
||||
from reversion.admin import VersionAdmin
|
||||
|
||||
from django_ace import AceWidget
|
||||
@ -250,6 +252,7 @@ class SubmissionAdmin(VersionAdmin):
|
||||
path('<int:id>/judge/', self.judge_view, name='judge_submission_rejudge'),
|
||||
] + super(SubmissionAdmin, self).get_urls()
|
||||
|
||||
@method_decorator(require_POST)
|
||||
def judge_view(self, request, id):
|
||||
if not request.user.has_perm('judge.rejudge_submission') or not request.user.has_perm('judge.edit_own_problem'):
|
||||
raise PermissionDenied()
|
||||
|
15
templates/admin/base_site.html
Normal file
15
templates/admin/base_site.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends "admin/base_site.html" %}
|
||||
|
||||
{% block pretitle %}{{ block.super }}
|
||||
<form style="display: none" id="empty-action-form" method="post">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
<script>
|
||||
django.jQuery(function ($) {
|
||||
$('.action-link').on('click', function () {
|
||||
$('#empty-action-form').attr('action', this.href).trigger('submit');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -15,7 +15,7 @@
|
||||
{% block after_field_sets %}{{ block.super }}
|
||||
{% if original and original.is_rated and original.ended and perms.judge.contest_rating %}
|
||||
<a style="display: none" title="{% trans "Rate" %}" href="{% url 'admin:judge_contest_rate' original.pk %}"
|
||||
class="button rerate-link">
|
||||
class="button rerate-link action-link">
|
||||
<i class="fa fa-lg fa-signal"></i>
|
||||
<span class="text">{% trans "Rate" %}</span>
|
||||
</a>
|
||||
|
@ -5,7 +5,7 @@
|
||||
{{ block.super }}
|
||||
{% if not is_popup and perms.judge.contest_rating %}
|
||||
<li>
|
||||
<a href="{% url 'admin:judge_contest_rate_all' %}" class="ratealllink">
|
||||
<a href="{% url 'admin:judge_contest_rate_all' %}" class="ratealllink action-link">
|
||||
<i class="fa fa-signal"></i> {% trans "Rate all ratable contests" %}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -14,24 +14,24 @@
|
||||
{% block after_field_sets %}{{ block.super }}
|
||||
{% if original %}
|
||||
<a style="display: none" title="{% trans "Disconnect" %}" href="{% url 'admin:judge_judge_disconnect' original.pk %}"
|
||||
class="button disconnect-link">
|
||||
class="button disconnect-link action-link">
|
||||
<i class="fa fa-lg fa-power-off"></i>
|
||||
<span class="text">{% trans "Disconnect" %}</span>
|
||||
</a>
|
||||
<a style="display: none" title="{% trans "Terminate" %}" href="{% url 'admin:judge_judge_terminate' original.pk %}"
|
||||
class="button terminate-link">
|
||||
class="button terminate-link action-link">
|
||||
<i class="fa fa-lg fa-plug"></i>
|
||||
<span class="text">{% trans "Terminate" %}</span>
|
||||
</a>
|
||||
{% if not original.is_disabled %}
|
||||
<a style="display: none" title="{% trans "Disable" %}" href="{% url 'admin:judge_judge_disable' original.pk %}"
|
||||
class="button disable-link">
|
||||
class="button disable-link action-link">
|
||||
<i class="fa fa-lg fa-times"></i>
|
||||
<span class="text">{% trans "Disable" %}</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<a style="display: none" title="{% trans "Enable" %}" href="{% url 'admin:judge_judge_disable' original.pk %}"
|
||||
class="button disable-link">
|
||||
class="button disable-link action-link">
|
||||
<i class="fa fa-lg fa-check"></i>
|
||||
<span class="text">{% trans "Enable" %}</span>
|
||||
</a>
|
||||
|
@ -12,7 +12,7 @@
|
||||
{% block after_field_sets %}{{ block.super }}
|
||||
{% if original and not original.is_locked %}
|
||||
<a style="display: none" title="{% trans "Rejudge" %}" href="{% url 'admin:judge_submission_rejudge' original.pk %}"
|
||||
class="button rejudgelink">
|
||||
class="button rejudgelink action-link">
|
||||
<i class="fa fa-lg fa-refresh"></i>
|
||||
<span class="text">{% trans "Rejudge" %}</span>
|
||||
</a>
|
||||
|
Loading…
Reference in New Issue
Block a user