feat(account): Add a view to create accounts

TODO: include the reset mechanism for the password
This commit is contained in:
Tom Hubrecht 2024-09-19 11:37:45 +02:00
parent cd8859f610
commit 36ccc6be24
Signed by: thubrecht
SSH key fingerprint: SHA256:r+nK/SIcWlJ0zFZJGHtlAoRwq1Rm+WcKAm5ADYMoQPc
5 changed files with 86 additions and 5 deletions

35
src/dgsi/forms.py Normal file
View file

@ -0,0 +1,35 @@
from asgiref.sync import async_to_sync
from django.core.exceptions import ValidationError
from django.forms import BooleanField, CharField, EmailField, forms
from django.utils.translation import gettext_lazy as _
from shared.kanidm import client
@async_to_sync
async def name_validator(value: str) -> None:
try:
await client.person_account_get(value)
except ValueError:
return
raise ValidationError(_("Identifiant déjà présent dans la base de données."))
class CreateKanidmAccountForm(forms.Form):
# TODO: Add a field for the clipper login information for the local mapping
name = CharField(
label=_("Identifiant"),
help_text=_("De préférence identique au login ENS de la personne concernée"),
validators=[name_validator],
)
displayname = CharField(label=_("Nom d'usage"))
mail = EmailField(
label=_("Adresse e-mail"),
help_text=_("De préférence l'adresse '@ens.psl.eu'"),
)
active = BooleanField(
label=_("Membre actif"),
help_text=_("Si selectionné, la personne sera ajoutée au groupe dgnum_members"),
required=False,
)

View file

@ -6,7 +6,11 @@ app_name = "dgsi"
urlpatterns = [ urlpatterns = [
path("accounts/profile/", views.ProfileView.as_view(), name="dgn-profile"), path("accounts/profile/", views.ProfileView.as_view(), name="dgn-profile"),
path("accounts/create/", views.CreateUserView.as_view(), name="dgn-create_user"), path(
"accounts/create-kanidm/",
views.CreateKanidmAccountView.as_view(),
name="dgn-create_user",
),
path( path(
"accounts/forbidden/", "accounts/forbidden/",
views.TemplateView.as_view(template_name="account/forbidden_category.html"), views.TemplateView.as_view(template_name="account/forbidden_category.html"),

View file

@ -1,8 +1,12 @@
from asgiref.sync import async_to_sync
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, TemplateView from django.urls import reverse_lazy
from django.views.generic import FormView, TemplateView
from dgsi.forms import CreateKanidmAccountForm
from dgsi.mixins import StaffRequiredMixin from dgsi.mixins import StaffRequiredMixin
from dgsi.models import User from dgsi.models import User
from shared.kanidm import client
class ProfileView(LoginRequiredMixin, TemplateView): class ProfileView(LoginRequiredMixin, TemplateView):
@ -18,5 +22,26 @@ class ProfileView(LoginRequiredMixin, TemplateView):
) )
class CreateUserView(StaffRequiredMixin, CreateView): class CreateKanidmAccountView(StaffRequiredMixin, FormView):
model = User form_class = CreateKanidmAccountForm
template_name = "account/create_kanidm.html"
success_url = reverse_lazy("dgsi:dgn-create_user")
@async_to_sync
async def form_valid(self, form):
d = form.cleaned_data
# Create the base account
await client.person_account_create(d["name"], d["displayname"])
# Update the information
await client.person_account_update(d["name"], mail=d["mail"])
# If necessary, add the user to the active members group
if d["active"]:
await client.group_add_members("dgnum_members", [d["name"]])
# TODO: Generate a reset token, and update it
return super().form_valid(form)

View file

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<h2 class="subtitle">{% trans "Création de compte Kanidm" %}</h2>
<hr>
<form class="container is-max-tablet" method="post">
{% csrf_token %}
{% include "bulma/form.html" with form=form %}
<button class="button is-fullwidth mt-6">{% trans "Enregistrer" %}</button>
</form>
{% endblock content %}

View file

@ -3,6 +3,9 @@
{% block content %} {% block content %}
{% if user.is_authenticated %} {% if user.is_authenticated %}
<a class="button is-fullwidth is-size-4 is-primary has-text-dark" href="{% url 'dgsi:dgn-profile' %}">{% trans "Mon profil" %}</a> <a class="button is-fullwidth is-size-4 is-primary has-text-dark block" href="{% url 'dgsi:dgn-profile' %}">{% trans "Mon profil" %}</a>
{% endif %}
{% if user.is_admin %}
<a class="button is-fullwidth is-size-4 is-danger has-text-dark block" href="{% url 'dgsi:dgn-create_user' %}">{% trans "Créer un nouveau compte" %}</a>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}