Compare commits

..

4 commits

6 changed files with 169 additions and 53 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ __pycache__/
!.static/.gitkeep !.static/.gitkeep
src/shared/static/bulma/bulma.css src/shared/static/bulma/bulma.css
src/shared/static/bulma/bulma.css.map src/shared/static/bulma/bulma.css.map
.credentials/KANIDM_AUTH_TOKEN

View file

@ -26,11 +26,19 @@ class CreateKanidmAccountForm(forms.Form):
displayname = CharField(label=_("Nom d'usage")) displayname = CharField(label=_("Nom d'usage"))
mail = EmailField( mail = EmailField(
label=_("Adresse e-mail"), label=_("Adresse e-mail"),
help_text=_("De préférence l'adresse '@ens.psl.eu' (si en scola) ou '@normalesup.org' (si archikhûbe), sauf si exté (accord explicite du bureau nécessaire)."), help_text=_(
"De préférence :<br>"
"- l'adresse <code>@ens.psl.eu</code> pour les personnes en scolarité ;<br>"
"- l'adresse <code>@normalesup.org</code> pour les personnes ayant fini leur scolarité ;<br>"
"<b>Pour les personnes extérieures, le bureau doit donner son accord.</b>"
),
) )
active = BooleanField( active = BooleanField(
label=_("Membre actif"), label=_("Membre actif"),
help_text=_("Si selectionné, la personne sera ajoutée au groupe dgnum_members. L'accord du bureau est nécessaire pour cette opération donnant des privilèges."), help_text=_(
"Si selectionné, la personne sera ajoutée au groupe <code>dgnum_members</code>.<br>"
"<b>L'accord préalable du bureau est nécessaire !</b>"
),
required=False, required=False,
) )

View file

@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-10-12 20:04
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("dgsi", "0007_alter_user_accepted_bylaws_and_more"),
]
operations = [
migrations.AlterField(
model_name="user",
name="accepted_statutes",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="dgsi.statutes",
verbose_name="Derniers Statuts acceptés",
),
),
]

View file

@ -3,6 +3,7 @@ from dataclasses import dataclass
from functools import cached_property from functools import cached_property
from typing import Optional, Self from typing import Optional, Self
from aiohttp.client_exceptions import ClientConnectorError
from allauth.socialaccount.models import SocialAccount from allauth.socialaccount.models import SocialAccount
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
@ -13,7 +14,6 @@ from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from kanidm.exceptions import NoMatchingEntries from kanidm.exceptions import NoMatchingEntries
from kanidm.models.person import Person from kanidm.models.person import Person
from kanidm.radius import ClientConnectorError
from shared.kanidm import klient from shared.kanidm import klient
@ -145,7 +145,7 @@ class User(AbstractUser):
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
null=True, null=True,
default=None, default=None,
verbose_name=_("Derniers statuts acceptés"), verbose_name=_("Derniers Statuts acceptés"),
) )
accepted_bylaws = models.ForeignKey( accepted_bylaws = models.ForeignKey(
Bylaws, Bylaws,

View file

@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: dgsi.dgnum.eu\n" "Project-Id-Version: dgsi.dgnum.eu\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-09-26 22:48+0200\n" "POT-Creation-Date: 2024-10-12 21:59+0200\n"
"PO-Revision-Date: 2024-09-26 22:49+0200\n" "PO-Revision-Date: 2024-10-12 22:04+0200\n"
"Last-Translator: Tom Hubrecht <tom.hubrecht@dgnum.eu>\n" "Last-Translator: Tom Hubrecht <tom.hubrecht@dgnum.eu>\n"
"Language-Team: French\n" "Language-Team: French\n"
"Language: fr\n" "Language: fr\n"
@ -18,10 +18,14 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1)\n" "Plural-Forms: nplurals=2; plural=(n > 1)\n"
"X-Generator: Gtranslator 46.1\n" "X-Generator: Gtranslator 46.1\n"
#: app/settings.py:276 #: app/settings.py:321
msgid "Administration de DGSI" msgid "Administration de DGSI"
msgstr "DGSI Administration" msgstr "DGSI Administration"
#: dgsi/admin.py:51
msgid "Documents DGNum"
msgstr "DGNum Documents"
#: dgsi/forms.py:16 #: dgsi/forms.py:16
msgid "Identifiant déjà présent dans la base de données." msgid "Identifiant déjà présent dans la base de données."
msgstr "Username already in the database." msgstr "Username already in the database."
@ -31,74 +35,97 @@ msgid "Identifiant"
msgstr "Username" msgstr "Username"
#: dgsi/forms.py:23 #: dgsi/forms.py:23
msgid "De préférence identique au login ENS de la personne concernée" msgid "De préférence identique au login ENS de la personne concernée."
msgstr "Preferably identical to the ENS login of the person concerned" msgstr "Preferably identical to the ENS login of the person concerned."
#: dgsi/forms.py:26 dgsi/forms.py:39 #: dgsi/forms.py:26 dgsi/forms.py:47
msgid "Nom d'usage" msgid "Nom d'usage"
msgstr "Name in use" msgstr "Name in use"
#: dgsi/forms.py:28 dgsi/forms.py:41 #: dgsi/forms.py:28 dgsi/forms.py:49
msgid "Adresse e-mail" msgid "Adresse e-mail"
msgstr "E-mail address" msgstr "E-mail address"
#: dgsi/forms.py:29 dgsi/forms.py:42 #: dgsi/forms.py:30
msgid "De préférence l'adresse '@ens.psl.eu'" msgid ""
msgstr "Preferably the @ens.psl.eu address" "De préférence :<br>- l'adresse <code>@ens.psl.eu</code> pour les personnes "
"en scolarité ;<br>- l'adresse <code>@normalesup.org</code> pour les "
"personnes ayant fini leur scolarité ;<br><b>Pour les personnes extérieures, "
"le bureau doit donner son accord.</b>"
msgstr ""
"Preferably:<br>- the <code>@ens.psl.eu</code> address for students;<br>- the "
"<code>@normalesup.org</code> address for people having finished their "
"studies;<br><b>For outsiders, the board must give its approval.</b>"
#: dgsi/forms.py:32 #: dgsi/forms.py:37
msgid "Membre actif" msgid "Membre actif"
msgstr "Active member" msgstr "Active member"
#: dgsi/forms.py:33 #: dgsi/forms.py:39
msgid "Si selectionné, la personne sera ajoutée au groupe dgnum_members" msgid ""
msgstr "If selected, the person will be added to the dgnum_members group." "Si selectionné, la personne sera ajoutée au groupe <code>dgnum_members</"
"code>.<br><b>L'accord préalable du bureau est nécessaire !</b>"
msgstr ""
"If selected, the person will be added to the <code>dgnum_members</code> "
"group.<br><b>Prior approval from the board is required!</b>"
#: dgsi/models.py:22 #: dgsi/forms.py:50
msgid "De préférence l'adresse '@ens.psl.eu'"
msgstr "Preferably the @ens.psl.eu address"
#: dgsi/models.py:24
msgid "Nom du service proposé" msgid "Nom du service proposé"
msgstr "Name of the proposed service" msgstr "Name of the proposed service"
#: dgsi/models.py:23 #: dgsi/models.py:25
msgid "Adresse du service" msgid "Adresse du service"
msgstr "Address of the service" msgstr "Address of the service"
#: dgsi/models.py:24 #: dgsi/models.py:26
msgid "Icône du service" msgid "Icône du service"
msgstr "Icon of the service" msgstr "Icon of the service"
#: dgsi/models.py:34 #: dgsi/models.py:36
msgid "Date du document" msgid "Date du document"
msgstr "Document date" msgstr "Document date"
#: dgsi/models.py:35 #: dgsi/models.py:37
msgid "Nom du document" msgid "Nom du document"
msgstr "Document name" msgstr "Document name"
#: dgsi/models.py:36 #: dgsi/models.py:38
msgid "Fichier PDF" msgid "Fichier PDF"
msgstr "PDF file" msgstr "PDF file"
#: dgsi/models.py:58 dgsi/models.py:59 #: dgsi/models.py:60 dgsi/models.py:61
#: dgsi/templates/dgsi/legal_documents.html:26 #: dgsi/templates/dgsi/legal_documents.html:26
msgid "Statuts" msgid "Statuts"
msgstr "Statutes" msgstr "Statutes"
#: dgsi/models.py:71 dgsi/templates/dgsi/legal_documents.html:30 #: dgsi/models.py:73 dgsi/templates/dgsi/legal_documents.html:30
msgid "Règlement Intérieur" msgid "Règlement Intérieur"
msgstr "Bylaws" msgstr "Bylaws"
#: dgsi/models.py:72 #: dgsi/models.py:74
msgid "Règlements Intérieurs" msgid "Règlements Intérieurs"
msgstr "Bylaws" msgstr "Bylaws"
#: dgsi/models.py:114 #: dgsi/models.py:116
msgid "Correspondance de login" msgid "Correspondance de login"
msgstr "Login mapping" msgstr "Login mapping"
#: dgsi/models.py:115 #: dgsi/models.py:117
msgid "Correspondances de login" msgid "Correspondances de login"
msgstr "Login mappings" msgstr "Login mappings"
#: dgsi/models.py:148
msgid "Derniers Statuts acceptés"
msgstr "Latest accepted Statutes"
#: dgsi/models.py:155
msgid "Dernier Règlement Intérieur accepté"
msgstr "Latest accepted Bylaws"
#: dgsi/templates/_legal_document.html:9 #: dgsi/templates/_legal_document.html:9
msgid "" msgid ""
" En acceptant, vous assurez avoir lu ce document et en approuver le contenu." " En acceptant, vous assurez avoir lu ce document et en approuver le contenu."
@ -154,31 +181,43 @@ msgstr "Accept the bylaws"
msgid "Profil de %(displayname)s" msgid "Profil de %(displayname)s"
msgstr "Profile of %(displayname)s" msgstr "Profile of %(displayname)s"
#: dgsi/templates/dgsi/profile.html:13 #: dgsi/templates/dgsi/profile.html:14
msgid "Mot de passe WiFi :" msgid "Mot de passe WiFi :"
msgstr "WiFi password:" msgstr "WiFi password:"
#: dgsi/templates/dgsi/profile.html:23 #: dgsi/templates/dgsi/profile.html:16
msgid "Êtes-vous sûr·e de vouloir réinitialiser votre mot de passe WiFi ?"
msgstr "Are you sure that you want to reset your WiFi password?"
#: dgsi/templates/dgsi/profile.html:19
msgid "Réinitialiser le mot de passe WiFi"
msgstr "Reset the WiFi password"
#: dgsi/templates/dgsi/profile.html:32
msgid "Générer un mot de passe WiFi"
msgstr "Generate a WiFi password:"
#: dgsi/templates/dgsi/profile.html:36
msgid "Adresse e-mail :" msgid "Adresse e-mail :"
msgstr "E-mail address:" msgstr "E-mail address:"
#: dgsi/templates/dgsi/profile.html:28 #: dgsi/templates/dgsi/profile.html:41
msgid "Informations techniques" msgid "Informations techniques"
msgstr "Technical informations" msgstr "Technical informations"
#: dgsi/templates/dgsi/profile.html:31 #: dgsi/templates/dgsi/profile.html:44
msgid "Identifiant unique :" msgid "Identifiant unique :"
msgstr "Unique identifier:" msgstr "Unique identifier:"
#: dgsi/templates/dgsi/profile.html:40 #: dgsi/templates/dgsi/profile.html:53
msgid "Membre des groupes suivants :" msgid "Membre des groupes suivants :"
msgstr "Member of the following groups:" msgstr "Member of the following groups:"
#: dgsi/templates/dgsi/profile.html:51 #: dgsi/templates/dgsi/profile.html:64
msgid "Pas de compte DGNum répertorié." msgid "Pas de compte DGNum répertorié."
msgstr "No DGNum account found." msgstr "No DGNum account found."
#: dgsi/templates/dgsi/profile.html:54 #: dgsi/templates/dgsi/profile.html:67
msgid "Créer un compte DGNum" msgid "Créer un compte DGNum"
msgstr "Create a DGNum account" msgstr "Create a DGNum account"
@ -194,45 +233,49 @@ msgstr "My profile"
msgid "Documents Légaux" msgid "Documents Légaux"
msgstr "Legal Documents" msgstr "Legal Documents"
#: dgsi/views.py:35 #: dgsi/views.py:32
msgid "Services proposés par la DGNum" msgid "Services proposés"
msgstr "Services offered by the DGNum" msgstr "Services offered"
#: dgsi/views.py:44 #: dgsi/views.py:39
msgid "Créer un nouveau compte Kanidm" msgid "Créer un compte Kanidm"
msgstr "Create a new Kanidm account" msgstr "Create a Kanidm account"
#: dgsi/views.py:48 #: dgsi/views.py:43 shared/templates/_hero.html:76
msgid "Interface d'administration" msgid "Interface d'administration"
msgstr "Administration interface" msgstr "Administration interface"
#: dgsi/views.py:83 #: dgsi/views.py:80
msgid "Compte DGNum inexistant."
msgstr "No existing DGNum account."
#: dgsi/views.py:97
msgid "Compte DGNum créé avec succès" msgid "Compte DGNum créé avec succès"
msgstr "DGNum account successfully created" msgstr "DGNum account successfully created"
#: dgsi/views.py:99 #: dgsi/views.py:113
msgid "<b>Vous possédez déjà un compte DGNum !</b>" msgid "<b>Vous possédez déjà un compte DGNum !</b>"
msgstr "<b>You already have a DGNum account!</b>" msgstr "<b>You already have a DGNum account!</b>"
#: dgsi/views.py:111 #: dgsi/views.py:125
msgid "Vous devez accepter les Statuts et le Règlement Intérieur." msgid "Vous devez accepter les Statuts et le Règlement Intérieur."
msgstr "You must accept the Statutes and the Bylaws." msgstr "You must accept the Statutes and the Bylaws."
#: dgsi/views.py:190 #: dgsi/views.py:204
#, python-format #, python-format
msgid "Type de document invalide : %(kind)s" msgid "Type de document invalide : %(kind)s"
msgstr "Invalid document type: %(kind)s" msgstr "Invalid document type: %(kind)s"
#: dgsi/views.py:220 #: dgsi/views.py:234
#, python-format #, python-format
msgid "Compte DGNum pour %(displayname)s [%(name)s] créé." msgid "Compte DGNum pour %(displayname)s [%(name)s] créé."
msgstr "DGNum account for %(displayname)s [%(name)s] created." msgstr "DGNum account for %(displayname)s [%(name)s] created."
#: shared/account.py:37 #: shared/account.py:40
msgid "Catégorie de compte ENS interdite." msgid "Catégorie de compte ENS interdite."
msgstr "ENS account category not permitted." msgstr "ENS account category not permitted."
#: shared/account.py:53 #: shared/account.py:57
msgid "Méthode de connexion invalide." msgid "Méthode de connexion invalide."
msgstr "Invalid connection method." msgstr "Invalid connection method."
@ -242,18 +285,30 @@ msgid ""
msgstr "" msgstr ""
"Software developed for and by the <a href=https://dgnum.eu>DGNum</a>." "Software developed for and by the <a href=https://dgnum.eu>DGNum</a>."
#: shared/templates/_hero.html:18 #: shared/templates/_hero.html:18 shared/templates/account/logout.html:6
msgid "Déconnexion" msgid "Déconnexion"
msgstr "Logout" msgstr "Logout"
#: shared/templates/_hero.html:27 #: shared/templates/_hero.html:27 shared/templates/socialaccount/login.html:6
msgid "Connexion" msgid "Connexion"
msgstr "Login" msgstr "Login"
#: shared/templates/_hero.html:41 #: shared/templates/_hero.html:40
msgid "Choix de la langue" msgid "Choix de la langue"
msgstr "Language selection" msgstr "Language selection"
#: shared/templates/account/login.html:7
msgid "Connexion via un compte tiers"
msgstr "Connection via a third-party account"
#: shared/templates/account/logout.html:10
msgid "Êtes vous certain·e de vouloir vous déconnecter ?"
msgstr "Are you sure you want to log out?"
#: shared/templates/account/logout.html:16
msgid "Se déconnecter"
msgstr "Log out"
#: shared/templates/accounts/forbidden_category.html:6 #: shared/templates/accounts/forbidden_category.html:6
msgid "Connexion impossible" msgid "Connexion impossible"
msgstr "Unable to connect" msgstr "Unable to connect"
@ -267,3 +322,30 @@ msgstr ""
"Your details do not allow the DGNum to authenticate you.<br>If you think " "Your details do not allow the DGNum to authenticate you.<br>If you think "
"this is a mistake, please contact us at: <a href=\"mailto:contact@dgnum." "this is a mistake, please contact us at: <a href=\"mailto:contact@dgnum."
"eu\">contact@dgnum.eu</a>" "eu\">contact@dgnum.eu</a>"
#: shared/templates/socialaccount/authentication_error.html:7
msgid "Erreur lors de la connexion"
msgstr "Error during login"
#: shared/templates/socialaccount/authentication_error.html:11
msgid ""
"Une erreur est survenue lors de votre tentative de connexion avec un compte "
"tiers."
msgstr ""
"An error has occurred while trying to login with a third-party account."
#: shared/templates/socialaccount/login.html:11
#, python-format
msgid "Se connecter via un compte <b>%(provider)s</b>"
msgstr "Log in with a <b>%(provider)s</b> account"
#: shared/templates/socialaccount/login.html:16
#, python-format
msgid ""
"Vous vous apprêtez à vous connecter à l'aide d'un compte tiers provenant de "
"%(provider)s."
msgstr "You are about to log in using a third-party account from %(provider)s."
#: shared/templates/socialaccount/login.html:21
msgid "Continuer"
msgstr "Continue"