diff --git a/backend/mixins.py b/backend/mixins.py index bdde115e45091116aca91926a22e38742370a399..3dbcaee4a3853b4d3e3357afb0a2440675d11396 100644 --- a/backend/mixins.py +++ b/backend/mixins.py @@ -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")) diff --git a/impersonate/__init__.py b/impersonate/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/impersonate/admin.py b/impersonate/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/impersonate/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/impersonate/apps.py b/impersonate/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..813354fd2598c7da2a4e471b88a9654d404bfed9 --- /dev/null +++ b/impersonate/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ImpersonateConfig(AppConfig): + name = 'impersonate' diff --git a/impersonate/migrations/__init__.py b/impersonate/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/impersonate/models.py b/impersonate/models.py new file mode 100644 index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91 --- /dev/null +++ b/impersonate/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/impersonate/tests.py b/impersonate/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/impersonate/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/impersonate/urls.py b/impersonate/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..ca1f4cee9615cca701801be05077c01b6f2c79da --- /dev/null +++ b/impersonate/urls.py @@ -0,0 +1,8 @@ +from __future__ import annotations +from django.urls import path +from . import views + +urlpatterns = [ + # Impersonate a user + path('impersonate/', views.Impersonate.as_view(), name="impersonate"), +] diff --git a/impersonate/views.py b/impersonate/views.py new file mode 100644 index 0000000000000000000000000000000000000000..8e940395a5579b56f6321542d6285df01796f128 --- /dev/null +++ b/impersonate/views.py @@ -0,0 +1,32 @@ +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) diff --git a/nm2/settings.py b/nm2/settings.py index 20c9e470836530cd7d17c68e194db0adf39ac24c..868d1d3f1d279fcd30ab0f4dd1f9d9db9ea900b0 100644 --- a/nm2/settings.py +++ b/nm2/settings.py @@ -74,6 +74,7 @@ INSTALLED_APPS = [ 'sitechecks', 'deploy', 'signon', + 'impersonate', ] MIDDLEWARE = [ diff --git a/nm2/urls.py b/nm2/urls.py index 1bdc10281ffa776dbf21e02bf4e87320bc4a5119..4c27f48e963a3d420a3ac314bddca0f6de7eef44 100644 --- a/nm2/urls.py +++ b/nm2/urls.py @@ -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')), diff --git a/nmlayout/templates/nm2-base.html b/nmlayout/templates/nm2-base.html index c9c1ffa652c0b4cc1fccf6105831be082383ec41..a411d3a629e70e56deba8640f95fc19b01300992 100644 --- a/nmlayout/templates/nm2-base.html +++ b/nmlayout/templates/nm2-base.html @@ -37,6 +37,13 @@ window.nm2.url_api_people = "{% url 'api_people' %}"; {% for link in navbar.person %} {% if link.icon %} {% endif %}{{link.label}} {% endfor %} + {% if visitor != person %} +
+ {% endif %} {% endif %} @@ -72,7 +79,10 @@ window.nm2.url_api_people = "{% url 'api_people' %}";