Merge pull request #3090 from modoboa/fix/csrf_issue_logout

Fixed CSRF vulnerability on logout view
This commit is contained in:
Antoine Nguyen
2023-10-17 15:06:30 +02:00
committed by GitHub
6 changed files with 47 additions and 20 deletions
+12 -8
View File
@@ -79,11 +79,11 @@ def admin_menu(selection, user):
@register.simple_tag
def user_menu(user, selection):
def user_menu(request, selection):
entries = [
{"name": "user",
"img": "fa fa-user",
"label": user.fullname,
"label": request.user.fullname,
"menu": [
{"name": "settings",
"img": "fa fa-list",
@@ -93,17 +93,21 @@ def user_menu(user, selection):
]
extra_entries = signals.extra_user_menu_entries.send(
sender="user_menu", location="options_menu", user=user)
sender="user_menu", location="options_menu", user=request.user)
extra_entries = reduce(
lambda a, b: a + b, [entry[1] for entry in extra_entries])
entries[0]["menu"] += (
extra_entries + [{"name": "logout",
"url": reverse("core:logout"),
"label": _("Logout"),
"img": "fa fa-sign-out"}]
extra_entries + [{
"name": "logout",
"url": reverse("core:logout"),
"label": _("Logout"),
"img": "fa fa-sign-out",
"method": "post"
}]
)
return render_to_string("common/menulist.html", {
"selection": selection, "entries": entries, "user": user
"request": request, "selection": selection,
"entries": entries, "user": request.user
})
+2
View File
@@ -16,6 +16,7 @@ from django.utils.http import urlsafe_base64_encode
from django.utils.translation import gettext as _
from django.views import generic
from django.views.decorators.cache import never_cache
from django.views.decorators.http import require_http_methods
from django.contrib.auth import (
authenticate, login, logout, views as auth_views
@@ -126,6 +127,7 @@ def dologin(request):
dologin = never_cache(dologin)
@require_http_methods(["POST"])
def dologout(request):
"""Logout current user."""
if not request.user.is_anonymous:
+10 -1
View File
@@ -3,7 +3,7 @@
from datetime import datetime
from django import template
from django.template import Context, Template
from django.template import Context, RequestContext, Template
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
@@ -51,6 +51,15 @@ class="{{ mdclass }}{% if link.class %} {{ link.class }}{% endif %}"
return t.render(Context({"link": linkdef, "mdclass": mdclass}))
@register.simple_tag
def render_post_link(linkdef, request):
t = Template("""<form method="post" action="{{ link.url }}">
{% csrf_token %}
<a class="menu-link" href="#" onclick="this.parentNode.submit()">{% if link.img %}<i class="{{ link.img }}"></i>{% endif %}{{ link.label }}</a>
</form>""")
return t.render(RequestContext(request, {"link": linkdef}))
@register.simple_tag
def progress_color(value):
value = int(value)
+15 -7
View File
@@ -1,6 +1,6 @@
/* ------- Media ------- */
.sidebar {
.sidebar {
display: none;
}
@@ -67,7 +67,7 @@
/* --------- general --------- */
.container-fluid {
.container-fluid {
padding-left: 0;
padding-right: 0;
}
@@ -101,7 +101,7 @@
/* Global */
body {
body {
padding-top: 50px;
padding-bottom: 50px;
}
@@ -168,7 +168,15 @@ label {
table-layout: fixed;
}
.menu-link {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
color: #333;
white-space: nowrap;
}
/* --------- main page --------- */
@@ -202,7 +210,7 @@ html body div.navbar div.container-fluid div#navigate-navbar-collapse.collapse u
padding-left: 20px;*/
}
.nav-sidebar > li > a:hover {
.nav-sidebar > li > a:hover {
background-color: #eee;
}
@@ -230,7 +238,7 @@ html body div.navbar div.container-fluid div#navigate-navbar-collapse.collapse u
margin-bottom: 4px;
}
.main {
.main {
padding: 20px 15px;
}
@@ -280,7 +288,7 @@ table td[name="actions"] {
/* modals */
.modal-body .nav-pills {
.modal-body .nav-pills {
margin-bottom: 15px;
}
+7 -3
View File
@@ -4,19 +4,23 @@
<li class="divider">&nbsp;</li>
{% else %}
{% if entry.menu %}
<li class="dropdown {{ entry.class }}{% if selection == entry.name %} active{% endif %}">
<li class="dropdown {{ entry.class }}{% if selection == entry.name %} active{% endif %}">
<a class="dropdown-toggle" name="{{ entry.name }}" data-toggle="dropdown" href="{{ entry.url }}">
{% if entry.img %}<span class="{{ entry.img }}"></span> {% endif %}{{ entry.label }}
</a>
<ul class="dropdown-menu" {% if entry.width %}style="width: {{ entry.width }}px"{% endif %}>
{% for sentry in entry.menu %}
<li>{% render_link sentry %}</li>
<li>{% if sentry.method == "post" %}{% render_post_link sentry request %}{% else %}{% render_link sentry %}{% endif %}</li>
{% endfor %}
</ul>
</li>
{% else %}
<li class="{% if selection == entry.name %}active{% endif %}">
{% render_link entry %}
{% if entry.method == "post" %}
{% render_post_link entry request %}
{% else %}
{% render_link entry %}
{% endif %}
</li>
{% endif %}
{% endif %}
+1 -1
View File
@@ -60,7 +60,7 @@
{% endif %}
</ul>
<ul class="nav navbar-nav navbar-right">
{% if selection %}{% user_menu user selection %}{% else %}{% user_menu user "" %}{% endif %}
{% if selection %}{% user_menu request selection %}{% else %}{% user_menu request "" %}{% endif %}
</ul>
{% include "common/top_notifications.html" %}
</div>