From 1e0e5f53a1024379d550a10c07949b3762f092cb Mon Sep 17 00:00:00 2001
From: Dan Braghis <dan.braghis@torchbox.com>
Date: Tue, 9 Jan 2018 15:04:14 +0000
Subject: [PATCH] Add password reset urls and templates

---
 opentech/apply/urls.py                        |  2 +-
 opentech/apply/users/urls.py                  | 51 ++++++++++++++++---
 opentech/apply/users/views.py                 |  9 +++-
 opentech/settings/base.py                     |  1 +
 opentech/users/templates/users/account.html   |  7 +++
 .../users/password_reset/complete.html        |  9 ++++
 .../users/password_reset/confirm.html         | 25 +++++++++
 .../templates/users/password_reset/done.html  |  9 ++++
 .../templates/users/password_reset/email.txt  |  7 +++
 .../templates/users/password_reset/form.html  | 25 +++++++++
 10 files changed, 135 insertions(+), 10 deletions(-)
 create mode 100644 opentech/users/templates/users/account.html
 create mode 100644 opentech/users/templates/users/password_reset/complete.html
 create mode 100644 opentech/users/templates/users/password_reset/confirm.html
 create mode 100644 opentech/users/templates/users/password_reset/done.html
 create mode 100644 opentech/users/templates/users/password_reset/email.txt
 create mode 100644 opentech/users/templates/users/password_reset/form.html

diff --git a/opentech/apply/urls.py b/opentech/apply/urls.py
index a7487aaf5..efd6ba373 100644
--- a/opentech/apply/urls.py
+++ b/opentech/apply/urls.py
@@ -5,5 +5,5 @@ from .users import urls as users_urls
 
 urlpatterns = [
     url(r'^apply/', include(funds_urls)),
-    url(r'^user/', include(users_urls))
+    url(r'^user/', include(users_urls, namespace='users')
 ]
diff --git a/opentech/apply/users/urls.py b/opentech/apply/users/urls.py
index 0185992fa..f21737750 100644
--- a/opentech/apply/users/urls.py
+++ b/opentech/apply/users/urls.py
@@ -2,15 +2,50 @@ from django.conf.urls import url
 
 from django.contrib.auth import views as auth_views
 
+from django.urls import reverse_lazy
+
+from wagtail.wagtailadmin.forms import PasswordResetForm
+
+from opentech.users.views import account
+
 urlpatterns = [
-    # TODO replace with dashboard view with a login_required decorator
-    url(r'^$', auth_views.login, {
-        'template_name': 'users/login.html'
-    }, name='user'),
-    url(r'^login$', auth_views.login, {
-        'template_name': 'users/login.html'
-    }, name='login'),
+    url(r'^$', account, name='account'),
+    url(
+        r'^login/$',
+        auth_views.LoginView.as_view(
+            template_name='users/login.html',
+            redirect_authenticated_user=True
+        ),
+        name='login'
+    ),
 
     # Log out
-    url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
+    url(r'^logout/$', auth_views.LogoutView.as_view(next_page='/'), name='logout'),
+
+    # Password reset
+    url(r'^password_reset/$', auth_views.PasswordResetView.as_view(
+        template_name='users/password_reset/form.html',
+        email_template_name='users/password_reset/email.txt',
+        success_url=reverse_lazy('users:password_reset_done'),
+        form_class=PasswordResetForm
+    )),
+    url(
+        r'^password_reset/done/$',
+        auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset/done.html'),
+        name='password_reset_done'
+    ),
+    url(
+        r'^password_reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
+        auth_views.PasswordResetConfirmView.as_view(
+            template_name='users/password_reset/confirm.html',
+            post_reset_login=True,
+            success_url=reverse_lazy('users:account')
+        ),
+        name='password_reset_confirm'
+    ),
+    url(
+        r'^password_reset/complete/$',
+        auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset/complete.html'),
+        name='password_reset_complete'
+    ),
 ]
diff --git a/opentech/apply/users/views.py b/opentech/apply/users/views.py
index f4f3c02cd..004fa0aa6 100644
--- a/opentech/apply/users/views.py
+++ b/opentech/apply/users/views.py
@@ -1 +1,8 @@
-# Views placeholder.
+from django.contrib.auth.decorators import login_required
+from django.template.response import TemplateResponse
+
+
+@login_required(login_url='/user/login')
+def account(request):
+    "Account page placeholder view"
+    return TemplateResponse(request, 'users/account.html', {})
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index 5aaf1a759..2693c88cb 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -181,6 +181,7 @@ MEDIA_URL = '/media/'
 
 AUTH_USER_MODEL = 'users.User'
 # TODO populate me with the dashboard URL when ready
+LOGIN_URL = 'users:login'
 LOGIN_REDIRECT_URL = '/'
 
 # Logging
diff --git a/opentech/users/templates/users/account.html b/opentech/users/templates/users/account.html
new file mode 100644
index 000000000..76ce008a2
--- /dev/null
+++ b/opentech/users/templates/users/account.html
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+
+{% block title %}Account{% endblock %}
+
+{% block content %}
+<h2>Welcome {{ user }}</h2>
+{% endblock %}
diff --git a/opentech/users/templates/users/password_reset/complete.html b/opentech/users/templates/users/password_reset/complete.html
new file mode 100644
index 000000000..00740fd92
--- /dev/null
+++ b/opentech/users/templates/users/password_reset/complete.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %}{% trans "Reset password" %}{% endblock %} {% block content %}
+    <h1>{% trans "Password change successful" %}</h1>
+    <p>
+        <a href="{% url 'users:login' %}">{% trans "Log in" %}</a>
+    </p>
+{% endblock %}
diff --git a/opentech/users/templates/users/password_reset/confirm.html b/opentech/users/templates/users/password_reset/confirm.html
new file mode 100644
index 000000000..6371c4593
--- /dev/null
+++ b/opentech/users/templates/users/password_reset/confirm.html
@@ -0,0 +1,25 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+    <form method="post" novalidate>
+        {% csrf_token %}
+        <h1>{% trans "Set your new password" %}</h1>
+
+        <ul class="fields">
+            <li>
+                <div class="field">
+                    {{ form.new_password1.label_tag }} {{ form.new_password1 }}
+                </div>
+            </li>
+            <li>
+                <div class="field">
+                    {{ form.new_password2.label_tag }} {{ form.new_password2 }}
+                </div>
+            </li>
+            <li class="submit">
+                <button type="submit">{% trans 'Reset password' %}</button>
+            </li>
+        </ul>
+    </form>
+{% endblock %}
diff --git a/opentech/users/templates/users/password_reset/done.html b/opentech/users/templates/users/password_reset/done.html
new file mode 100644
index 000000000..8773bd7ac
--- /dev/null
+++ b/opentech/users/templates/users/password_reset/done.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %}{% trans "Reset password" %}{% endblock %}
+
+{% block content %}
+    <h1>{% trans "Check your email" %}</h1>
+    <p>{% trans "A link to reset your password has been emailed to you." %}</p>
+{% endblock %}
diff --git a/opentech/users/templates/users/password_reset/email.txt b/opentech/users/templates/users/password_reset/email.txt
new file mode 100644
index 000000000..30d6aa5aa
--- /dev/null
+++ b/opentech/users/templates/users/password_reset/email.txt
@@ -0,0 +1,7 @@
+{% load i18n wagtailadmin_tags %}{% base_url_setting as base_url %}
+{% trans "Please follow the link below to reset your password:" %}
+{% if base_url %}{{ base_url }}{% else %}{{ protocol }}://{{ domain }}{% endif %}{% url 'users:password_reset_confirm' uidb64=uid token=token %}
+
+{% if user.USERNAME_FIELD != "email" %}
+{% trans "Your username (in case you've forgotten):" %} {{ user.get_username }}
+{% endif %}
diff --git a/opentech/users/templates/users/password_reset/form.html b/opentech/users/templates/users/password_reset/form.html
new file mode 100644
index 000000000..e75567ab5
--- /dev/null
+++ b/opentech/users/templates/users/password_reset/form.html
@@ -0,0 +1,25 @@
+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Reset password" %}{% endblock %}
+
+
+{% block content %}
+    {% if form.non_field_errors %}
+        <div class="messages">
+            <ul>
+                {% for error in form.non_field_errors %}
+                <li class="error">{{ error }}</li>
+                {% endfor %}
+            </ul>
+        </div>
+    {% endif %}
+
+    <form method="post">
+        {% csrf_token %}
+        {{ form.email.label_tag }}
+        {{ form.email }}
+
+        <button type="submit">{% trans 'Reset password' %}</button>
+    </form>
+{% endblock %}
-- 
GitLab