Connect as other people

This commit is contained in:
Yohann D'ANELLO 2020-05-04 21:02:57 +02:00
parent 5ebf258eab
commit ac2790d327
6 changed files with 67 additions and 23 deletions

View File

@ -2,7 +2,7 @@ from django.urls import path
from django.views.generic import RedirectView from django.views.generic import RedirectView
from .views import CreateUserView, MyAccountView, UserDetailView,\ from .views import CreateUserView, MyAccountView, UserDetailView,\
ProfileListView, OrphanedProfileListView, OrganizersListView ProfileListView, OrphanedProfileListView, OrganizersListView, ResetAdminView
app_name = "member" app_name = "member"
@ -17,4 +17,5 @@ urlpatterns = [
path("profiles/", ProfileListView.as_view(), name="all_profiles"), path("profiles/", ProfileListView.as_view(), name="all_profiles"),
path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"), path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"),
path("organizers/", OrganizersListView.as_view(), name="organizers"), path("organizers/", OrganizersListView.as_view(), name="organizers"),
path("reset-admin/", ResetAdminView.as_view(), name="reset_admin"),
] ]

View File

@ -1,7 +1,9 @@
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Q from django.db.models import Q
from django.http import FileResponse from django.http import FileResponse
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views import View from django.views import View
from django.views.generic import CreateView, UpdateView, DetailView from django.views.generic import CreateView, UpdateView, DetailView
@ -31,15 +33,29 @@ class MyAccountView(LoginRequiredMixin, UpdateView):
class UserDetailView(LoginRequiredMixin, DetailView): class UserDetailView(LoginRequiredMixin, DetailView):
model = TFJMUser model = TFJMUser
form_class = TFJMUserForm form_class = TFJMUserForm
context_object_name = "user" context_object_name = "tfjmuser"
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
raise PermissionDenied
self.object = self.get_object()
if not request.user.admin \ if not request.user.admin \
and (self.object.team is not None and request.user not in self.object.team.tournament.organizers)\ and (self.object.team is not None and request.user not in self.object.team.tournament.organizers.all())\
and self.request.user != self.object: and self.request.user != self.object:
raise PermissionDenied raise PermissionDenied
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if "view_as" in request.POST:
session = request.session
session["admin"] = request.user.pk
obj = self.get_object()
session["_fake_user_id"] = obj.pk
return redirect(request.path)
return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
@ -82,3 +98,10 @@ class OrganizersListView(AdminMixin, SingleTableView):
table_class = UserTable table_class = UserTable
template_name = "member/profile_list.html" template_name = "member/profile_list.html"
extra_context = dict(title=_("Organizers")) extra_context = dict(title=_("Organizers"))
class ResetAdminView(AdminMixin, View):
def dispatch(self, request, *args, **kwargs):
if "_fake_user_id" in request.session:
del request.session["_fake_user_id"]
return redirect(request.GET["path"])

View File

@ -141,6 +141,11 @@
{% endif %} {% endif %}
</ul> </ul>
<ul class="navbar-nav"> <ul class="navbar-nav">
{% if "_fake_user_id" in request.session %}
<li class="nav-item active">
<a class="nav-link" href="{% url "member:reset_admin" %}?path={{ request.path }}"><i class="fas fa-cog"></i> {% trans "Return to admin view" %}</a>
</li>
{% endif %}
{% if not user.is_authenticated %} {% if not user.is_authenticated %}
<li class="nav-item active"> <li class="nav-item active">
<a class="nav-link" href="{% url "login" %}"><i class="fas fa-sign-in-alt"></i> {% trans "Log in" %}</a> <a class="nav-link" href="{% url "login" %}"><i class="fas fa-sign-in-alt"></i> {% trans "Log in" %}</a>

View File

@ -10,52 +10,52 @@
<div class="card-body"> <div class="card-body">
<dl class="row"> <dl class="row">
<dt class="col-xl-6 text-right">{% trans 'role'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'role'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.get_role_display }}</dd> <dd class="col-xl-6">{{ tfjmuser.get_role_display }}</dd>
<dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt>
<dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=user.team.pk %}">{{ user.team }}</a></dd> <dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=tfjmuser.team.pk %}">{{ tfjmuser.team }}</a></dd>
<dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.birth_date }}</dd> <dd class="col-xl-6">{{ tfjmuser.birth_date }}</dd>
<dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.get_gender_display }}</dd> <dd class="col-xl-6">{{ tfjmuser.get_gender_display }}</dd>
<dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.address }}, {{ user.postal_code }}, {{ user.city }}{% if user.country != "France" %}, {{ user.country }}{% endif %}</dd> <dd class="col-xl-6">{{ tfjmuser.address }}, {{ tfjmuser.postal_code }}, {{ tfjmuser.city }}{% if tfjmuser.country != "France" %}, {{ tfjmuser.country }}{% endif %}</dd>
<dt class="col-xl-6 text-right">{% trans 'email'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'email'|capfirst %}</dt>
<dd class="col-xl-6"><a href="mailto:{{ user.email }}">{{ user.email }}</a></dd> <dd class="col-xl-6"><a href="mailto:{{ tfjmuser.email }}">{{ tfjmuser.email }}</a></dd>
<dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.phone_number }}</dd> <dd class="col-xl-6">{{ tfjmuser.phone_number }}</dd>
{% if user.role == '3participant' %} {% if tfjmuser.role == '3participant' %}
<dt class="col-xl-6 text-right">{% trans 'school'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'school'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.school }}</dd> <dd class="col-xl-6">{{ tfjmuser.school }}</dd>
<dt class="col-xl-6 text-right">{% trans 'class'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'class'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.get_student_class_display }}</dd> <dd class="col-xl-6">{{ tfjmuser.get_student_class_display }}</dd>
{% if user.responsible_name %} {% if tfjmuser.responsible_name %}
<dt class="col-xl-6 text-right">{% trans 'responsible name'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'responsible name'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.responsible_name }}</dd> <dd class="col-xl-6">{{ tfjmuser.responsible_name }}</dd>
{% endif %} {% endif %}
{% if user.responsible_phone %} {% if tfjmuser.responsible_phone %}
<dt class="col-xl-6 text-right">{% trans 'responsible phone'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'responsible phone'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.responsible_phone }}</dd> <dd class="col-xl-6">{{ tfjmuser.responsible_phone }}</dd>
{% endif %} {% endif %}
{% if user.responsible_email %} {% if tfjmuser.responsible_email %}
<dt class="col-xl-6 text-right">{% trans 'responsible email'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'responsible email'|capfirst %}</dt>
<dd class="col-xl-6"><a href="{{ user.responsible_email }}">{{ user.responsible_email }}</a></dd> <dd class="col-xl-6"><a href="{{ tfjmuser.responsible_email }}">{{ tfjmuser.responsible_email }}</a></dd>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if user.role == '2coach' %} {% if tfjmuser.role == '2coach' %}
<dt class="col-xl-6 text-right">{% trans 'description'|capfirst %}</dt> <dt class="col-xl-6 text-right">{% trans 'description'|capfirst %}</dt>
<dd class="col-xl-6">{{ user.description }}</dd> <dd class="col-xl-6">{{ tfjmuser.description }}</dd>
{% endif %} {% endif %}
</dl> </dl>
</div> </div>
@ -66,4 +66,12 @@
<h4>{% trans "Documents" %}</h4> <h4>{% trans "Documents" %}</h4>
{# TODO Display documents #} {# TODO Display documents #}
{% if request.user.is_superuser %}
<hr>
<form method="post">
{% csrf_token %}
<button name="view_as" class="btn btn-block btn-warning">{% blocktrans %}View site as {{ tfjmuser }}{% endblocktrans %}</button>
</form>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -2,12 +2,14 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AnonymousUser, User from django.contrib.auth.models import AnonymousUser
from threading import local from threading import local
from django.contrib.sessions.backends.db import SessionStore from django.contrib.sessions.backends.db import SessionStore
from member.models import TFJMUser
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user') USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session') SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip') IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
@ -21,7 +23,7 @@ def _set_current_user_and_ip(user=None, session=None, ip=None):
setattr(_thread_locals, IP_ATTR_NAME, ip) setattr(_thread_locals, IP_ATTR_NAME, ip)
def get_current_user() -> User: def get_current_user() -> TFJMUser:
return getattr(_thread_locals, USER_ATTR_NAME, None) return getattr(_thread_locals, USER_ATTR_NAME, None)
@ -49,7 +51,11 @@ class SessionMiddleware(object):
self.get_response = get_response self.get_response = get_response
def __call__(self, request): def __call__(self, request):
if "_fake_user_id" in request.session:
request.user = TFJMUser.objects.get(pk=request.session["_fake_user_id"])
user = request.user user = request.user
print(user)
if 'HTTP_X_FORWARDED_FOR' in request.META: if 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META.get('HTTP_X_FORWARDED_FOR') ip = request.META.get('HTTP_X_FORWARDED_FOR')
else: else:

View File

@ -65,6 +65,7 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware', 'django.contrib.sites.middleware.CurrentSiteMiddleware',
'tfjm.middlewares.SessionMiddleware',
'tfjm.middlewares.TurbolinksMiddleware', 'tfjm.middlewares.TurbolinksMiddleware',
] ]