diff --git a/opentech/apply/urls.py b/opentech/apply/urls.py index 086b4ea815d1a71b4f759d5f2179df3e306ed263..af5565ba19061a894a56d245bf6634df642edf83 100644 --- a/opentech/apply/urls.py +++ b/opentech/apply/urls.py @@ -8,4 +8,5 @@ urlpatterns = [ path('apply/', include('opentech.apply.funds.urls', 'apply')), path('account/', include(users_urls)), path('dashboard/', include(dashboard_urls)), + path('hijack/', include('hijack.urls', 'hijack')), ] diff --git a/opentech/apply/users/decorators.py b/opentech/apply/users/decorators.py index 38874fb6cc621b168fb20cdeab960cb4740a5da5..26d4016f57356e56ce077dfa4c40d012ee2ccef1 100644 --- a/opentech/apply/users/decorators.py +++ b/opentech/apply/users/decorators.py @@ -20,3 +20,8 @@ def is_apply_staff(user): staff_required = [login_required, user_passes_test(is_apply_staff)] + + +def superuser_decorator(fn): + check = user_passes_test(lambda user: user.is_superuser) + return check(fn) diff --git a/opentech/apply/users/templates/users/account.html b/opentech/apply/users/templates/users/account.html index b4f1f35dc2629015043fdd8cee2bfd1e0fc9d66f..6064bb0670e7036fa21cc62cf863226cace4d7d0 100644 --- a/opentech/apply/users/templates/users/account.html +++ b/opentech/apply/users/templates/users/account.html @@ -16,6 +16,28 @@ <a href="{% url 'users:password_change' %}">{% trans "Change password" %}</a> {% endif %} + {% if swappable %} + <form action="{% url 'users:become' %}" method="post" class="form"> + {% csrf_token %} + {% for user in swappable %} + {% if forloop.first %} + <label for="user" class="form__question">Become: </label> + <div class="form__item"> + <div class="form__select"> + <select name="user" id="user"> + {% endif %} + <option value="{{ user.id }}">{{ user }}</option> + {% if forloop.last %} + </select> + </div> + </div> + <p class="form__help">Only includes active, non-superusers</p> + {% endif %} + {% endfor %} + <button class="button button--primary" type="submit">Become</button> + </form> + {% endif %} + {# Remove the comment block tags below when such need arises. e.g. adding new providers #} {% comment %} {% can_use_oauth as show_oauth_link %} diff --git a/opentech/apply/users/urls.py b/opentech/apply/users/urls.py index 315e0cfe44c3000fbb11a22d5dd5b54b8ce40f54..30dc4c0206e371f3a82583da74df77f43d446070 100644 --- a/opentech/apply/users/urls.py +++ b/opentech/apply/users/urls.py @@ -2,13 +2,14 @@ from django.urls import path from django.contrib.auth import views as auth_views from django.urls import reverse_lazy -from opentech.apply.users.views import account, oauth, ActivationView, create_password +from opentech.apply.users.views import account, become, oauth, ActivationView, create_password app_name = 'users' urlpatterns = [ path('', account, name='account'), + path('become/', become, name='become'), path( 'login/', auth_views.LoginView.as_view( diff --git a/opentech/apply/users/views.py b/opentech/apply/users/views.py index 6a3f580ac625befdd10ce9ee520fdc7b01a375fe..7669165d9879dc243b4c841f0bd2cf1bc2493671 100644 --- a/opentech/apply/users/views.py +++ b/opentech/apply/users/views.py @@ -10,20 +10,37 @@ from django.utils.encoding import force_text from django.utils.http import urlsafe_base64_decode from django.views.generic.base import TemplateView +from hijack.views import login_with_id + from wagtail.admin.views.account import password_management_enabled from .decorators import require_oauth_whitelist +User = get_user_model() + @login_required(login_url=reverse_lazy('users:login')) def account(request): """Account page placeholder view""" + if request.user.is_superuser: + swappable = User.objects.filter(is_active=True, is_superuser=False) + else: + swappable = [] return render(request, 'users/account.html', { 'show_change_password': password_management_enabled() and request.user.has_usable_password(), + 'swappable': swappable, }) +@login_required(login_url=reverse_lazy('users:login')) +def become(request): + if request.POST: + id = request.POST['user'] + return login_with_id(request, id) + return redirect('users:account') + + @login_required(login_url=reverse_lazy('users:login')) @require_oauth_whitelist def oauth(request): @@ -61,8 +78,6 @@ class ActivationView(TemplateView): corresponding user account if it exists, or ``None`` if it doesn't. """ - User = get_user_model() - try: user = User.objects.get(**{ 'pk': force_text(urlsafe_base64_decode(uidb64)), diff --git a/opentech/settings/base.py b/opentech/settings/base.py index 2b69ec1644edc17b5d265d91e0adfd4edf9283d8..df8289a9007cb67325288b6279f250b0fe1cd8cb 100644 --- a/opentech/settings/base.py +++ b/opentech/settings/base.py @@ -63,6 +63,9 @@ INSTALLED_APPS = [ 'django_bleach', 'django_fsm', + 'hijack', + 'compat', + 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -339,3 +342,8 @@ BLEACH_ALLOWED_STYLES = ['font-family', 'font-weight', 'text-decoration', 'font- BLEACH_STRIP_TAGS = True BLEACH_STRIP_COMMENTS = True + +# Hijack Settings +HIJACK_LOGIN_REDIRECT_URL = '/dashboard/' +HIJACK_LOGOUT_REDIRECT_URL = '/account/' +HIJACK_DECORATOR = 'opentech.apply.users.decorators.superuser_decorator' diff --git a/opentech/templates/base-apply.html b/opentech/templates/base-apply.html index 2c40bc277f96eb609f985f3ea14dec3abf8c6c15..a2f3f51fd446a68913a1a0179c18c48479be3af9 100644 --- a/opentech/templates/base-apply.html +++ b/opentech/templates/base-apply.html @@ -1,4 +1,4 @@ -{% load static wagtailuserbar wagtailcore_tags wagtailimages_tags navigation_tags util_tags %}<!doctype html> +{% load static wagtailuserbar wagtailcore_tags wagtailimages_tags navigation_tags util_tags hijack_tags %}<!doctype html> <html class="no-js" lang="en"> <head> {# TODO fallbacks if page is not defined e.g. for 404 page #} @@ -26,9 +26,13 @@ {% block extra_css %}{% endblock %} <link rel="stylesheet" type="text/css" href="{% static 'css/apply/main.css' %}"> + {# Hijack styling #} + <link rel="stylesheet" type="text/css" href="{% static 'hijack/hijack-styles.css' %}" /> </head> <body class="{% block body_class %}light-grey-bg template-{{ page.get_verbose_name|slugify }}{% endblock %}"> + {% hijack_notification %} + {% if GOOGLE_TAG_MANAGER_ID %} {# To enable GTM code you need to specify GOOGLE_TAG_MANAGER_ID in production.py or in local.py #} <!-- Google Tag Manager (noscript) --> diff --git a/requirements.txt b/requirements.txt index ffdcd69b1c839754762df8767919b6755ec30713..7c0bdc343e2fcdfa710e513beed3cd7b5ea4f354 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,7 @@ Werkzeug==0.11.11 stellar==0.4.3 django-tinymce4-lite==1.7.0 uwsgidecorators==1.1.0 +django-hijack==2.1.9 factory_boy==2.9.2 # wagtail_factories - waiting on merge and release form master branch