From e5ec0ff1a15018c938a37faecaf05a4fce854590 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 3 Nov 2026 12:08:57 +0100 Subject: [PATCH] Add registration --- 9 | 0 README.md | 94 ++++++++++++++++---------- bin/initialize-account | 89 ------------------------- netig.rb | 93 +++++++++++++++++++++++++- views/create-account.erb | 140 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 291 insertions(+), 125 deletions(-) create mode 100644 9 delete mode 100644 bin/initialize-account create mode 100644 views/create-account.erb diff --git a/9 b/9 new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 886b898..344cc40 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,10 @@ ## À faire - limiter le spam sur `/contact/send` -- développer l'inscription des utilisateurs et la vérification des adresses électroniques - développer les demandes d'adhésion et leur examen par le Noyau -- développer l'espace personnel des adhérents +- développer l'espace personnel des membres - afficher les recettes et les dépenses sur la page d'accueil -- gérer les accès aux services selon la situation des adhérents +- gérer les accès aux services selon la situation des membres ## Développement @@ -21,10 +20,18 @@ Créer un fichier `.env` à la racine du projet : ```dotenv SESSION_SECRET=... +RODAUTH_HMAC_SECRET=... +RODAUTH_DOMAIN=netig.net +BASE_URL=http://[::1]:9292 SMTP_PASSWORD=... ``` -Générer `SESSION_SECRET` avec `openssl rand -hex 64`. +Générer `SESSION_SECRET` et `RODAUTH_HMAC_SECRET` avec : + +```sh +openssl rand -hex 64 +``` + Ne pas versionner le fichier `.env`. Créer ou mettre à jour la base de données : @@ -33,32 +40,33 @@ Créer ou mettre à jour la base de données : bundle exec ruby bin/migrate ``` -Créer un ou plusieurs comptes de test : - -```sh -bundle exec ruby bin/initialize-account -``` - -Cette commande crée un compte vérifié et sa fiche de membre. -Elle peut être exécutée plusieurs fois. Les comptes créés ne possèdent -aucune adhésion ni responsabilité au sein du Noyau. - -Pour tester l'espace du Noyau, désigner un ou plusieurs comptes de test : - -```sh -bundle exec ruby bin/initialize-core -``` - -En développement, un seul membre suffit. Cette commande peut être -réexécutée pour ajouter d'autres membres au Noyau. - Démarrer le serveur de développement : ```sh bundle exec puma ``` -Ou ouvrir un shell interactif : +Créer des comptes de test depuis le site : + +http://[::1]:9292/create-account + +Les personnes physiques et les personnes morales peuvent créer +un compte. L'adresse électronique doit être vérifiée avant de +pouvoir se connecter. + +Pour tester l'espace du Noyau, désigner un ou plusieurs comptes +de test depuis le terminal : + +```sh +bundle exec ruby bin/initialize-core +``` + +En développement, un seul membre suffit. Cette commande peut +être réexécutée pour ajouter d'autres membres au Noyau. + +La date de l'assemblée est demandée lors de l'exécution. + +Pour ouvrir un shell interactif : ```sh bundle exec irb -r dotenv/load -r ./netig.rb @@ -66,11 +74,24 @@ bundle exec irb -r dotenv/load -r ./netig.rb ## Production -Docker Compose fournit les variables d'environnement via `env_file` et définit -`RACK_ENV=production`. +Docker Compose fournit les variables d'environnement via `env_file` +et définit `RACK_ENV=production`. -Exécuter les migrations dans le conteneur applicatif avant de démarrer -la nouvelle version : +Le fichier d'environnement doit notamment définir : + +```dotenv +SESSION_SECRET=... +RODAUTH_HMAC_SECRET=... +RODAUTH_DOMAIN=netig.net +BASE_URL=https://netig.net +SMTP_PASSWORD=... +``` + +Générer les deux secrets avec `openssl rand -hex 64`. +Ne pas versionner le fichier contenant ces variables. + +Créer ou mettre à jour la base de données dans le conteneur +applicatif avant de démarrer la nouvelle version : ```sh bundle exec ruby bin/migrate @@ -78,19 +99,22 @@ bundle exec ruby bin/migrate ### Initialisation du premier Noyau -Une fois l'inscription publique disponible, les membres fondateurs créent -leurs comptes depuis le site et vérifient leurs adresses électroniques. +Une fois l'inscription publique disponible, les membres fondateurs +créent leurs comptes depuis le site et vérifient leurs adresses +électroniques. -Après leur désignation par l'assemblée constitutive, initialiser le Noyau -depuis le conteneur applicatif : +Après leur désignation par l'assemblée constitutive, initialiser +le Noyau depuis le conteneur applicatif : ```sh bundle exec ruby bin/initialize-core ``` Cette commande doit être exécutée une seule fois en production. -Elle exige au moins trois personnes physiques disposant d'un compte vérifié. -Elle enregistre leurs adhésions comme acceptées et leur attribue la qualité -de membre du Noyau. +Elle exige au moins trois personnes physiques disposant d'un +compte vérifié. + +Elle enregistre leurs adhésions comme acceptées et leur attribue +la qualité de membre du Noyau. La date de l'assemblée constitutive est demandée lors de l'exécution. diff --git a/bin/initialize-account b/bin/initialize-account deleted file mode 100644 index cea7cd8..0000000 --- a/bin/initialize-account +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env ruby - -environment = ENV.fetch("RACK_ENV", "development") -require "dotenv/load" if environment == "development" - -abort "Ce script est réservé au développement." unless - ENV.fetch("RACK_ENV", "development") == "development" - -require "io/console" -require "rodauth" - -require_relative "../lib/database" - -console = IO.console or abort "Terminal interactif requis." - -console.print "Adresse électronique : " -email = console.gets&.strip&.downcase - -abort "Adresse électronique obligatoire." if email.to_s.empty? - -existing_account = DB[:accounts] - .where(Sequel.function(:lower, :email) => email) - .count - .positive? - -abort "Ce compte existe déjà." if existing_account - -console.print "Prénom : " -first_name = console.gets&.strip - -console.print "Nom : " -last_name = console.gets&.strip - -abort "Prénom et nom obligatoires." if - first_name.to_s.empty? || last_name.to_s.empty? - -password = console.getpass("Mot de passe : ") -confirmation = console.getpass("Confirmer le mot de passe : ") - -abort "Mot de passe obligatoire." if password.to_s.empty? -abort "Les mots de passe ne correspondent pas." unless - password == confirmation - -verified_status_id = DB[:account_statuses] - .where(name: "Verified") - .get(:id) - -abort "Statut Verified introuvable." unless verified_status_id - -console.puts -console.puts "Compte : #{first_name} #{last_name} (#{email})" -console.puts -console.print "Confirmer la création ? [o/N] " - -abort "Opération annulée." unless %w[o oui].include?( - console.gets&.strip&.downcase -) - -auth = Rodauth.lib do - db DB - enable :create_account - - already_logged_in { super() } -end - -DB.transaction do - auth.create_account( - login: email, - password: password - ) - - account_id = auth.account_id_for_login(login: email) - - DB[:accounts] - .where(id: account_id) - .update(status_id: verified_status_id) - - DB[:members].insert( - account_id: account_id, - kind: "individual", - first_name: first_name, - last_name: last_name, - organization_name: nil, - core_member: false - ) -end - -puts "Compte de développement créé." - diff --git a/netig.rb b/netig.rb index 4c45126..d11809c 100644 --- a/netig.rb +++ b/netig.rb @@ -19,7 +19,17 @@ class Netig < Roda plugin :rodauth do db DB - enable :login, :logout + enable :login, :logout, :create_account, :verify_account + + domain ENV.fetch("RODAUTH_DOMAIN") + + account_unverified_status_value 1 + account_open_status_value 2 + + base_url ENV.fetch("BASE_URL") + hmac_secret ENV.fetch("RODAUTH_HMAC_SECRET") + + email_from "NETig " login_label "Adresse électronique" password_label "Mot de passe" @@ -28,6 +38,87 @@ class Netig < Roda login_redirect "/temporary_page" login_return_to_requested_location? true + create_account_page_title "Créer un compte — NETig" + create_account_button "Créer mon compte" + create_account_link_text "Créer un compte" + + verify_account_page_title "Vérifier votre adresse électronique — NETig" + verify_account_button "Confirmer mon adresse électronique" + verify_account_set_password? true + + verify_account_email_subject "Confirmez votre adresse électronique — NETig" + + verify_account_email_body do + <<~EMAIL + Bonjour, + + Pour vérifier votre adresse électronique et activer votre compte + NETig, ouvrez le lien suivant : + + #{verify_account_email_link} + + Si vous n'êtes pas à l'origine de cette demande, ignorez ce message. + + L'équipe NETig + EMAIL + end + + verify_account_email_sent_notice_flash( + "Un courriel de vérification vient de vous être envoyé." + ) + + verify_account_notice_flash( + "Votre adresse électronique est maintenant vérifiée." + ) + + before_create_account do + case param("kind") + when "individual" + throw_error_status( + 422, "first_name", "doit être renseigné" + ) if param("first_name").to_s.strip.empty? + + throw_error_status( + 422, "last_name", "doit être renseigné" + ) if param("last_name").to_s.strip.empty? + + when "organization" + throw_error_status( + 422, "organization_name", "doit être renseignée" + ) if param("organization_name").to_s.strip.empty? + + else + throw_error_status( + 422, "kind", "choisissez un type de compte" + ) + end + end + + after_create_account do + member = if param("kind") == "individual" + { + kind: "individual", + first_name: param("first_name").to_s.strip, + last_name: param("last_name").to_s.strip, + organization_name: nil + } + else + { + kind: "organization", + first_name: nil, + last_name: nil, + organization_name: param("organization_name").to_s.strip + } + end + + db[:members].insert( + member.merge( + account_id: account[:id], + core_member: false + ) + ) + end + already_logged_in do request.redirect("/") end diff --git a/views/create-account.erb b/views/create-account.erb new file mode 100644 index 0000000..1d13946 --- /dev/null +++ b/views/create-account.erb @@ -0,0 +1,140 @@ +<% kind = request.params["kind"] %> +<% valid_kind = %w[individual organization].include?(kind) %> + +
+
+

Créer un compte

+ +

+ Créez un compte pour accéder à votre espace personnel + et, si vous le souhaitez, demander à rejoindre NETig. +

+ + <% if error = flash["error"] %> + + <% end %> + + <% unless valid_kind %> +

Quel type de compte souhaitez-vous créer ?

+ + + + <% else %> +
+ <%== rodauth.csrf_tag %> + + + + <% if kind == "individual" %> +

Personne physique

+ + + " + required + > + + <% if error = rodauth.field_error("first_name") %> +

<%= error %>

+ <% end %> + + + " + required + > + + <% if error = rodauth.field_error("last_name") %> +

<%= error %>

+ <% end %> + + <% else %> +

Personne morale

+ + + " + required + > + + <% if error = rodauth.field_error("organization_name") %> +

<%= error %>

+ <% end %> + <% end %> + + + + + <% if error = rodauth.field_error(rodauth.login_param) %> +

<%= error %>

+ <% end %> + +

+ Nous vous enverrons un courriel pour vérifier votre adresse + électronique. Vous choisirez votre mot de passe à cette étape. +

+ + +
+ +

+ + Changer de type de compte + +

+ <% end %> + +

+ Vous avez déjà un compte ? + Se connecter. +

+
+