Rajoute une page pour créer plus facilement des comptes avec mdp
This commit is contained in:
parent
c73f8a5943
commit
c97f57912b
11 changed files with 108 additions and 19 deletions
|
@ -94,7 +94,7 @@ class DeleteVoteForm(forms.Form):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
if voter is not None:
|
if voter is not None:
|
||||||
self.fields["delete"].label = _("Supprimer le vote de {} ({}) ?").format(
|
self.fields["delete"].label = _("Supprimer le vote de {} ({}) ?").format(
|
||||||
voter.full_name, voter.get_username()
|
voter.full_name, voter.base_username
|
||||||
)
|
)
|
||||||
|
|
||||||
delete = forms.ChoiceField(
|
delete = forms.ChoiceField(
|
||||||
|
|
|
@ -208,7 +208,8 @@ class User(AbstractUser):
|
||||||
)
|
)
|
||||||
full_name = models.CharField(_("Nom et Prénom"), max_length=150, blank=True)
|
full_name = models.CharField(_("Nom et Prénom"), max_length=150, blank=True)
|
||||||
|
|
||||||
def get_username(self):
|
@property
|
||||||
|
def base_username(self):
|
||||||
return "__".join(self.username.split("__")[1:])
|
return "__".join(self.username.split("__")[1:])
|
||||||
|
|
||||||
def can_vote(self, request, election):
|
def can_vote(self, request, election):
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
{% if election.restricted %}
|
{% if election.restricted %}
|
||||||
{% for v in election.registered_voters.all %}
|
{% for v in election.registered_voters.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ v.full_name }} ({{ v.get_username }})</td>
|
<td>{{ v.full_name }} ({{ v.base_username }})</td>
|
||||||
<td class="has-text-centered">
|
<td class="has-text-centered">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
{% if v in voters %}
|
{% if v in voters %}
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
{% for v in voters %}
|
{% for v in voters %}
|
||||||
<tr id="v_{{ forloop.counter }}">
|
<tr id="v_{{ forloop.counter }}">
|
||||||
<td>{{ v.full_name }} ({{ v.get_username }})</td>
|
<td>{{ v.full_name }} ({{ v.base_username }})</td>
|
||||||
<td class="has-text-centered">
|
<td class="has-text-centered">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-check"></i>
|
<i class="fas fa-check"></i>
|
||||||
|
|
|
@ -110,7 +110,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for v in voters %}
|
{% for v in voters %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ v.get_username }}</td>
|
<td>{{ v.base_username }}</td>
|
||||||
<td>{{ v.full_name }}</td>
|
<td>{{ v.full_name }}</td>
|
||||||
<td>{{ v.email }}</td>
|
<td>{{ v.email }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import csv
|
import csv
|
||||||
import io
|
import io
|
||||||
import random
|
|
||||||
|
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -14,6 +13,8 @@ from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from shared.auth.utils import generate_password
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Fonctions universelles
|
# Fonctions universelles
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
@ -389,16 +390,6 @@ def check_csv(csv_file):
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
def generate_password():
|
|
||||||
random.seed()
|
|
||||||
alphabet = "abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
|
||||||
password = ""
|
|
||||||
for i in range(15):
|
|
||||||
password += random.choice(alphabet)
|
|
||||||
|
|
||||||
return password
|
|
||||||
|
|
||||||
|
|
||||||
def send_mail(election, mail_form):
|
def send_mail(election, mail_form):
|
||||||
"""Envoie le mail d'annonce de l'élection avec identifiants et mot de passe
|
"""Envoie le mail d'annonce de l'élection avec identifiants et mot de passe
|
||||||
aux votant·e·s, le mdp est généré en même temps que le mail est envoyé.
|
aux votant·e·s, le mdp est généré en même temps que le mail est envoyé.
|
||||||
|
@ -418,7 +409,7 @@ def send_mail(election, mail_form):
|
||||||
body=mail_form.cleaned_data["message"].format(
|
body=mail_form.cleaned_data["message"].format(
|
||||||
full_name=v.full_name,
|
full_name=v.full_name,
|
||||||
election_url=url,
|
election_url=url,
|
||||||
username=v.get_username(),
|
username=v.base_username,
|
||||||
password=password,
|
password=password,
|
||||||
),
|
),
|
||||||
to=[v.email],
|
to=[v.email],
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django import forms
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth import forms as auth_forms
|
from django.contrib.auth import forms as auth_forms
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.validators import validate_email
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
|
@ -61,3 +62,23 @@ class PwdResetForm(auth_forms.PasswordResetForm):
|
||||||
def get_users(self, email):
|
def get_users(self, email):
|
||||||
users = super().get_users(email)
|
users = super().get_users(email)
|
||||||
return (u for u in users if u.username.split("__")[0] == "pwd")
|
return (u for u in users if u.username.split("__")[0] == "pwd")
|
||||||
|
|
||||||
|
|
||||||
|
class PwdUserForm(forms.ModelForm):
|
||||||
|
"""
|
||||||
|
Allows for the creation of a Password Account given the email, base username and full name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
email = forms.EmailField(
|
||||||
|
label=_("Email"), required=True, validators=[validate_email]
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
# On rajoute le préfixe signifiant qu'on crée un compte avec mot de passe
|
||||||
|
cleaned_data = super().clean()
|
||||||
|
cleaned_data["username"] = "pwd__" + cleaned_data["username"]
|
||||||
|
return cleaned_data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = UserModel
|
||||||
|
fields = ["username", "full_name", "email"]
|
||||||
|
|
|
@ -8,4 +8,5 @@ urlpatterns = [
|
||||||
views.ElectionLoginView.as_view(),
|
views.ElectionLoginView.as_view(),
|
||||||
name="auth.election",
|
name="auth.election",
|
||||||
),
|
),
|
||||||
|
path("pwd-create", views.CreatePwdAccount.as_view(), name="auth.create-account"),
|
||||||
]
|
]
|
||||||
|
|
15
shared/auth/utils.py
Normal file
15
shared/auth/utils.py
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
# #############################################################################
|
||||||
|
# Fonctions universelles
|
||||||
|
# #############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
def generate_password(size=15):
|
||||||
|
random.seed()
|
||||||
|
alphabet = "abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
|
||||||
|
password = ""
|
||||||
|
for i in range(size):
|
||||||
|
password += random.choice(alphabet)
|
||||||
|
|
||||||
|
return password
|
|
@ -1,6 +1,15 @@
|
||||||
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.contrib.auth.hashers import make_password
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views.generic.edit import CreateView
|
||||||
|
|
||||||
from .forms import ElectionAuthForm
|
from .forms import ElectionAuthForm, PwdUserForm
|
||||||
|
from .utils import generate_password
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Election Specific Login
|
# Election Specific Login
|
||||||
|
@ -17,3 +26,23 @@ class ElectionLoginView(auth_views.LoginView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
kwargs.update({"election_id": self.kwargs.get("election_id")})
|
kwargs.update({"election_id": self.kwargs.get("election_id")})
|
||||||
return super().get_context_data(**kwargs)
|
return super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
# #############################################################################
|
||||||
|
# Creation of Password Accounts
|
||||||
|
# #############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
@method_decorator(staff_member_required, name="dispatch")
|
||||||
|
class CreatePwdAccount(CreateView):
|
||||||
|
model = User
|
||||||
|
form_class = PwdUserForm
|
||||||
|
template_name = "auth/create-user.html"
|
||||||
|
success_url = reverse_lazy("auth.create-account")
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
# On enregistre un mot de passe aléatoire
|
||||||
|
form.instance.password = make_password(generate_password(32))
|
||||||
|
|
||||||
|
# On envoie un mail pour réinitialiser le mot de passe
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
31
shared/templates/auth/create-user.html
Normal file
31
shared/templates/auth/create-user.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1 class="title">{% trans "Créer un compte avec mot de passe" %}</h1>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-two-thirds">
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% include "forms/form.html" with errors=True %}
|
||||||
|
|
||||||
|
<div class="field is-grouped is-centered">
|
||||||
|
<div class="control is-expanded">
|
||||||
|
<button class="button is-fullwidth is-outlined is-primary is-light">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="fas fa-check"></i>
|
||||||
|
</span>
|
||||||
|
<span>{% trans "Enregistrer" %}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -122,7 +122,7 @@
|
||||||
<div class="level is-mobile">
|
<div class="level is-mobile">
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<div class="tag">
|
<div class="tag">
|
||||||
{% blocktrans with name=user.get_username connection=user.connection_method %}Connecté·e en tant que {{ name }} par {{ connection }}{% endblocktrans %}
|
{% blocktrans with name=user.base_username connection=user.connection_method %}Connecté·e en tant que {{ name }} par {{ connection }}{% endblocktrans %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue