Commit 529cdf7e authored by Enrico Zini's avatar Enrico Zini
Browse files

Moved Impersonate view to its own app, activate by POST instead of GET, made...

Moved Impersonate view to its own app, activate by POST instead of GET, made view work with any user model. refs: #12
parent 3e7c587b
......@@ -39,9 +39,9 @@ class VisitorMixin(NM2LayoutMixin):
# Implement impersonation if requested in session
if self.visitor.is_admin:
key = self.request.session.get("impersonate", None)
if key is not None:
p = bmodels.Person.lookup(key)
pk = self.request.session.get("impersonate", None)
if pk is not None:
p = bmodels.Person.objects.get(pk=pk)
if p is not None:
self.impersonator = self.visitor
self.visitor = p
......@@ -121,11 +121,6 @@ class VisitPersonMixin(VisitorMixin):
if "am_candidate" in self.person.perms:
res.append(NavLink(
reverse("admin:backend_am_add") + f"?person={self.person.id}", _("Make AM")))
if self.visitor != self.person:
res.append(NavLink(
reverse("impersonate", kwargs={
"key": self.person.lookup_key}) + f"?url={self.request.build_absolute_uri()}",
_("Impersonate"), "random"))
if self.person.is_dd:
res.append(NavLink(
reverse("mia_wat_ping", kwargs={"key": self.person.lookup_key}), _("WAT ping"), "heartbeat"))
......
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class ImpersonateConfig(AppConfig):
name = 'impersonate'
from django.db import models
# Create your models here.
from django.test import TestCase
# Create your tests here.
from __future__ import annotations
from django.urls import path
from . import views
urlpatterns = [
# Impersonate a user
path('impersonate/', views.Impersonate.as_view(), name="impersonate"),
]
from __future__ import annotations
from django.utils.translation import ugettext as _
from django.views.generic import View
from django.shortcuts import redirect
from django.core.exceptions import PermissionDenied
from django.contrib import messages
from django.contrib.auth import get_user_model
class Impersonate(View):
def post(self, request, *args, **kw):
User = get_user_model()
effective_user = getattr(request, "impersonator", None)
if effective_user is None:
effective_user = request.user
if not effective_user.is_authenticated or not effective_user.is_admin:
raise PermissionDenied
pk = request.POST.get("pk")
if pk is None:
del request.session["impersonate"]
messages.add_message(request, messages.INFO, _("Impersonation canceled"))
user = effective_user
else:
user = User.objects.get(pk=pk)
request.session["impersonate"] = user.pk
messages.info(request, _("Impersonating {}").format(user))
url = request.POST.get("next", None)
if url is None:
return redirect(user.get_absolute_url())
else:
return redirect(url)
......@@ -74,6 +74,7 @@ INSTALLED_APPS = [
'sitechecks',
'deploy',
'signon',
'impersonate',
]
MIDDLEWARE = [
......
......@@ -44,10 +44,9 @@ urlpatterns = [
path('minechangelogs/', include("minechangelogs.urls")),
path('sitechecks/', include("sitechecks.urls")),
path('deploy/', include("deploy.urls")),
path('rest/api/', include(router.urls)),
path('signon/', include("signon.urls")),
path('impersonate/', include("impersonate.urls")),
# Uncomment the admin/doc line below to enable admin documentation:
path('admin/doc/', include('django.contrib.admindocs.urls')),
......
......@@ -37,6 +37,13 @@ window.nm2.url_api_people = "{% url 'api_people' %}";
{% for link in navbar.person %}
<a class="dropdown-item" href="{{link.url}}">{% if link.icon %}<span class="fa fa-{{link.icon}}"></span> {% endif %}{{link.label}}</a>
{% endfor %}
{% if visitor != person %}
<form class="form-inline" method="POST" action="{% url 'impersonate' %}">{% csrf_token %}
<input type="hidden" name="pk" value="{{person.pk}}">
<input type="hidden" name="next" value="{{request.build_absolute_uri}}">
<button class="dropdown-item btn btn-link" type="submit"><span class="fa fa-random"></span> {% trans "Impersonate" %}</button>
</form>
{% endif %}
</div>
</li>
{% endif %}
......@@ -72,7 +79,10 @@ window.nm2.url_api_people = "{% url 'api_people' %}";
<div class="dropdown-menu dropdown-menu-right" role="menu" aria-labelledby="navbarDropdown">
{% block visitor_menu %}
{% if impersonator %}
<a class="dropdown-item" href="{% url 'impersonate' %}?url={{request.build_absolute_uri}}"><span class="fa fa-random"></span> (really {{impersonator.lookup_key}})</a>
<form class="form-inline" method="POST" action="{% url 'impersonate' %}">{% csrf_token %}
<input type="hidden" name="next" value="{{request.build_absolute_uri}}">
<button class="dropdown-item btn btn-link" type="submit"><span class="fa fa-random"></span> (really {{impersonator.lookup_key}})</button>
</form>
{% endif %}
{% if user.is_anonymous %}
<a class="dropdown-item" href="{% url 'dm_claim' %}">{% trans "claim account" %}</a>
......@@ -112,8 +122,10 @@ window.nm2.url_api_people = "{% url 'api_people' %}";
{% if impersonator %}
<div id="impersonation" class="container-fluid bg-warning">
<span class="badge badge-pill badge-light"><span class="fa fa-random"></span> {{impersonator.a_link}} as {{visitor.a_link}}</span>
<a class="badge badge-pill badge-primary" href="{% url 'impersonate' %}?url={{request.build_absolute_uri}}">{% trans "Cancel" %}</a>
<br>
<form class="form-inline" method="POST" action="{% url 'impersonate' %}">{% csrf_token %}
<input type="hidden" name="next" value="{{request.build_absolute_uri}}">
<button class="badge badge-pill badge-primary" type="submit">{% trans "Cancel" %}</button>
</form>
{% for perm in visit_perms %}<span class="badge badge-pill badge-info mr-1">{{perm}}</span>{% endfor %}
</div>
{% endif %}
......
......@@ -2,8 +2,6 @@ from django.urls import path
from . import views
urlpatterns = [
# Impersonate a user
path('impersonate/<key>/', views.Impersonate.as_view(), name="impersonate"),
# Export database
path('db-export/', views.DBExport.as_view(), name="restricted_db_export"),
# Mailbox stats
......
......@@ -2,11 +2,8 @@ from __future__ import annotations
from django import http
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
from django.core.exceptions import PermissionDenied
from django.views.generic import View
from django.contrib import messages
from django.contrib.sites.shortcuts import get_current_site
import backend.models as bmodels
import backend.const as const
......@@ -114,26 +111,6 @@ class SalsaExport(VisitorMixin, View):
return res
class Impersonate(View):
def get(self, request, key=None, *args, **kw):
visitor = request.user
if not visitor.is_authenticated or not visitor.is_admin:
raise PermissionDenied
if key is None:
del request.session["impersonate"]
messages.add_message(request, messages.INFO, _("Impersonation canceled"))
else:
person = bmodels.Person.lookup_or_404(key)
request.session["impersonate"] = person.lookup_key
messages.info(request, _("Impersonating {}").format(person.lookup_key))
url = request.GET.get("url", None)
if url is None:
return redirect('home')
else:
return redirect(url)
class MailboxStats(VisitorTemplateView):
template_name = "restricted/mailbox-stats.html"
require_visitor = "admin"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment