Add basic user functionalities

Users need to register, login, logout and reset their password.
This commit is contained in:
Rodolphe Breard 2018-02-04 01:36:39 +01:00
parent e0d26e8a7a
commit ab4eb7414c
28 changed files with 694 additions and 13 deletions

View file

@ -35,3 +35,13 @@ You can set the following variables in the `.env` file:
* `KHAGANAT_STATIC_ROOT`: Absolute path to the directory where static files should be collected.
* `KHAGANAT_LOGS_MIN_DAYS`: Numbers of days before logs are hidden, default is 7.
* `KHAGANAT_LOGS_MAX_DAYS`: Number of days before logs are published, default is 0.
* `KHAGANAT_LOGIN_URL`: The login URL, default is `/account/login/`.
* `KHAGANAT_LOGIN_REDIRECT_URL`: URL to redirect after user login. Will be reversed, default is `index`.
* `KHAGANAT_REGISTER_REQUIRE_VALIDATION`: require email validation upon registration, default is true.
* `KHAGANAT_EMAIL_HOST`: The host to use for sending email, default is `localhost`.
* `KHAGANAT_EMAIL_PORT`: Port to use for the SMTP server, default is `25`.
* `KHAGANAT_EMAIL_HOST_USER`: Username to use for the SMTP server, default is empty (no authentication).
* `KHAGANAT_EMAIL_HOST_PASSWORD`: Password to use for the SMTP server, default is empty.
* `KHAGANAT_EMAIL_USE_TLS`: Whether to use a TLS connection to the SMTP server, default is `False`.
* `KHAGANAT_EMAIL_SUBJECT_PREFIX`: Subject-line prefix for email, default is empty.
* `KHAGANAT_DEFAULT_FROM_EMAIL`: Default email address to use, default is `no-reply@localhost`.

View file

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.0/ref/settings/
"""
from django.utils.translation import gettext_lazy as _
from django.urls import reverse_lazy
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
@ -91,10 +92,26 @@ DATABASES = {
}
# Emailing
# https://docs.djangoproject.com/fr/2.0/topics/email/
EMAIL_HOST = os.getenv('KHAGANAT_EMAIL_HOST', default='localhost')
EMAIL_PORT = int(os.getenv('KHAGANAT_EMAIL_PORT', default='25'))
EMAIL_HOST_USER = os.getenv('KHAGANAT_EMAIL_HOST_USER', default='')
EMAIL_HOST_PASSWORD = os.getenv('KHAGANAT_EMAIL_HOST_PASSWORD', default='')
EMAIL_USE_TLS = os.getenv('KHAGANAT_EMAIL_USE_TLS', default='')
EMAIL_SUBJECT_PREFIX = os.getenv('KHAGANAT_EMAIL_SUBJECT_PREFIX', default='')
DEFAULT_FROM_EMAIL = os.getenv('KHAGANAT_DEFAULT_FROM_EMAIL', default='no-reply@localhost')
# User model
# https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
AUTH_USER_MODEL = 'neluser.NelUser'
LOGIN_URL = os.getenv('KHAGANAT_LOGIN_URL', default='/account/login/')
LOGIN_REDIRECT_URL = reverse_lazy(os.getenv('KHAGANAT_LOGIN_REDIRECT_URL', default='index'))
REGISTER_REQUIRE_VALIDATION = bool(os.getenv('KHAGANAT_REGISTER_REQUIRE_VALIDATION', default='True'))
# Password validation

View file

@ -1,5 +1,5 @@
{% load static %}{% load navbar %}<!doctype html>
<html lang="en">
{% load static %}{% load i18n %}{% load navbar %}{% get_current_language as LANGUAGE_CODE %}<!doctype html>
<html lang="{{ LANGUAGE_CODE }}">
<head>
<!-- Begin bootstrap headers -->
<meta charset="utf-8" />

View file

@ -0,0 +1,11 @@
{% load i18n %}{% get_current_language as LANGUAGE_CODE %}<!doctype html>
<html lang="{{ LANGUAGE_CODE }}">
<head>
<meta charset="utf-8" />
</head>
<body>
<div class="container" id="main-content">
{% block content %}{% endblock %}
</div>
</body>
</html>

View file

@ -26,6 +26,7 @@ urlpatterns = [
urlpatterns += i18n_patterns(
path('', index),
path('admin/', admin.site.urls),
path('account/', include('neluser.urls')),
path('page/', include('pages.urls')),
path('logs/', include('logs.urls')),
)

View file

@ -3,10 +3,10 @@ msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+1\n"
"Last-Translator: Rodolphe Bréard <rodolphe@what.tf>\n"
"PO-Revision-Date: 2018-01-27 18:35+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: English\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View file

@ -3,10 +3,10 @@ msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-27 18:32+0100\n"
"PO-Revision-Date: 2018-01-27 18:35+1\n"
"Last-Translator: Rodolphe Bréard <rodolphe@what.tf>\n"
"PO-Revision-Date: 2018-01-27 18:35+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: Français\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View file

@ -1,4 +1,7 @@
{% load static %}<nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
{% load static %}
{% load i18n %}
<nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
<a class="navbar-brand" href="{% url 'index' %}">
<img src="{% static "images/icon_khaganat.png" %}" alt="Khaganat">
</a>
@ -35,6 +38,24 @@
</ul>
</div>
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
{% if user.is_authenticated %}
<li class="nav-item dropdown">
<a class="nav-item nav-link dropdown-toggle mr-md-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{% trans "my_account" %}</a>
<div class="dropdown-menu dropdown-menu-right">
<!--
<a class="dropdown-item" href="{% url "settings" %}">{% trans "settings" %}</a>
-->
<a class="dropdown-item" href="{% url "logout" %}">{% trans "logout" %}</a>
</div>
</li>
{% else %}
<li>
<a class="btn btn-primary" href="{% url "login" %}?next={{ current_url }}" role="button">{% trans "login"|capfirst %}</a>
</li>
<li>
<a class="btn btn-secondary" href="{% url "register" %}" role="button">{% trans "register"|capfirst %}</a>
</li>
{% endif %}
<li class="nav-item dropdown">
<a class="nav-item nav-link dropdown-toggle mr-md-2" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ current_lang_name|capfirst }}</a>
<div class="dropdown-menu dropdown-menu-right">

View file

@ -35,6 +35,8 @@ def navbar(context):
request = context['request']
curr_lang = get_language()
ctx = {
'user': request.user,
'current_url': request.path_info,
'elems': Element.objects.filter(parent=None).order_by('weight'),
'current_lang_code': curr_lang,
'current_lang_name': get_lang_name(curr_lang),

9
neluser/forms.py Normal file
View file

@ -0,0 +1,9 @@
from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import gettext_lazy as _
from .models import NelUser
class RegistrationForm(UserCreationForm):
class Meta:
model = NelUser
fields = (NelUser.EMAIL_FIELD,)

View file

@ -0,0 +1,155 @@
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-04 01:03+0100\n"
"PO-Revision-Date: 2018-02-04 01:03+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: models.py:40
msgid "email"
msgstr ""
#: models.py:42
msgid "staff status"
msgstr ""
#: models.py:45
msgid "Designates whether the user can log into this admin site."
msgstr ""
#: models.py:49
msgid "active"
msgstr ""
#: models.py:52
msgid ""
"Designates whether this user should be treated as active. Unselect this "
"instead of deleting accounts."
msgstr ""
#: models.py:56
msgid "date joined"
msgstr ""
#: models.py:65
msgid "user"
msgstr ""
#: models.py:66
msgid "users"
msgstr ""
#: templates/neluser/activate_done.html:4 templates/neluser/login.html:13
#: templates/neluser/register.html:4 templates/neluser/register.html:11
#: templates/neluser/register_done.html:4
msgid "register"
msgstr ""
#: templates/neluser/activate_done.html:9
msgid "account_activated"
msgstr "Your account has been activated."
#: templates/neluser/activate_done.html:10 templates/neluser/login.html:4
#: templates/neluser/login.html:12
msgid "login"
msgstr ""
#: templates/neluser/activate_email.html:5
#: templates/neluser/activate_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you created an account at %(site_name)s."
msgstr ""
#: templates/neluser/activate_email.html:7
#: templates/neluser/activate_email.txt:4
msgid "Please go to the following page to activate your account:"
msgstr ""
#: templates/neluser/activate_email.html:13
#: templates/neluser/activate_email.txt:9
#: templates/neluser/password_reset_email.html:13
#: templates/neluser/password_reset_email.txt:9
msgid "Thanks for using our site!"
msgstr ""
#: templates/neluser/activate_email.html:14
#: templates/neluser/activate_email.txt:10
#: templates/neluser/password_reset_email.html:14
#: templates/neluser/password_reset_email.txt:10
#, python-format
msgid "The %(site_name)s team"
msgstr ""
#: templates/neluser/activate_email_subject.txt:2
#, python-format
msgid "Account activation on %(site_name)s"
msgstr ""
#: templates/neluser/login.html:14
msgid "forgotten_password"
msgstr "forgotten password"
#: templates/neluser/password_reset.html:4
#: templates/neluser/password_reset_confirm.html:4
#: templates/neluser/password_reset_done.html:4
msgid "password_reset"
msgstr "password reset"
#: templates/neluser/password_reset.html:11
msgid "reset_my_password"
msgstr "reset my password"
#: templates/neluser/password_reset_confirm.html:9
msgid "set_new_password"
msgstr "Please set a new password"
#: templates/neluser/password_reset_confirm.html:13
msgid "change_my_password"
msgstr "change my password"
#: templates/neluser/password_reset_confirm.html:16
msgid "reset_password_invalid_link"
msgstr "Sorry, we are unable to reset your password."
#: templates/neluser/password_reset_done.html:8
msgid "password_reset_success"
msgstr "Your password has been changed."
#: templates/neluser/password_reset_email.html:5
#: templates/neluser/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
#: templates/neluser/password_reset_email.html:7
#: templates/neluser/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr ""
#: templates/neluser/password_reset_email_subject.txt:2
#, python-format
msgid "Password reset on %(site_name)s"
msgstr ""
#: templates/neluser/register_done.html:9
msgid "almost_there"
msgstr "Almost there…"
#: templates/neluser/register_done.html:10
msgid "activate_your_account"
msgstr "You now need to activate your account. Please click on the link that "
"has been sent to your email address."
#: templates/neluser/register_done.html:11
msgid "take_me_home"
msgstr "Take me home"

View file

@ -0,0 +1,160 @@
msgid ""
msgstr ""
"Project-Id-Version: 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-04 01:03+0100\n"
"PO-Revision-Date: 2018-02-04 01:03+0100\n"
"Last-Translator: Khaganat <assoc@khaganat.net>\n"
"Language-Team: Khaganat <assoc@khaganat.net>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: models.py:40
msgid "email"
msgstr "adresse électronique"
#: models.py:42
msgid "staff status"
msgstr "statut équipe"
#: models.py:45
msgid "Designates whether the user can log into this admin site."
msgstr "Précise si l'utilisateur peut se connecter à ce site d'administration."
#: models.py:49
msgid "active"
msgstr "actif"
#: models.py:52
msgid ""
"Designates whether this user should be treated as active. Unselect this "
"instead of deleting accounts."
msgstr ""
"Précise si l'utilisateur doit être considéré comme actif. Décochez ceci "
"plutôt que de supprimer le compte."
#: models.py:56
msgid "date joined"
msgstr "date d'inscription"
#: models.py:65
msgid "user"
msgstr "utilisateur"
#: models.py:66
msgid "users"
msgstr "utilisateurs"
#: templates/neluser/activate_done.html:4 templates/neluser/login.html:13
#: templates/neluser/register.html:4 templates/neluser/register.html:11
#: templates/neluser/register_done.html:4
msgid "register"
msgstr "inscription"
#: templates/neluser/activate_done.html:9
msgid "account_activated"
msgstr "compte activé"
#: templates/neluser/activate_done.html:10 templates/neluser/login.html:4
#: templates/neluser/login.html:12
msgid "login"
msgstr "connexion"
#: templates/neluser/activate_email.html:5
#: templates/neluser/activate_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you created an account at %(site_name)s."
msgstr ""
"Vous recevez cet email car vous avez créé un compte sur %(site_name)s."
#: templates/neluser/activate_email.html:7
#: templates/neluser/activate_email.txt:4
msgid "Please go to the following page to activate your account:"
msgstr "Veuillez suivre le lien suivant pour activer votre compte :"
#: templates/neluser/activate_email.html:13
#: templates/neluser/activate_email.txt:9
#: templates/neluser/password_reset_email.html:13
#: templates/neluser/password_reset_email.txt:9
msgid "Thanks for using our site!"
msgstr "Merci d'utiliser notre site !"
#: templates/neluser/activate_email.html:14
#: templates/neluser/activate_email.txt:10
#: templates/neluser/password_reset_email.html:14
#: templates/neluser/password_reset_email.txt:10
#, python-format
msgid "The %(site_name)s team"
msgstr "L'équipe %(site_name)s"
#: templates/neluser/activate_email_subject.txt:2
#, python-format
msgid "Account activation on %(site_name)s"
msgstr "Activation de compte sur %(site_name)s"
#: templates/neluser/login.html:14
msgid "forgotten_password"
msgstr "mot de passe oublié"
#: templates/neluser/password_reset.html:4
#: templates/neluser/password_reset_confirm.html:4
#: templates/neluser/password_reset_done.html:4
msgid "password_reset"
msgstr "réinitialisation du mot de passe"
#: templates/neluser/password_reset.html:11
msgid "reset_my_password"
msgstr "réinitialiser mon mot de passe"
#: templates/neluser/password_reset_confirm.html:9
msgid "set_new_password"
msgstr "Veuillez indiquer un nouveau mot de passe"
#: templates/neluser/password_reset_confirm.html:13
msgid "change_my_password"
msgstr "Modifier mon mot de passe"
#: templates/neluser/password_reset_confirm.html:16
msgid "reset_password_invalid_link"
msgstr "Désolé, nous ne sommes pas en mesure de modifier votre mot de passe."
#: templates/neluser/password_reset_done.html:8
msgid "password_reset_success"
msgstr "Votre mot de passe a été modifié."
#: templates/neluser/password_reset_email.html:5
#: templates/neluser/password_reset_email.txt:2
#, python-format
msgid ""
"You're receiving this email because you requested a password reset for your "
"user account at %(site_name)s."
msgstr ""
"Vous recevez ce message car vous avez demandé la réinitialisation du mot de "
"passe pour votre compte sur %(site_name)s."
#: templates/neluser/password_reset_email.html:7
#: templates/neluser/password_reset_email.txt:4
msgid "Please go to the following page and choose a new password:"
msgstr "Veuillez suivre le lien suivant pour réinitialiser votre mot de passe :"
#: templates/neluser/password_reset_email_subject.txt:2
#, python-format
msgid "Password reset on %(site_name)s"
msgstr "Réinitialisation du mot de passe sur %(site_name)s"
#: templates/neluser/register_done.html:9
msgid "almost_there"
msgstr "Vous y êtes presque…"
#: templates/neluser/register_done.html:10
msgid "activate_your_account"
msgstr "Vous devez maintenant activer votre compte. Veuillez cliquer sur le "
"lien qui vient d'être envoyé sur votre adresse électronique."
#: templates/neluser/register_done.html:11
msgid "take_me_home"
msgstr "Retour à l'accueil"

View file

@ -37,7 +37,7 @@ class NelUserManager(BaseUserManager):
class NelUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True, null=True)
email = models.EmailField(_('email'), unique=True, null=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
@ -47,7 +47,7 @@ class NelUser(AbstractBaseUser, PermissionsMixin):
)
is_active = models.BooleanField(
_('active'),
default=True,
default=False,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'

View file

@ -0,0 +1,13 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "register" %}{% endblock %}
{% block content %}
<div class="alert alert-success" role="alert">
<p>{% trans 'account_activated' %}</p>
<a class="btn btn-secondary" href="{% url "login" %}" role="button">{% trans "login"|capfirst %}</a>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "khaganat/email.html" %}
{% load i18n %}
{% block content %}
<p>{% blocktrans %}You're receiving this email because you created an account at {{ site_name }}.{% endblocktrans %}</p>
<p>
{% trans "Please go to the following page to activate your account:" %}<br />
{% block activation_link %}
<a href="{{ protocol }}://{{ domain }}{% url 'activate' uidb64=uid token=token %}">{{ protocol }}://{{ domain }}{% url 'activate' uidb64=uid token=token %}</a>
{% endblock %}
</p>
<p>
{% trans "Thanks for using our site!" %}<br />
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
</p>
{% endblock %}

View file

@ -0,0 +1,12 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you created an account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page to activate your account:" %}
{% block activation_link %}
{{ protocol }}://{{ domain }}{% url 'activate' uidb64=uid token=token %}
{% endblock %}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View file

@ -0,0 +1,3 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}Account activation on {{ site_name }}{% endblocktrans %}
{% endautoescape %}

View file

@ -0,0 +1,17 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "login" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="next" value="{{ request.GET.next }}" />
<button type="submit" class="btn btn-success">{% trans "login"|capfirst %}</button>
<a class="btn btn-primary" href="{% url "register" %}" role="button">{% trans "register"|capfirst %}</a>
<a class="btn btn-secondary" href="{% url "password_reset" %}" role="button">{% trans "forgotten_password"|capfirst %}</a>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "password_reset" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<form method="post" action="{% url 'password_reset' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">{% trans "reset_my_password" %}</button>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,19 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "password_reset" %}{% endblock %}
{% block content %}
<div class="content-bloc">
{% if validlink %}
<h2>{% trans "set_new_password" %}</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">{% trans "change_my_password"|capfirst %}</button>
</form>
{% else %}
<div class="alert alert-danger" role="alert">{% trans "reset_password_invalid_link" %}</div>
{% endif %}
</div>
{% endblock %}

View file

@ -0,0 +1,10 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "password_reset" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<div class="alert alert-success" role="alert">{% trans "password_reset_success" %}</div>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "khaganat/email.html" %}
{% load i18n %}
{% block content %}
<p>{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}</p>
<p>
{% trans "Please go to the following page and choose a new password:" %}<br />
{% block reset_link %}
<a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}">{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}</a>
{% endblock %}
</p>
<p>
{% trans "Thanks for using our site!" %}<br />
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
</p>
{% endblock %}

View file

@ -0,0 +1,12 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}You're receiving this email because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View file

@ -0,0 +1,3 @@
{% load i18n %}{% autoescape off %}
{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %}
{% endautoescape %}

View file

@ -0,0 +1,14 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "register" %}{% endblock %}
{% block content %}
<div class="content-bloc">
<form method="post" action="{% url 'register' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">{% trans "register"|capfirst %}</button>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,13 @@
{% extends "khaganat/base.html" %}
{% load i18n %}
{% block title %}{% trans "register" %}{% endblock %}
{% block content %}
<div class="alert alert-success" role="alert">
<h4 class="alert-heading">{% trans 'almost_there' %}</h4>
<p>{% trans 'activate_your_account' %}</p>
<a class="btn btn-secondary" href="{% url "index" %}" role="button">{% trans "take_me_home"|capfirst %}</a>
</div>
{% endblock %}

64
neluser/urls.py Normal file
View file

@ -0,0 +1,64 @@
from django.contrib.auth import views as auth_views
from django.urls import reverse_lazy, path
from . import views
urlpatterns = [
# login/logout
path(
'login/',
auth_views.LoginView.as_view(template_name='neluser/login.html'),
name='login'
),
path(
'logout/',
auth_views.LogoutView.as_view(next_page=reverse_lazy('index')),
name='logout'
),
# account activation
path('register/', views.register, name='register'),
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
# settings
path('settings/', views.profile, name='settings'),
path('settings/password/', views.profile, name='password_change'),
path(
'settings/password/change/done/',
views.profile,
name='password_change_done'
),
# forgotten_password
path(
'forgotten_password/',
auth_views.PasswordResetView.as_view(
template_name='neluser/password_reset.html',
email_template_name='neluser/password_reset_email.txt',
html_email_template_name='neluser/password_reset_email.html',
subject_template_name='neluser/password_reset_email_subject.txt'
),
name='password_reset'
),
path(
'forgotten_password/done/',
auth_views.PasswordResetDoneView.as_view(
template_name='neluser/password_reset_done.html'
),
name='password_reset_done'
),
path(
'password/reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(
template_name='neluser/password_reset_confirm.html'
),
name='password_reset_confirm'
),
path(
'password/reset/done/',
auth_views.PasswordResetCompleteView.as_view(
template_name='neluser/password_reset_done.html'
),
name='password_reset_complete'
),
]

View file

@ -1,3 +1,72 @@
from django.shortcuts import render
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives
from django.utils.encoding import force_bytes
from django.http import HttpResponse, Http404
from django.conf import settings
from django.urls import reverse
from .forms import RegistrationForm
from .models import NelUser
# Create your views here.
def profile(request):
return HttpResponse('<h1>lol</h1>')
def send_activation_email(request, user):
current_site = get_current_site(request)
context = {
'email': user.email,
'domain': current_site.domain,
'site_name': current_site.name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'user': user,
'token': default_token_generator.make_token(user),
'protocol': 'https' if request.is_secure() else 'http',
}
subject = render_to_string('neluser/activate_email_subject.txt', context)
subject = ''.join(subject.splitlines()),
email_message = EmailMultiAlternatives(
subject,
render_to_string('neluser/activate_email.txt', context),
settings.DEFAULT_FROM_EMAIL,
[user.email]
)
email_message.attach_alternative(
render_to_string('neluser/activate_email.html', context),
'text/html'
)
email_message.send()
def activate(request, uidb64, token):
uid = urlsafe_base64_decode(uidb64).decode()
user = get_object_or_404(NelUser, pk=uid)
if default_token_generator.check_token(user, token):
user.is_active = True
user.save()
return render(
request,
'neluser/activate_done.html',
{'activated': activated}
)
raise Http404("Unable to activate user %d with token %s." % (uid, token))
def register(request):
if request.method == 'GET':
form = RegistrationForm()
elif request.method == 'POST':
form = RegistrationForm(data=request.POST)
if form.is_valid():
user = form.save(commit=False)
user.set_password(form.cleaned_data.get('password1'))
user.is_active = not settings.REGISTER_REQUIRE_VALIDATION
user.save()
if settings.REGISTER_REQUIRE_VALIDATION:
send_activation_email(request, user)
return render(request, 'neluser/register_done.html')
return render(request, 'neluser/register.html', {'form': form})