From 2d72b20cadec5f4d1d18c8211ee31a7537db8786 Mon Sep 17 00:00:00 2001 From: julien Date: Tue, 3 Nov 2026 15:18:09 +0100 Subject: [PATCH] Improve script --- 9 | 0 README.md | 66 +++++++++++++++---- bin/add-core-member | 51 +++++++++++++++ bin/initialize-core | 155 -------------------------------------------- config/rodauth.rb | 2 + 5 files changed, 107 insertions(+), 167 deletions(-) delete mode 100644 9 create mode 100644 bin/add-core-member delete mode 100644 bin/initialize-core diff --git a/9 b/9 deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 344cc40..9aca922 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,27 @@ openssl rand -hex 64 Ne pas versionner le fichier `.env`. +### Base de données + +En développement, la base est créée dans : + +```text +db/development.sqlite3 +``` + +Ce chemin est utilisé par défaut. Il est possible de le modifier +avec la variable d'environnement `DATABASE_PATH`. + +Le chemin indiqué est relatif au fichier `lib/database.rb`. + Créer ou mettre à jour la base de données : ```sh bundle exec ruby bin/migrate ``` +### Serveur + Démarrer le serveur de développement : ```sh @@ -50,22 +65,25 @@ 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. +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 : +### Initialisation du Noyau + +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. +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. +### Shell interactif + Pour ouvrir un shell interactif : ```sh @@ -80,6 +98,7 @@ et définit `RACK_ENV=production`. Le fichier d'environnement doit notamment définir : ```dotenv +DATABASE_PATH=../db/netig.sqlite3 SESSION_SECRET=... RODAUTH_HMAC_SECRET=... RODAUTH_DOMAIN=netig.net @@ -87,11 +106,34 @@ BASE_URL=https://netig.net SMTP_PASSWORD=... ``` -Générer les deux secrets avec `openssl rand -hex 64`. +Générer les deux secrets avec : + +```sh +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 : +### Base de données + +La base de production est stockée dans : + +```text +db/netig.sqlite3 +``` + +Le chemin `../db/netig.sqlite3` est relatif au fichier +`lib/database.rb`. Il désigne donc le dossier `db/` à la racine +du projet. + +Le dossier `db/` doit être conservé entre les déploiements et rester +accessible en écriture par l'utilisateur qui exécute Puma. + +Il doit également être inclus dans les sauvegardes. + +Créer ou mettre à jour la base de données dans le conteneur applicatif, +avec les mêmes variables d'environnement que l'application, avant +de démarrer la nouvelle version : ```sh bundle exec ruby bin/migrate @@ -111,8 +153,8 @@ 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 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. diff --git a/bin/add-core-member b/bin/add-core-member new file mode 100644 index 0000000..f77e7ff --- /dev/null +++ b/bin/add-core-member @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby + +require "dotenv/load" if ENV.fetch("RACK_ENV", "development") == "development" + +require_relative "../lib/database" + +abort "Usage: ruby bin/add-core-member EMAIL" unless ARGV.one? + +email = ARGV.first.strip.downcase +abort "Adresse électronique manquante." if email.empty? + +begin + DB.transaction do + verified_status_id = DB[:account_statuses] + .where(name: "Verified") + .get(:id) + + raise "Statut Verified introuvable." unless verified_status_id + + account = DB[:accounts] + .where(Sequel.function(:lower, :email) => email) + .first + + raise "Compte introuvable : #{email}" unless account + raise "Adresse électronique non vérifiée : #{email}" unless + account[:status_id] == verified_status_id + + member = DB[:members].where(account_id: account[:id]).first + + raise "Fiche membre introuvable." unless member + raise "Une personne physique est requise." unless + member[:kind] == "individual" + raise "Ce membre appartient déjà au Noyau." if member[:core_member] + + membership = DB[:memberships] + .where(member_id: member[:id], status: "accepted") + .first + + raise "Ce membre doit avoir une adhésion acceptée." unless membership + + updated = DB[:members] + .where(id: member[:id], core_member: false) + .update(core_member: true) + + raise "Impossible d'ajouter ce membre au Noyau." unless updated == 1 + end +rescue StandardError => e + abort "Erreur : #{e.message}" +end + +puts "#{email} a été ajouté au Noyau." diff --git a/bin/initialize-core b/bin/initialize-core deleted file mode 100644 index 900974f..0000000 --- a/bin/initialize-core +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env ruby - -require "dotenv/load" if ENV.fetch("RACK_ENV", "development") == "development" - -environment = ENV.fetch("RACK_ENV", "development") - -abort "Environnement non pris en charge." unless - %w[development production].include?(environment) - -require "date" -require "io/console" - -require_relative "../lib/database" - -console = IO.console or abort "Terminal interactif requis." - -if environment == "production" && - DB[:members].where(core_member: true).count.positive? - abort "Un Noyau existe déjà." -end - -verified_status_id = DB[:account_statuses] - .where(name: "Verified") - .get(:id) - -abort "Statut Verified introuvable." unless verified_status_id - -find_member = lambda do |email| - account = DB[:accounts] - .where(Sequel.function(:lower, :email) => email) - .first - - abort "Compte introuvable : #{email}" unless account - - abort "Adresse électronique non vérifiée : #{email}" unless - account[:status_id] == verified_status_id - - member = DB[:members] - .where(account_id: account[:id]) - .first - - abort "Fiche membre introuvable : #{email}" unless member - - abort "Une personne physique est requise : #{email}" unless - member[:kind] == "individual" - - member -end - -console.print "Date de l'assemblée (AAAA-MM-JJ) : " -date_input = console.gets&.strip - -unless date_input&.match?(/\A\d{4}-\d{2}-\d{2}\z/) - abort "Format attendu : AAAA-MM-JJ." -end - -begin - assembly_date = Date.iso8601(date_input) -rescue Date::Error - abort "Date invalide." -end - -abort "La date ne peut pas être dans le futur." if - assembly_date > Date.today - -assembly_datetime = Time.utc( - assembly_date.year, - assembly_date.month, - assembly_date.day -) - -console.puts -console.puts "Saisissez les adresses électroniques des membres désignés." -console.puts "Une adresse par ligne. Entrée pour terminer." -console.puts - -emails = [] - -loop do - console.print "Adresse électronique : " - email = console.gets&.strip&.downcase - - break if email.to_s.empty? - - abort "Adresse déjà saisie : #{email}" if emails.include?(email) - - emails << email -end - -minimum_members = environment == "production" ? 3 : 1 - -abort "Au moins #{minimum_members} membre(s) sont nécessaires." if - emails.length < minimum_members - -members = emails.map do |email| - [email, find_member.call(email)] -end - -console.puts -console.puts "Environnement : #{environment}" -console.puts "Date de l'assemblée : #{assembly_date}" -console.puts -console.puts "Membres du Noyau :" - -members.each do |email, member| - name = "#{member[:first_name]} #{member[:last_name]}" - console.puts " #{name} (#{email})" -end - -console.puts -console.print "Confirmer l'initialisation ? [o/N] " - -abort "Opération annulée." unless %w[o oui].include?( - console.gets&.strip&.downcase -) - -if environment == "production" && - DB[:members].where(core_member: true).count.positive? - abort "Un Noyau existe déjà." -end - -DB.transaction do - members.each do |_email, member| - membership = DB[:memberships] - .where( - member_id: member[:id], - status: %w[pending accepted] - ) - .first - - if membership && membership[:status] == "pending" - DB[:memberships] - .where(id: membership[:id]) - .update( - status: "accepted", - decided_at: assembly_datetime, - recorded_by: nil - ) - elsif membership.nil? - DB[:memberships].insert( - member_id: member[:id], - status: "accepted", - requested_at: assembly_datetime, - decided_at: assembly_datetime, - recorded_by: nil - ) - end - - DB[:members] - .where(id: member[:id]) - .update(core_member: true) - end -end - -puts "Membres du Noyau enregistrés (#{members.length})." diff --git a/config/rodauth.rb b/config/rodauth.rb index 3a33e70..67f2d6a 100644 --- a/config/rodauth.rb +++ b/config/rodauth.rb @@ -11,6 +11,8 @@ class Netig account_unverified_status_value 1 account_open_status_value 2 + normalize_login(&:downcase) + email_from "NETig " title_instance_variable :@page_title