Coverage for src/mesh/views/views_user.py: 35%
67 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-28 07:45 +0000
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-28 07:45 +0000
1from typing import Any
3from django.contrib import messages
4from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login, logout
5from django.contrib.auth.mixins import LoginRequiredMixin
6from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect
7from django.urls import reverse_lazy
8from django.utils.translation import gettext_lazy as _
9from django.views.generic import FormView, View
11from mesh.model.roles.editor import Editor
12from mesh.model.roles.journal_manager import JournalManager
13from mesh.model.user.user_interfaces import ImpersonateData, UserInfo
14from mesh.views.forms.user_forms import UserForm
15from mesh.views.mixins import RoleMixin
17from ..models.user_models import USER_TOKEN_QUERY_PARAM
18from .components.breadcrumb import get_base_breadcrumb
21class InitImpersonateSessionView(RoleMixin, FormView):
22 form_class = UserForm
23 template_name = "mesh/forms/form_full_page.html"
24 restricted_roles = [JournalManager, Editor]
26 def restrict_dispatch(self, request: HttpRequest, *args, **kwargs):
27 """
28 Check that the user is not currently in impersonate mode (deny
29 recursively impersonating user, too messy).
30 """
31 if "impersonate_target_id" in self.request.session:
32 return True
33 return not self.role_handler.check_rights("can_impersonate")
35 def get_form_kwargs(self) -> dict[str, Any]:
36 """
37 Adds the _users queryset of availabe users for impersonating when instantiating
38 the form.
39 """
40 kwargs = super().get_form_kwargs()
41 kwargs["_users"] = self.role_handler.get_attribute("managed_users")
43 return kwargs
45 def get_success_url(self) -> str:
46 return reverse_lazy("mesh:home")
48 def form_valid(self, form: UserForm) -> HttpResponse:
49 """
50 Serializes the impersonate data in the current session.
51 """
52 user = form.cleaned_data["user"]
54 user_info = UserInfo.from_user(self.request.user) # type:ignore
56 data = ImpersonateData(source=user_info, target_id=user.pk)
57 data.serialize(self.request.session)
59 return super().form_valid(form)
61 def get_context_data(self, *args, **kwargs):
62 context = super().get_context_data(*args, **kwargs)
64 context["page_title"] = _("Choose user to impersonate")
66 # Generate breadcrumb data
67 breadcrumb = get_base_breadcrumb()
68 breadcrumb.add_item(title=_("Impersonate user"), url=reverse_lazy("mesh:impersonate_init"))
69 context["breadcrumb"] = breadcrumb
70 return context
73class CloseImpersonateSessionView(LoginRequiredMixin, View):
74 """
75 Cleans the current session of all impersonating related variables.
76 """
78 def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
79 ImpersonateData.clean_session(request.session)
80 redirect_url = request.headers.get("referer", reverse_lazy("mesh:home"))
81 return HttpResponseRedirect(redirect_url)
84# @method_decorator(rate_limit(action="token_authentication"), name="dispatch")
85# We would like to protect this view with a rate limit mechanism.
86# Unfortunately the django-allauth rate limiter does not support GET requests..
87class TokenLoginView(View):
88 """
89 View to login using an `UserToken`.
90 """
92 def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
93 token = request.GET.get(USER_TOKEN_QUERY_PARAM)
94 if not token:
95 raise Http404
97 response = HttpResponseRedirect(reverse_lazy("mesh:home"))
99 user = authenticate(request, token=token)
100 if not user:
101 messages.warning(
102 request,
103 _(
104 "The given authentication token is invalid, expired or "
105 "you're not allowed to use token authentication."
106 ),
107 )
108 return response
110 # Check for redirection
111 redirect_uri = request.GET.get(REDIRECT_FIELD_NAME)
112 if redirect_uri:
113 response = HttpResponseRedirect(redirect_uri)
115 # Handle already populated user instance by the default `AuthenticationMiddleware`
116 if hasattr(request, "user"):
117 # Same user requesting authentication -> Nothing to do.
118 if request.user.is_authenticated and request.user.pk == user.pk:
119 return response
121 logout(request)
123 request.user = user
124 login(request, user)
126 return response