Add basic user functionalities
Users need to register, login, logout and reset their password.
This commit is contained in:
parent
e0d26e8a7a
commit
ab4eb7414c
28 changed files with 694 additions and 13 deletions
10
README.md
10
README.md
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
11
khaganat/templates/khaganat/email.html
Normal file
11
khaganat/templates/khaganat/email.html
Normal 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>
|
|
@ -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')),
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
9
neluser/forms.py
Normal 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,)
|
155
neluser/locale/en/LC_MESSAGES/django.po
Normal file
155
neluser/locale/en/LC_MESSAGES/django.po
Normal 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"
|
160
neluser/locale/fr/LC_MESSAGES/django.po
Normal file
160
neluser/locale/fr/LC_MESSAGES/django.po
Normal 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"
|
|
@ -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.'
|
||||
|
|
13
neluser/templates/neluser/activate_done.html
Normal file
13
neluser/templates/neluser/activate_done.html
Normal 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 %}
|
16
neluser/templates/neluser/activate_email.html
Normal file
16
neluser/templates/neluser/activate_email.html
Normal 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 %}
|
12
neluser/templates/neluser/activate_email.txt
Normal file
12
neluser/templates/neluser/activate_email.txt
Normal 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 %}
|
3
neluser/templates/neluser/activate_email_subject.txt
Normal file
3
neluser/templates/neluser/activate_email_subject.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
{% load i18n %}{% autoescape off %}
|
||||
{% blocktrans %}Account activation on {{ site_name }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
17
neluser/templates/neluser/login.html
Normal file
17
neluser/templates/neluser/login.html
Normal 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 %}
|
14
neluser/templates/neluser/password_reset.html
Normal file
14
neluser/templates/neluser/password_reset.html
Normal 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 %}
|
19
neluser/templates/neluser/password_reset_confirm.html
Normal file
19
neluser/templates/neluser/password_reset_confirm.html
Normal 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 %}
|
10
neluser/templates/neluser/password_reset_done.html
Normal file
10
neluser/templates/neluser/password_reset_done.html
Normal 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 %}
|
16
neluser/templates/neluser/password_reset_email.html
Normal file
16
neluser/templates/neluser/password_reset_email.html
Normal 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 %}
|
12
neluser/templates/neluser/password_reset_email.txt
Normal file
12
neluser/templates/neluser/password_reset_email.txt
Normal 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 %}
|
|
@ -0,0 +1,3 @@
|
|||
{% load i18n %}{% autoescape off %}
|
||||
{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %}
|
||||
{% endautoescape %}
|
14
neluser/templates/neluser/register.html
Normal file
14
neluser/templates/neluser/register.html
Normal 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 %}
|
13
neluser/templates/neluser/register_done.html
Normal file
13
neluser/templates/neluser/register_done.html
Normal 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
64
neluser/urls.py
Normal 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'
|
||||
),
|
||||
]
|
|
@ -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})
|
||||
|
|
Loading…
Reference in a new issue