Remove admin account
This commit is contained in:
1 parent
4f28a59c7e
commit
db316b2914
13 files changed
+372
-144
No files matched your search
@@ -33,15 +33,24 @@ Créer ou mettre à jour la base de données :
|
|||||||
bundle exec ruby bin/migrate
|
bundle exec ruby bin/migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
Lors de la première installation, créer le compte du premier administrateur :
|
Créer un ou plusieurs comptes de test :
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bundle exec ruby bin/initialize-admin
|
bundle exec ruby bin/initialize-account
|
||||||
```
|
```
|
||||||
|
|
||||||
Cette commande est à exécuter une seule fois. Elle crée un compte vérifié et
|
Cette commande crée un compte vérifié et sa fiche de membre.
|
||||||
lui attribue les droits techniques d'administration. Elle ne crée pas de
|
Elle peut être exécutée plusieurs fois. Les comptes créés ne possèdent
|
||||||
demande d'adhésion.
|
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 :
|
Démarrer le serveur de développement :
|
||||||
|
|
||||||
@@ -60,16 +69,28 @@ bundle exec irb -r dotenv/load -r ./netig.rb
|
|||||||
Docker Compose fournit les variables d'environnement via `env_file` et définit
|
Docker Compose fournit les variables d'environnement via `env_file` et définit
|
||||||
`RACK_ENV=production`.
|
`RACK_ENV=production`.
|
||||||
|
|
||||||
Exécuter les migrations dans le conteneur applicatif avant de démarrer la
|
Exécuter les migrations dans le conteneur applicatif avant de démarrer
|
||||||
nouvelle version :
|
la nouvelle version :
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bundle exec ruby bin/migrate
|
bundle exec ruby bin/migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
Lors de la première installation, créer le premier administrateur depuis le
|
### Initialisation du premier Noyau
|
||||||
conteneur applicatif :
|
|
||||||
|
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 :
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
bundle exec ruby bin/initialize-admin
|
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.
|
||||||
|
|
||||||
|
La date de l'assemblée constitutive est demandée lors de l'exécution.
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
require "dotenv/load" if ENV.fetch("RACK_ENV", "development") == "development"
|
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 "io/console"
|
||||||
require "rodauth"
|
require "rodauth"
|
||||||
|
|
||||||
@@ -8,16 +13,17 @@ require_relative "../lib/database"
|
|||||||
|
|
||||||
console = IO.console or abort "Terminal interactif requis."
|
console = IO.console or abort "Terminal interactif requis."
|
||||||
|
|
||||||
abort "Un administrateur existe déjà." if
|
|
||||||
DB[:members].where(admin: true).count.positive?
|
|
||||||
|
|
||||||
console.print "Adresse électronique : "
|
console.print "Adresse électronique : "
|
||||||
email = console.gets&.strip
|
email = console.gets&.strip&.downcase
|
||||||
|
|
||||||
abort "Adresse électronique obligatoire." if email.to_s.empty?
|
abort "Adresse électronique obligatoire." if email.to_s.empty?
|
||||||
|
|
||||||
abort "Ce compte existe déjà." if
|
existing_account = DB[:accounts]
|
||||||
DB[:accounts].where(email: email).count.positive?
|
.where(Sequel.function(:lower, :email) => email)
|
||||||
|
.count
|
||||||
|
.positive?
|
||||||
|
|
||||||
|
abort "Ce compte existe déjà." if existing_account
|
||||||
|
|
||||||
console.print "Prénom : "
|
console.print "Prénom : "
|
||||||
first_name = console.gets&.strip
|
first_name = console.gets&.strip
|
||||||
@@ -31,16 +37,9 @@ abort "Prénom et nom obligatoires." if
|
|||||||
password = console.getpass("Mot de passe : ")
|
password = console.getpass("Mot de passe : ")
|
||||||
confirmation = console.getpass("Confirmer le mot de passe : ")
|
confirmation = console.getpass("Confirmer le mot de passe : ")
|
||||||
|
|
||||||
abort "Mot de passe obligatoire." if password.empty?
|
abort "Mot de passe obligatoire." if password.to_s.empty?
|
||||||
abort "Les mots de passe ne correspondent pas." unless password == confirmation
|
abort "Les mots de passe ne correspondent pas." unless
|
||||||
|
password == confirmation
|
||||||
console.puts
|
|
||||||
console.puts "Administrateur : #{first_name} #{last_name} (#{email})"
|
|
||||||
console.print "Confirmer la création ? [o/N] "
|
|
||||||
|
|
||||||
abort "Opération annulée." unless %w[o oui].include?(
|
|
||||||
console.gets&.strip&.downcase
|
|
||||||
)
|
|
||||||
|
|
||||||
verified_status_id = DB[:account_statuses]
|
verified_status_id = DB[:account_statuses]
|
||||||
.where(name: "Verified")
|
.where(name: "Verified")
|
||||||
@@ -48,6 +47,15 @@ verified_status_id = DB[:account_statuses]
|
|||||||
|
|
||||||
abort "Statut Verified introuvable." unless verified_status_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
|
auth = Rodauth.lib do
|
||||||
db DB
|
db DB
|
||||||
enable :create_account
|
enable :create_account
|
||||||
@@ -73,8 +81,9 @@ DB.transaction do
|
|||||||
first_name: first_name,
|
first_name: first_name,
|
||||||
last_name: last_name,
|
last_name: last_name,
|
||||||
organization_name: nil,
|
organization_name: nil,
|
||||||
admin: true
|
core_member: false
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "Premier administrateur créé."
|
puts "Compte de développement créé."
|
||||||
|
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
environment = ENV.fetch("RACK_ENV", "development")
|
||||||
|
require "dotenv/load" if environment == "development"
|
||||||
|
|
||||||
|
abort "Environnement non pris en charge." unless
|
||||||
|
%w[development production].include?(
|
||||||
|
ENV.fetch("RACK_ENV", "development")
|
||||||
|
)
|
||||||
|
|
||||||
|
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.print "Adresse de la personne qui enregistre la décision : "
|
||||||
|
recorded_by_email = console.gets&.strip&.downcase
|
||||||
|
|
||||||
|
abort "Adresse électronique obligatoire." if
|
||||||
|
recorded_by_email.to_s.empty?
|
||||||
|
|
||||||
|
recorded_by = find_member.call(recorded_by_email)
|
||||||
|
|
||||||
|
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.puts "Décision enregistrée par : #{recorded_by_email}"
|
||||||
|
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],
|
||||||
|
ended_at: nil
|
||||||
|
)
|
||||||
|
.first
|
||||||
|
|
||||||
|
if membership && membership[:status] == "pending"
|
||||||
|
DB[:memberships]
|
||||||
|
.where(id: membership[:id])
|
||||||
|
.update(
|
||||||
|
status: "accepted",
|
||||||
|
decided_at: assembly_datetime,
|
||||||
|
recorded_by: recorded_by[:id]
|
||||||
|
)
|
||||||
|
elsif membership.nil?
|
||||||
|
DB[:memberships].insert(
|
||||||
|
member_id: member[:id],
|
||||||
|
status: "accepted",
|
||||||
|
requested_at: assembly_datetime,
|
||||||
|
decided_at: assembly_datetime,
|
||||||
|
recorded_by: recorded_by[:id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
DB[:members]
|
||||||
|
.where(id: member[:id])
|
||||||
|
.update(core_member: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Noyau initialisé (#{members.length} membres)."
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ Sequel.migration do
|
|||||||
String :last_name
|
String :last_name
|
||||||
String :organization_name
|
String :organization_name
|
||||||
|
|
||||||
TrueClass :admin, null: false, default: false
|
TrueClass :core_member, null: false, default: false
|
||||||
|
|
||||||
index :account_id, unique: true
|
index :account_id, unique: true
|
||||||
|
|
||||||
@@ -28,6 +28,9 @@ Sequel.migration do
|
|||||||
"AND last_name IS NULL AND organization_name IS NOT NULL " \
|
"AND last_name IS NULL AND organization_name IS NOT NULL " \
|
||||||
"AND trim(organization_name) <> '')"
|
"AND trim(organization_name) <> '')"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
constraint :members_core_member_individual,
|
||||||
|
Sequel.lit("core_member = FALSE OR kind = 'individual'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+67
-50
@@ -1,9 +1,9 @@
|
|||||||
# Informations légales et conditions d’utilisation
|
# Informations légales et conditions d’utilisation
|
||||||
|
|
||||||
NETig est un projet associatif régi par la loi du 1er juillet 1901.
|
NETig est un projet associatif régi par la loi du 1er juillet 1901.
|
||||||
L’association n’a pas encore été déclarée en préfecture et ne dispose donc
|
L’association n’a pas encore été déclarée en préfecture et ne dispose
|
||||||
pas encore de la personnalité morale ni de la capacité juridique attachée
|
donc pas encore de la personnalité morale ni de la capacité juridique
|
||||||
à une association déclarée. Cette information sera mise à jour après la
|
attachée à une association déclarée. Cette information sera mise à jour après la
|
||||||
déclaration et sa publication au Journal officiel des associations et
|
déclaration et sa publication au Journal officiel des associations et
|
||||||
fondations d’entreprises (JOAFE).
|
fondations d’entreprises (JOAFE).
|
||||||
|
|
||||||
@@ -30,30 +30,29 @@ Finlande.
|
|||||||
|
|
||||||
Les services NETig sont proposés sans facturation liée à leur utilisation.
|
Les services NETig sont proposés sans facturation liée à leur utilisation.
|
||||||
Certains sont accessibles au public ; d’autres sont réservés aux membres
|
Certains sont accessibles au public ; d’autres sont réservés aux membres
|
||||||
à jour de leur cotisation.
|
de l’association.
|
||||||
|
|
||||||
Conformément aux statuts, toute demande d’adhésion est examinée par le Noyau.
|
Toute personne physique ou morale peut demander à adhérer à l’association,
|
||||||
L’adhésion prend effet après acceptation de la demande et paiement de la
|
à condition d’accepter ses statuts et ses principes. Le Noyau examine les
|
||||||
cotisation annuelle fixée par l’Assemblée générale. Elle dure un an et se
|
demandes et décide de l’admission. L’adhésion prend effet à la date de
|
||||||
renouvelle à chaque échéance si la cotisation est payée. La création d’un
|
son acceptation et est valable sans limitation de durée. La création d’un compte
|
||||||
compte utilisateur, lorsqu’elle sera proposée, ne vaudra pas à elle seule
|
utilisateur ne vaut pas, à elle seule, adhésion à l’association.
|
||||||
adhésion à l’association.
|
|
||||||
|
|
||||||
En cas d’impayé, une relance laisse trente jours pour régler la cotisation.
|
Aucune cotisation ni aucun don n’est exigé pour adhérer, conserver la
|
||||||
Pendant ce délai, le membre n’est plus considéré comme à jour : il ne peut
|
qualité de membre ou exercer les droits qui y sont attachés. Les dons sont
|
||||||
pas voter en Assemblée générale et ses accès aux services réservés aux
|
libres, volontaires et sans contrepartie. NETig invite les membres et les
|
||||||
membres à jour peuvent être suspendus. À défaut de paiement à l’expiration
|
utilisateurs qui le peuvent à soutenir financièrement l’association, selon
|
||||||
de ce délai, l’adhésion prend fin.
|
leurs moyens. Cette participation contribue au financement des
|
||||||
|
infrastructures et à la pérennité des services, mais ne conditionne ni
|
||||||
Les dons sont libres et volontaires. Ils contribuent au financement des
|
l’adhésion, ni les droits des membres, ni l’accès aux services et ne donne
|
||||||
infrastructures, ne remplacent pas la cotisation nécessaire à l’adhésion
|
droit à aucun avantage particulier.
|
||||||
et ne donnent droit à aucun accès ou avantage particulier.
|
|
||||||
|
|
||||||
L’accès à chaque service dépend des ressources disponibles et peut être
|
L’accès à chaque service dépend des ressources disponibles et peut être
|
||||||
limité. Une disponibilité permanente n’est pas garantie. L’état des services
|
limité. Une disponibilité permanente n’est pas garantie. L’état des services
|
||||||
est consultable sur la [page de statut](https://status.netig.net/status/services).
|
est consultable sur la page de statut :
|
||||||
Les interruptions de maintenance peuvent être annoncées par la
|
[page de statut](https://status.netig.net/status/services). Les interruptions
|
||||||
[liste de diffusion dédiée](https://list.netig.net/subscription/form).
|
de maintenance peuvent être annoncées par la liste de diffusion dédiée :
|
||||||
|
[liste de diffusion](https://list.netig.net/subscription/form).
|
||||||
|
|
||||||
### Utilisation des services
|
### Utilisation des services
|
||||||
|
|
||||||
@@ -71,11 +70,12 @@ propres copies lorsque cela est possible.
|
|||||||
|
|
||||||
La personne responsable d’un service peut limiter ou suspendre un accès
|
La personne responsable d’un service peut limiter ou suspendre un accès
|
||||||
de manière proportionnée en cas d’abus ou de risque pour la sécurité,
|
de manière proportionnée en cas d’abus ou de risque pour la sécurité,
|
||||||
les données, le fonctionnement ou les ressources du service. Elle informe
|
les données, le fonctionnement ou les ressources du service. Elle en
|
||||||
la personne concernée et le Noyau des motifs de la mesure.
|
informe la personne concernée ainsi que le Noyau, en indiquant les motifs
|
||||||
|
de la mesure.
|
||||||
|
|
||||||
La personne concernée peut demander au Noyau de réexaminer cette mesure.
|
La personne concernée peut demander au Noyau de réexaminer cette mesure.
|
||||||
Le Noyau répond sous quinze jours. Si le Noyau a pris ou confirmé la mesure,
|
Celui-ci répond sous quinze jours. Si le Noyau a pris ou confirmé la mesure,
|
||||||
la personne concernée ou tout membre peut demander son réexamen par
|
la personne concernée ou tout membre peut demander son réexamen par
|
||||||
l’Assemblée générale. La suspension d’un accès ne met pas fin à la qualité
|
l’Assemblée générale. La suspension d’un accès ne met pas fin à la qualité
|
||||||
de membre.
|
de membre.
|
||||||
@@ -101,13 +101,16 @@ la personne ou de la structure qui détermine actuellement les finalités
|
|||||||
et les moyens des traitements].
|
et les moyens des traitements].
|
||||||
|
|
||||||
La présente notice décrit les traitements réalisés sur le site netig.net,
|
La présente notice décrit les traitements réalisés sur le site netig.net,
|
||||||
notamment par son formulaire de contact. Les services hébergés sur d’autres
|
notamment par son formulaire de contact et par les fonctions
|
||||||
adresses peuvent mettre en œuvre des traitements propres ; leurs modalités
|
d’authentification réservées aux comptes créés par l’administration. Les
|
||||||
spécifiques doivent être présentées dans les services concernés.
|
services hébergés sur d’autres adresses peuvent mettre en œuvre des
|
||||||
|
traitements propres ; leurs modalités spécifiques doivent être présentées
|
||||||
|
dans les services concernés.
|
||||||
|
|
||||||
À la date de cette notice, le site netig.net ne propose pas encore de
|
À la date de cette notice, le site netig.net ne propose pas encore
|
||||||
création de compte utilisateur ni d’adhésion en ligne. Les informations
|
d’inscription publique ni de demande d’adhésion en ligne. Ces fonctionnalités
|
||||||
relatives à ces fonctions seront ajoutées avant leur mise en service.
|
et les traitements associés feront l’objet d’une mise à jour de la notice
|
||||||
|
avant leur mise en service.
|
||||||
|
|
||||||
### Données traitées et finalités
|
### Données traitées et finalités
|
||||||
|
|
||||||
@@ -115,10 +118,18 @@ Le formulaire de contact recueille le nom, l’adresse électronique, l’objet
|
|||||||
et le contenu du message. Ces informations sont utilisées pour répondre
|
et le contenu du message. Ces informations sont utilisées pour répondre
|
||||||
aux demandes et assurer le suivi des échanges.
|
aux demandes et assurer le suivi des échanges.
|
||||||
|
|
||||||
|
Pour les comptes déjà créés, l’adresse électronique sert d’identifiant.
|
||||||
|
Une empreinte du mot de passe est conservée pour permettre
|
||||||
|
l’authentification ; le mot de passe n’est pas enregistré en clair. Les
|
||||||
|
informations d’identité associées au compte, lorsqu’elles sont renseignées,
|
||||||
|
peuvent comprendre le type de membre, le prénom, le nom ou la dénomination
|
||||||
|
de la personne morale. Ces données sont utilisées pour gérer les comptes
|
||||||
|
et l’administration du site.
|
||||||
|
|
||||||
Des données techniques nécessaires au fonctionnement et à la sécurité du
|
Des données techniques nécessaires au fonctionnement et à la sécurité du
|
||||||
site peuvent également être traitées, notamment dans les journaux du
|
site peuvent également être traitées, notamment les données de session et
|
||||||
serveur. Leur nature et leur durée de conservation doivent être adaptées
|
les journaux du serveur. Leur nature et leur durée de conservation doivent
|
||||||
à leur utilité réelle.
|
être adaptées à leur utilité réelle.
|
||||||
|
|
||||||
Les données ne sont ni vendues ni utilisées à des fins publicitaires.
|
Les données ne sont ni vendues ni utilisées à des fins publicitaires.
|
||||||
|
|
||||||
@@ -126,16 +137,19 @@ Les données ne sont ni vendues ni utilisées à des fins publicitaires.
|
|||||||
|
|
||||||
Les messages sont traités dans le cadre de l’intérêt légitime à répondre
|
Les messages sont traités dans le cadre de l’intérêt légitime à répondre
|
||||||
aux sollicitations adressées au projet NETig et à assurer le suivi des
|
aux sollicitations adressées au projet NETig et à assurer le suivi des
|
||||||
échanges. Les données techniques nécessaires à la sécurité sont traitées
|
échanges. Les données nécessaires à l’authentification et à la gestion
|
||||||
dans l’intérêt légitime de protéger le site, les services et leurs
|
des comptes sont traitées dans l’intérêt légitime de sécuriser
|
||||||
utilisateurs.
|
l’administration du site. Les données techniques nécessaires à la sécurité
|
||||||
|
sont traitées dans l’intérêt légitime de protéger le site, les services
|
||||||
|
et leurs utilisateurs.
|
||||||
|
|
||||||
### Destinataires et hébergement
|
### Destinataires et hébergement
|
||||||
|
|
||||||
Les messages sont transmis à l’adresse [contact@netig.net](mailto:contact@netig.net)
|
Les messages sont transmis à l’adresse
|
||||||
et peuvent être consultés par les personnes habilitées à répondre aux
|
[contact@netig.net](mailto:contact@netig.net) et peuvent être consultés par
|
||||||
demandes. Les données techniques peuvent être accessibles aux personnes
|
les personnes habilitées à répondre aux demandes. Les données des comptes
|
||||||
chargées de l’administration des infrastructures et aux prestataires
|
et les données techniques peuvent être accessibles aux personnes habilitées
|
||||||
|
à administrer le site et les infrastructures, ainsi qu’aux prestataires
|
||||||
techniques concernés.
|
techniques concernés.
|
||||||
|
|
||||||
L’hébergement principal est assuré par Hetzner Online GmbH. Des sauvegardes
|
L’hébergement principal est assuré par Hetzner Online GmbH. Des sauvegardes
|
||||||
@@ -147,12 +161,15 @@ Les messages reçus sont conservés dans la messagerie le temps nécessaire
|
|||||||
au traitement de la demande et au suivi des échanges, puis supprimés,
|
au traitement de la demande et au suivi des échanges, puis supprimés,
|
||||||
sauf nécessité de conservation plus longue ou obligation légale.
|
sauf nécessité de conservation plus longue ou obligation légale.
|
||||||
|
|
||||||
Les journaux techniques et les sauvegardes peuvent conserver certaines
|
Les données des comptes sont conservées pendant la durée nécessaire à leur
|
||||||
données après leur suppression des systèmes actifs. Les durées de
|
gestion et à la sécurisation du site. Les journaux techniques et les
|
||||||
conservation effectivement appliquées doivent être précisées avant
|
sauvegardes peuvent conserver certaines données après leur suppression des
|
||||||
l’ouverture des services concernés :
|
systèmes actifs. Les durées de conservation effectivement appliquées doivent
|
||||||
|
être précisées avant l’ouverture des services concernés :
|
||||||
|
|
||||||
- **Messages de contact :** [durée à définir].
|
- **Messages de contact :** [durée à définir].
|
||||||
|
- **Comptes et fiches associées :** [durée à définir].
|
||||||
|
- **Données de session :** [durée à définir].
|
||||||
- **Journaux techniques :** [durée à définir].
|
- **Journaux techniques :** [durée à définir].
|
||||||
- **Sauvegardes :** [durée de rétention à définir].
|
- **Sauvegardes :** [durée de rétention à définir].
|
||||||
|
|
||||||
@@ -163,15 +180,15 @@ l’accès à vos données, leur rectification ou leur effacement, la limitation
|
|||||||
de leur traitement et vous opposer à certains traitements. Vous pouvez
|
de leur traitement et vous opposer à certains traitements. Vous pouvez
|
||||||
également demander la portabilité lorsque ce droit s’applique.
|
également demander la portabilité lorsque ce droit s’applique.
|
||||||
|
|
||||||
Pour exercer vos droits, écrivez à [contact@netig.net](mailto:contact@netig.net).
|
Pour exercer vos droits, écrivez à
|
||||||
Vous pouvez également introduire une réclamation auprès de la
|
[contact@netig.net](mailto:contact@netig.net). Vous pouvez également
|
||||||
[CNIL](https://www.cnil.fr/).
|
introduire une réclamation auprès de la [CNIL](https://www.cnil.fr/).
|
||||||
|
|
||||||
### Cookies
|
### Cookies
|
||||||
|
|
||||||
Le site utilise des cookies techniques nécessaires au fonctionnement
|
Le site utilise des cookies techniques nécessaires au fonctionnement
|
||||||
des sessions et à la sécurité. Ils ne sont pas utilisés à des fins de
|
des sessions et à la sécurité, notamment pour l’authentification. Ils ne
|
||||||
publicité ou de suivi de navigation.
|
sont pas utilisés à des fins de publicité ou de suivi de navigation.
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
class Netig
|
||||||
|
private
|
||||||
|
|
||||||
|
def require_core_member!(r)
|
||||||
|
rodauth.require_account
|
||||||
|
|
||||||
|
core_member = DB[:members]
|
||||||
|
.join(:memberships, member_id: :id)
|
||||||
|
.where(
|
||||||
|
Sequel[:members][:account_id] => rodauth.account_id,
|
||||||
|
Sequel[:members][:kind] => "individual",
|
||||||
|
Sequel[:members][:core_member] => true,
|
||||||
|
Sequel[:memberships][:status] => "accepted",
|
||||||
|
Sequel[:memberships][:ended_at] => nil
|
||||||
|
)
|
||||||
|
.count
|
||||||
|
.positive?
|
||||||
|
|
||||||
|
return if core_member
|
||||||
|
|
||||||
|
r.halt [
|
||||||
|
403,
|
||||||
|
{ "Content-Type" => "text/plain; charset=utf-8" },
|
||||||
|
["Accès interdit."]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -35,7 +35,8 @@ class Netig < Roda
|
|||||||
logout_redirect "/"
|
logout_redirect "/"
|
||||||
end
|
end
|
||||||
|
|
||||||
require_relative "routes/admin"
|
require_relative "lib/authorization"
|
||||||
|
require_relative "routes/noyau"
|
||||||
require_relative "routes/contact"
|
require_relative "routes/contact"
|
||||||
|
|
||||||
route do |r|
|
route do |r|
|
||||||
|
|||||||
@@ -490,23 +490,23 @@ summary:focus-visible {
|
|||||||
/* Admin
|
/* Admin
|
||||||
------------------------------------------------------------------------ */
|
------------------------------------------------------------------------ */
|
||||||
|
|
||||||
.admin-table {
|
.members-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-table th,
|
.members-table th,
|
||||||
.admin-table td {
|
.members-table td {
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
border-bottom: 1px solid var(--color-shadow-light);
|
border-bottom: 1px solid var(--color-shadow-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-table th {
|
.members-table th {
|
||||||
color: var(--color-highlight);
|
color: var(--color-highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-table td {
|
.members-table td {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
class Netig
|
|
||||||
hash_branch "admin" do |r|
|
|
||||||
require_admin!(r)
|
|
||||||
|
|
||||||
@page_title = "Admin — NETig"
|
|
||||||
@page_description = "Interface d'administration de NETig."
|
|
||||||
@canonical_url = "https://netig.net/admin"
|
|
||||||
|
|
||||||
r.is do
|
|
||||||
r.get do
|
|
||||||
view "admin"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
r.on "members" do
|
|
||||||
r.is do
|
|
||||||
r.get do
|
|
||||||
@page_title = "Adhérents — Admin — NETig"
|
|
||||||
|
|
||||||
@members = DB[:members]
|
|
||||||
.join(:accounts, id: :account_id)
|
|
||||||
.select_all(:members)
|
|
||||||
.select_append(Sequel[:accounts][:email].as(:email))
|
|
||||||
.order(Sequel[:members][:id])
|
|
||||||
.all
|
|
||||||
|
|
||||||
view "admin/members"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def require_admin!(r)
|
|
||||||
rodauth.require_account
|
|
||||||
|
|
||||||
admin = DB[:members].where(
|
|
||||||
account_id: rodauth.account_id,
|
|
||||||
admin: true
|
|
||||||
).get(:admin)
|
|
||||||
|
|
||||||
return if admin
|
|
||||||
|
|
||||||
r.halt [
|
|
||||||
403,
|
|
||||||
{ "Content-Type" => "text/plain; charset=utf-8" },
|
|
||||||
["Accès interdit."]
|
|
||||||
]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
class Netig
|
||||||
|
hash_branch "noyau" do |r|
|
||||||
|
require_core_member!(r)
|
||||||
|
|
||||||
|
@page_title = "Noyau — NETig"
|
||||||
|
@page_description = "Espace de gestion de l'association NETig."
|
||||||
|
@canonical_url = "https://netig.net/noyau"
|
||||||
|
|
||||||
|
r.is do
|
||||||
|
r.get do
|
||||||
|
view "noyau"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
r.on "members" do
|
||||||
|
r.is do
|
||||||
|
r.get do
|
||||||
|
@page_title = "Adhérents — Noyau — NETig"
|
||||||
|
|
||||||
|
@members = DB[:members]
|
||||||
|
.join(:accounts, id: :account_id)
|
||||||
|
.select_all(:members)
|
||||||
|
.select_append(Sequel[:accounts][:email].as(:email))
|
||||||
|
.order(Sequel[:members][:id])
|
||||||
|
.all
|
||||||
|
|
||||||
|
view "noyau/members"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
+1
-2
@@ -113,8 +113,7 @@
|
|||||||
<section id="association" class="section-association">
|
<section id="association" class="section-association">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h2>Aidez-nous à continuer !</h2>
|
<h2>Aidez-nous à continuer !</h2>
|
||||||
<p>Les services sont financés grâce à vos adhésions et vos dons. Votre soutien nous aide à couvrir les frais d'hébergement et à maintenir les services accessibles.</p>
|
<p>Les services ne sont financés que par vos dons. Votre soutien nous aide à couvrir les frais d'hébergement et à maintenir les services accessibles.</p>
|
||||||
<a class="button" href="/temporary_page">Adhérer ➜</a>
|
|
||||||
<a class="button" href="/temporary_page">Faire un don ➜</a>
|
<a class="button" href="/temporary_page">Faire un don ➜</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<section class="page-section">
|
<section class="page-section">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h1>Administration de NETig</h1>
|
<h1>Espace du Noyau</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a class="button" href="/admin/members">
|
<a class="button" href="/noyau/members">
|
||||||
Gérer les adhérents
|
Gérer les adhérents
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@@ -5,13 +5,12 @@
|
|||||||
<% if @members.empty? %>
|
<% if @members.empty? %>
|
||||||
<p>Aucun adhérent enregistré.</p>
|
<p>Aucun adhérent enregistré.</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<table class="admin-table">
|
<table class="members-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Identité</th>
|
<th>Identité</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Adresse électronique</th>
|
<th>Adresse électronique</th>
|
||||||
<th>Administration</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
@@ -28,7 +27,6 @@
|
|||||||
"Personne physique" : "Personne morale" %>
|
"Personne physique" : "Personne morale" %>
|
||||||
</td>
|
</td>
|
||||||
<td><%= member[:email] %></td>
|
<td><%= member[:email] %></td>
|
||||||
<td><%= member[:admin] ? "Oui" : "Non" %></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -36,3 +34,4 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
Reference in new issue
Block a user