Imrpove migrations
This commit is contained in:
1 parent
f386499d2f
commit
4f28a59c7e
7 files changed
+187
-88
No files matched your search
@@ -3,8 +3,11 @@
|
||||
## À faire
|
||||
|
||||
- limiter le spam sur `/contact/send`
|
||||
- développer les comptes utilisateurs et leur interface
|
||||
- afficher les recettes et dépenses sur la page d'accueil
|
||||
- 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
|
||||
- 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
|
||||
|
||||
## Développement
|
||||
|
||||
@@ -24,12 +27,22 @@ SMTP_PASSWORD=...
|
||||
Générer `SESSION_SECRET` avec `openssl rand -hex 64`.
|
||||
Ne pas versionner le fichier `.env`.
|
||||
|
||||
Appliquer les migrations :
|
||||
Créer ou mettre à jour la base de données :
|
||||
|
||||
```sh
|
||||
bundle exec ruby bin/migrate
|
||||
```
|
||||
|
||||
Lors de la première installation, créer le compte du premier administrateur :
|
||||
|
||||
```sh
|
||||
bundle exec ruby bin/initialize-admin
|
||||
```
|
||||
|
||||
Cette commande est à exécuter une seule fois. Elle crée un compte vérifié et
|
||||
lui attribue les droits techniques d'administration. Elle ne crée pas de
|
||||
demande d'adhésion.
|
||||
|
||||
Démarrer le serveur de développement :
|
||||
|
||||
```sh
|
||||
@@ -44,12 +57,19 @@ 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 :
|
||||
Exécuter les migrations dans le conteneur applicatif avant de démarrer la
|
||||
nouvelle version :
|
||||
|
||||
```sh
|
||||
bundle exec ruby bin/migrate
|
||||
```
|
||||
|
||||
Lors de la première installation, créer le premier administrateur depuis le
|
||||
conteneur applicatif :
|
||||
|
||||
```sh
|
||||
bundle exec ruby bin/initialize-admin
|
||||
```
|
||||
@@ -42,6 +42,12 @@ abort "Opération annulée." unless %w[o oui].include?(
|
||||
console.gets&.strip&.downcase
|
||||
)
|
||||
|
||||
verified_status_id = DB[:account_statuses]
|
||||
.where(name: "Verified")
|
||||
.get(:id)
|
||||
|
||||
abort "Statut Verified introuvable." unless verified_status_id
|
||||
|
||||
auth = Rodauth.lib do
|
||||
db DB
|
||||
enable :create_account
|
||||
@@ -57,6 +63,10 @@ DB.transaction do
|
||||
|
||||
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",
|
||||
|
||||
@@ -1,19 +1,68 @@
|
||||
Sequel.migration do
|
||||
up do
|
||||
create_table(:account_statuses) do
|
||||
Integer :id, primary_key: true
|
||||
String :name, null: false, unique: true
|
||||
end
|
||||
|
||||
from(:account_statuses).import(
|
||||
[:id, :name],
|
||||
[
|
||||
[1, "Unverified"],
|
||||
[2, "Verified"],
|
||||
[3, "Closed"]
|
||||
]
|
||||
)
|
||||
|
||||
db = self
|
||||
|
||||
create_table(:accounts) do
|
||||
primary_key :id, type: :Bignum
|
||||
|
||||
foreign_key :status_id, :account_statuses,
|
||||
null: false,
|
||||
default: 1
|
||||
|
||||
String :email, null: false
|
||||
|
||||
index :email, unique: true
|
||||
if db.supports_partial_indexes?
|
||||
index :email, unique: true, where: { status_id: [1, 2] }
|
||||
else
|
||||
index :email, unique: true
|
||||
end
|
||||
end
|
||||
|
||||
create_table(:account_password_hashes) do
|
||||
foreign_key :id, :accounts, primary_key: true, type: :Bignum
|
||||
foreign_key :id, :accounts,
|
||||
primary_key: true,
|
||||
type: :Bignum
|
||||
|
||||
String :password_hash, null: false
|
||||
end
|
||||
|
||||
create_table(:account_verification_keys) do
|
||||
foreign_key :id, :accounts,
|
||||
primary_key: true,
|
||||
type: :Bignum
|
||||
|
||||
String :key, null: false
|
||||
|
||||
DateTime :requested_at,
|
||||
null: false,
|
||||
default: Sequel::CURRENT_TIMESTAMP
|
||||
|
||||
DateTime :email_last_sent,
|
||||
null: false,
|
||||
default: Sequel::CURRENT_TIMESTAMP
|
||||
end
|
||||
end
|
||||
|
||||
down do
|
||||
drop_table(:account_password_hashes, :accounts)
|
||||
drop_table(
|
||||
:account_verification_keys,
|
||||
:account_password_hashes,
|
||||
:accounts,
|
||||
:account_statuses
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -12,6 +12,8 @@ Sequel.migration do
|
||||
String :last_name
|
||||
String :organization_name
|
||||
|
||||
TrueClass :admin, null: false, default: false
|
||||
|
||||
index :account_id, unique: true
|
||||
|
||||
constraint :members_kind_valid,
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
Sequel.migration do
|
||||
up do
|
||||
alter_table(:members) do
|
||||
add_column :admin, TrueClass, null: false, default: false
|
||||
end
|
||||
end
|
||||
|
||||
down do
|
||||
alter_table(:members) do
|
||||
drop_column :admin
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
Sequel.migration do
|
||||
up do
|
||||
create_table(:memberships) do
|
||||
primary_key :id, type: :Bignum
|
||||
|
||||
foreign_key :member_id, :members,
|
||||
type: :Bignum,
|
||||
null: false
|
||||
|
||||
String :status, null: false, default: "pending"
|
||||
|
||||
DateTime :requested_at,
|
||||
null: false,
|
||||
default: Sequel::CURRENT_TIMESTAMP
|
||||
|
||||
DateTime :decided_at
|
||||
|
||||
foreign_key :recorded_by, :members,
|
||||
type: :Bignum
|
||||
|
||||
DateTime :ended_at
|
||||
String :end_reason
|
||||
|
||||
index :status
|
||||
|
||||
# Un seul dossier en attente ou une seule adhésion
|
||||
# en cours par adhérent.
|
||||
index :member_id,
|
||||
unique: true,
|
||||
where: { status: ["pending", "accepted"], ended_at: nil }
|
||||
|
||||
constraint :memberships_status_valid,
|
||||
Sequel.lit("status IN ('pending', 'accepted', 'rejected')")
|
||||
|
||||
constraint :memberships_decision_consistent,
|
||||
Sequel.lit(
|
||||
"(status = 'pending' AND decided_at IS NULL " \
|
||||
"AND recorded_by IS NULL) " \
|
||||
"OR (status IN ('accepted', 'rejected') " \
|
||||
"AND decided_at IS NOT NULL AND recorded_by IS NOT NULL)"
|
||||
)
|
||||
|
||||
constraint :memberships_end_consistent,
|
||||
Sequel.lit(
|
||||
"(ended_at IS NULL AND end_reason IS NULL) " \
|
||||
"OR (status = 'accepted' AND ended_at IS NOT NULL " \
|
||||
"AND end_reason IN ('resignation', 'death', " \
|
||||
"'dissolution', 'exclusion'))"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
down do
|
||||
drop_table(:memberships)
|
||||
end
|
||||
end
|
||||
+40
-65
@@ -28,30 +28,26 @@ Ses principes sont :
|
||||
- le partage ouvert des savoirs et des compétences informatiques.
|
||||
|
||||
L'association est sans but lucratif. Ses services sont proposés sans
|
||||
facturation liée à leur utilisation. Ses ressources, notamment les
|
||||
cotisations des membres et les dons volontaires, servent à financer et
|
||||
pérenniser ses infrastructures. Aucun bénéfice n’est distribué aux membres.
|
||||
facturation liée à leur utilisation. Les dons volontaires contribuent au
|
||||
financement des infrastructures et à la pérennité des services. L’association
|
||||
invite les membres et les utilisateurs qui le peuvent à la soutenir
|
||||
financièrement, selon leurs moyens. Cette participation est importante pour
|
||||
assurer la continuité des services. Les dons sont libres, sans contrepartie
|
||||
et ne conditionnent ni l’adhésion, ni les droits des membres, ni l’accès aux
|
||||
services. Aucun bénéfice n’est distribué aux membres.
|
||||
|
||||
## Article 3 — Adhésion
|
||||
|
||||
Peut adhérer toute personne physique ou morale acceptant les statuts et
|
||||
les principes de l’association. Le Noyau examine les demandes.
|
||||
les principes de l’association. Le Noyau examine les demandes et décide
|
||||
de l’admission.
|
||||
|
||||
L’Assemblée générale (ci-après « AG ») fixe la cotisation annuelle. Après
|
||||
acceptation et paiement, l’adhésion dure un an et se renouvelle à chaque
|
||||
échéance si la cotisation est payée. Un paiement anticipé ou effectué
|
||||
pendant le délai de relance ne change pas l’échéance.
|
||||
L’adhésion prend effet à la date de son acceptation et est valable sans
|
||||
limitation de durée. Aucune cotisation ni aucun don n’est exigé pour adhérer,
|
||||
conserver la qualité de membre ou exercer les droits qui y sont attachés.
|
||||
|
||||
En cas d’impayé, une relance laisse trente jours pour payer. L’adhésion
|
||||
est maintenue pendant ce délai, mais le membre n’est plus à jour de sa
|
||||
cotisation : il ne peut pas voter en AG et ses accès aux services réservés
|
||||
aux membres à jour peuvent être suspendus par le Noyau ou le responsable
|
||||
du service. À défaut de paiement à l’expiration du délai, l’adhésion prend fin.
|
||||
|
||||
L’adhésion prend également fin par démission notifiée, décès, dissolution
|
||||
de la personne morale ou exclusion (article 7). La démission n’annule pas
|
||||
l'obligation de régler les cotisations en retard ni celle due pour l’année
|
||||
en cours.
|
||||
L’adhésion prend fin par démission notifiée, décès, dissolution de la
|
||||
personne morale ou exclusion (article 7).
|
||||
|
||||
## Article 4 — Assemblée générale
|
||||
|
||||
@@ -89,22 +85,21 @@ modifications statutaires et à la dissolution.
|
||||
|
||||
### Voix et procurations
|
||||
|
||||
Chaque membre à jour de sa cotisation, personne physique ou morale,
|
||||
dispose d’une voix. La voix d’une personne morale est exercée par son
|
||||
représentant habilité. Une personne physique également membre à titre
|
||||
personnel qui représente une ou plusieurs personnes morales membres
|
||||
exerce une voix en son nom et une voix pour chacune d’elles.
|
||||
Chaque membre, personne physique ou morale, dispose d’une voix délibérative.
|
||||
La voix d’une personne morale est exercée par son représentant habilité.
|
||||
Une personne physique également membre à titre personnel qui représente
|
||||
une ou plusieurs personnes morales membres exerce une voix en son nom et
|
||||
une voix pour chacune d’elles.
|
||||
|
||||
Tout membre à jour peut se faire représenter par un membre personne
|
||||
physique à jour. Une personne morale donne procuration par son
|
||||
représentant habilité. Une même personne peut détenir au plus deux
|
||||
procurations, en plus des voix qu’elle exerce en son nom ou comme
|
||||
représentant d’une ou plusieurs personnes morales.
|
||||
Tout membre peut se faire représenter par un membre personne physique.
|
||||
Une personne morale donne procuration par son représentant habilité.
|
||||
Une même personne peut détenir au plus deux procurations, en plus des voix
|
||||
qu’elle exerce en son nom ou comme représentant d’une ou plusieurs personnes
|
||||
morales.
|
||||
|
||||
Les voix délibératives sont celles des membres à jour de leur cotisation.
|
||||
Chaque voix délibérative compte séparément pour le calcul des seuils et
|
||||
des quorums prévus par les statuts ; les fractions sont arrondies à
|
||||
l’entier supérieur.
|
||||
Chaque voix délibérative compte séparément pour le calcul des seuils et des
|
||||
quorums prévus par les statuts ; les fractions sont arrondies à l’entier
|
||||
supérieur.
|
||||
|
||||
### Décisions
|
||||
|
||||
@@ -224,9 +219,9 @@ principes de l’article 2 ni modifier les statuts.
|
||||
|
||||
## Article 6 — Ressources et comptabilité
|
||||
|
||||
Les ressources comprennent les cotisations, dons, subventions, recettes
|
||||
d’activités compatibles avec l’objet et les principes de l’association
|
||||
et toute autre ressource autorisée par la loi.
|
||||
Les ressources comprennent les dons volontaires, les subventions, les
|
||||
recettes d’activités compatibles avec l’objet et les principes de
|
||||
l’association et toute autre ressource autorisée par la loi.
|
||||
|
||||
Les fonctions sont bénévoles. Les frais engagés pour l’association peuvent
|
||||
être remboursés sur justificatifs, selon les modalités du Noyau. Nul ne
|
||||
@@ -318,14 +313,14 @@ substantielle impose une nouvelle AG et fait repartir le délai de
|
||||
trente jours.
|
||||
|
||||
La première AG ne délibère que si deux tiers au moins des voix
|
||||
délibératives des membres à jour sont présentes ou représentées. À
|
||||
défaut de quorum, une seconde AG est convoquée par le Noyau ou, si la
|
||||
première AG a été convoquée par des membres, par ces mêmes membres.
|
||||
Sa convocation est envoyée dans les quinze jours suivant le constat
|
||||
de l’absence de quorum. Elle se tient au moins quinze jours après
|
||||
l’envoi de sa convocation. Elle reprend le même ordre du jour et le même
|
||||
projet, et ne délibère valablement que si un tiers au moins des voix
|
||||
délibératives des membres à jour est présent ou représenté.
|
||||
délibératives sont présentes ou représentées. À défaut de quorum, une
|
||||
seconde AG est convoquée par le Noyau ou, si la première AG a été
|
||||
convoquée par des membres, par ces mêmes membres. Sa convocation est
|
||||
envoyée dans les quinze jours suivant le constat de l’absence de quorum.
|
||||
Elle se tient au moins quinze jours après l’envoi de sa convocation.
|
||||
Elle reprend le même ordre du jour et le même projet, et ne délibère
|
||||
valablement que si un tiers au moins des voix délibératives est présent
|
||||
ou représenté.
|
||||
|
||||
Si le quorum de la seconde AG n’est pas atteint, le projet n’est pas
|
||||
adopté. Il peut être soumis à une nouvelle procédure dans les conditions
|
||||
@@ -334,31 +329,11 @@ du présent article.
|
||||
La modification ou la dissolution est adoptée à la majorité des deux
|
||||
tiers des suffrages exprimés. Toutefois, toute modification statutaire
|
||||
ayant pour effet d’augmenter les engagements des membres requiert
|
||||
l’accord unanime de tous les membres, y compris ceux qui ne sont pas
|
||||
à jour de leur cotisation. Cet accord peut être recueilli par écrit
|
||||
en dehors de l’AG.
|
||||
l’accord unanime de tous les membres. Cet accord peut être recueilli
|
||||
par écrit en dehors de l’AG.
|
||||
|
||||
En cas de dissolution, l’AG désigne un ou plusieurs liquidateurs et
|
||||
attribue l’actif net, après règlement des dettes, à un organisme à but
|
||||
non lucratif poursuivant un objet compatible avec celui de NETig.
|
||||
Aucun actif n’est distribué aux membres.
|
||||
|
||||
---
|
||||
|
||||
**Statuts adoptés par l’Assemblée générale constitutive.**
|
||||
|
||||
Fait à __________________________, le ____ / ____ / ______
|
||||
|
||||
**Signatures**
|
||||
|
||||
Nom : __________________________________________
|
||||
|
||||
Signature : _____________________________________
|
||||
|
||||
Nom : __________________________________________
|
||||
|
||||
Signature : _____________________________________
|
||||
|
||||
Nom : __________________________________________
|
||||
|
||||
Signature : _____________________________________
|
||||
Reference in new issue
Block a user