Add registration
This commit is contained in:
1 parent
137e53618b
commit
e5ec0ff1a1
5 files changed
+291
-125
No files matched your search
@@ -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.
|
||||
@@ -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éé."
|
||||
|
||||
@@ -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 <noreply@netig.net>"
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
<% kind = request.params["kind"] %>
|
||||
<% valid_kind = %w[individual organization].include?(kind) %>
|
||||
|
||||
<section class="page-section">
|
||||
<div class="content page-panel">
|
||||
<h1>Créer un compte</h1>
|
||||
|
||||
<p>
|
||||
Créez un compte pour accéder à votre espace personnel
|
||||
et, si vous le souhaitez, demander à rejoindre NETig.
|
||||
</p>
|
||||
|
||||
<% if error = flash["error"] %>
|
||||
<p class="flash flash--error" role="alert"><%= error %></p>
|
||||
<% end %>
|
||||
|
||||
<% unless valid_kind %>
|
||||
<p>Quel type de compte souhaitez-vous créer ?</p>
|
||||
|
||||
<div class="hero__actions">
|
||||
<a
|
||||
class="button button--secondary"
|
||||
href="<%= rodauth.create_account_path %>?kind=individual"
|
||||
>
|
||||
Personne physique
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="button button--secondary"
|
||||
href="<%= rodauth.create_account_path %>?kind=organization"
|
||||
>
|
||||
Personne morale
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<% else %>
|
||||
<form
|
||||
action="<%= rodauth.create_account_path %>"
|
||||
method="post"
|
||||
class="contact-form"
|
||||
accept-charset="UTF-8"
|
||||
>
|
||||
<%== rodauth.csrf_tag %>
|
||||
|
||||
<input type="hidden" name="kind" value="<%= kind %>">
|
||||
|
||||
<% if kind == "individual" %>
|
||||
<h2>Personne physique</h2>
|
||||
|
||||
<label for="first_name">Prénom</label>
|
||||
<input
|
||||
id="first_name"
|
||||
name="first_name"
|
||||
type="text"
|
||||
maxlength="128"
|
||||
autocomplete="given-name"
|
||||
value="<%= request.params["first_name"] %>"
|
||||
required
|
||||
>
|
||||
|
||||
<% if error = rodauth.field_error("first_name") %>
|
||||
<p class="flash flash--error"><%= error %></p>
|
||||
<% end %>
|
||||
|
||||
<label for="last_name">Nom</label>
|
||||
<input
|
||||
id="last_name"
|
||||
name="last_name"
|
||||
type="text"
|
||||
maxlength="128"
|
||||
autocomplete="family-name"
|
||||
value="<%= request.params["last_name"] %>"
|
||||
required
|
||||
>
|
||||
|
||||
<% if error = rodauth.field_error("last_name") %>
|
||||
<p class="flash flash--error"><%= error %></p>
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
<h2>Personne morale</h2>
|
||||
|
||||
<label for="organization_name">Dénomination</label>
|
||||
<input
|
||||
id="organization_name"
|
||||
name="organization_name"
|
||||
type="text"
|
||||
maxlength="255"
|
||||
autocomplete="organization"
|
||||
value="<%= request.params["organization_name"] %>"
|
||||
required
|
||||
>
|
||||
|
||||
<% if error = rodauth.field_error("organization_name") %>
|
||||
<p class="flash flash--error"><%= error %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<label for="<%= rodauth.login_param %>">
|
||||
Adresse électronique
|
||||
</label>
|
||||
<input
|
||||
id="<%= rodauth.login_param %>"
|
||||
name="<%= rodauth.login_param %>"
|
||||
type="<%= rodauth.login_input_type %>"
|
||||
maxlength="254"
|
||||
autocomplete="email"
|
||||
value="<%= request.params[rodauth.login_param] %>"
|
||||
required
|
||||
>
|
||||
|
||||
<% if error = rodauth.field_error(rodauth.login_param) %>
|
||||
<p class="flash flash--error"><%= error %></p>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
Nous vous enverrons un courriel pour vérifier votre adresse
|
||||
électronique. Vous choisirez votre mot de passe à cette étape.
|
||||
</p>
|
||||
|
||||
<input
|
||||
type="submit"
|
||||
value="<%= rodauth.create_account_button %>"
|
||||
class="submit"
|
||||
>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
<a href="<%= rodauth.create_account_path %>">
|
||||
Changer de type de compte
|
||||
</a>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p>
|
||||
Vous avez déjà un compte ?
|
||||
<a href="<%= rodauth.login_path %>">Se connecter</a>.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
Reference in new issue
Block a user