mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-10 04:06:47 +00:00
fix: require POST for user block/unblock and OTP email, flag console cookie
- user_block, user_unblock and admin_email_otp changed state on GET, so an <img> tag could lock a user out or trigger OTP emails through an admin's session. They now require POST; the buttons are CSRF forms. - The console token cookie is set with httponly, SameSite=Lax and, on HTTPS, secure. Only novncd reads it; the page gets the token directly.
This commit is contained in:
parent
e76149c71a
commit
cf1cde376b
8 changed files with 77 additions and 6 deletions
|
|
@ -60,9 +60,13 @@
|
|||
<a class="btn btn-success" title="{%trans "View Profile" %}" href="{% url 'accounts:account' user.id %}">{% bs_icon 'eye-fill' %}</a>
|
||||
<a class="btn btn-primary" title="{%trans "Edit" %}" href="{% url 'admin:user_update' user.id %}">{% bs_icon 'pencil-fill' %}</a>
|
||||
{% if user.is_active %}
|
||||
<a class="btn btn-warning" title="{%trans "Block" %}" href="{% url 'admin:user_block' user.id %}">{% bs_icon 'stop-fill' %}</a>
|
||||
<form method="post" action="{% url 'admin:user_block' user.id %}">{% csrf_token %}
|
||||
<button type="submit" class="btn btn-warning rounded-0" title="{%trans "Block" %}">{% bs_icon 'stop-fill' %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<a class="btn btn-success" title="{%trans "Unblock" %}" href="{% url 'admin:user_unblock' user.id %}">{% bs_icon 'play-fill' %}</a>
|
||||
<form method="post" action="{% url 'admin:user_unblock' user.id %}">{% csrf_token %}
|
||||
<button type="submit" class="btn btn-success rounded-0" title="{%trans "Unblock" %}">{% bs_icon 'play-fill' %}</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<a class="btn btn-danger" title="{%trans "Delete" %}" href="{% url 'admin:user_delete' user.id %}">{% bs_icon 'x-circle-fill' %}</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -102,11 +102,21 @@ class AdminTestCase(TestCase):
|
|||
self.assertEqual(ua.max_memory, 2048)
|
||||
self.assertEqual(ua.max_disk_size, 8)
|
||||
|
||||
# Blocking changes state, so a GET (e.g. an <img> tag) must not do it.
|
||||
User.objects.filter(id=user_id).update(is_active=True)
|
||||
response = self.client.get(reverse("admin:user_block", args=[user_id]))
|
||||
self.assertEqual(response.status_code, 405)
|
||||
self.assertTrue(User.objects.get(id=user_id).is_active)
|
||||
|
||||
response = self.client.post(reverse("admin:user_block", args=[user_id]))
|
||||
user = User.objects.get(id=user_id)
|
||||
self.assertFalse(user.is_active)
|
||||
|
||||
response = self.client.get(reverse("admin:user_unblock", args=[user_id]))
|
||||
self.assertEqual(response.status_code, 405)
|
||||
self.assertFalse(User.objects.get(id=user_id).is_active)
|
||||
|
||||
response = self.client.post(reverse("admin:user_unblock", args=[user_id]))
|
||||
user = User.objects.get(id=user_id)
|
||||
self.assertTrue(user.is_active)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from django.contrib.auth.models import Group, User
|
|||
from django.core.paginator import Paginator
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_POST
|
||||
from logs.models import Logs
|
||||
|
||||
from . import forms
|
||||
|
|
@ -180,6 +181,7 @@ def user_delete(request, pk):
|
|||
)
|
||||
|
||||
|
||||
@require_POST
|
||||
@superuser_only
|
||||
def user_block(request, pk):
|
||||
user: User = get_object_or_404(User, pk=pk)
|
||||
|
|
@ -188,6 +190,7 @@ def user_block(request, pk):
|
|||
return redirect("admin:user_list")
|
||||
|
||||
|
||||
@require_POST
|
||||
@superuser_only
|
||||
def user_unblock(request, pk):
|
||||
user: User = get_object_or_404(User, pk=pk)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue