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 = [
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(
"accounts/forbidden/",
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.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.models import User
from shared.kanidm import client
class ProfileView(LoginRequiredMixin, TemplateView):
@ -18,5 +22,26 @@ class ProfileView(LoginRequiredMixin, TemplateView):
)
class CreateUserView(StaffRequiredMixin, CreateView):
model = User
class CreateKanidmAccountView(StaffRequiredMixin, FormView):
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 %}
{% 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 %}
{% endblock content %}