diff --git a/README.md b/README.md
index 12e332d..f992a57 100644
--- a/README.md
+++ b/README.md
@@ -3,175 +3,234 @@
Application web de saisie et de recherche de relevés généalogiques pour associations.
Permet la saisie collaborative de relevés d'actes (naissance, mariage, décès, etc.), la recherche plein texte et l'export au format GEDCOM 5.5.1.
+---
+
+## Installation sur hébergement mutualisé (recommandé)
+
+### Prérequis serveur
+
+| Composant | Version minimale |
+|---|---|
+| PHP | 8.2 avec extensions : `pdo_mysql`, `mbstring`, `openssl`, `tokenizer`, `xml`, `ctype`, `fileinfo`, `bcmath`, `curl` |
+| MySQL / MariaDB | MySQL 8.0+ ou MariaDB 10.5+ |
+| Serveur web | Apache (mod_rewrite activé) ou Nginx |
+| Accès fichier | Écriture sur `storage/` et `bootstrap/cache/` |
+
+> **PostgreSQL** est également supporté et recommandé pour les grandes bases de relevés (full-text search natif, JSONB). Voir la section [Docker](#docker) pour une installation avec PostgreSQL.
+
+---
+
+### Étape 1 — Télécharger et décompresser l'archive
+
+Récupérez la dernière archive depuis la page des [releases](https://git.barbel.synology.me/CGL/mesreleves-php/releases) :
+
+```
+mesreleves-X.Y.Z.tar.gz
+```
+
+Décompressez-la dans le dossier de votre hébergement (via FTP ou le gestionnaire de fichiers du panneau de contrôle) :
+
+```bash
+tar -xzf mesreleves-X.Y.Z.tar.gz
+```
+
+Cela crée un dossier `mesreleves/` contenant toute l'application.
+
+---
+
+### Étape 2 — Faire pointer le site vers `public/`
+
+Le point d'entrée de l'application est le dossier `public/`.
+**Le dossier racine de votre site (document root) doit pointer sur `public/`, pas sur la racine de l'archive.**
+
+**Exemples de configurations :**
+
+
+Apache — .htaccess (déjà inclus dans public/)
+
+Rien à faire : le `.htaccess` livré avec l'application configure automatiquement la réécriture d'URL. Vérifiez que `mod_rewrite` est activé sur votre hébergement.
+
+Si vous ne pouvez pas modifier le document root, vous pouvez déposer les fichiers directement dans le dossier `public_html/` de votre hébergement en copiant le contenu de `public/` à sa racine et en adaptant le chemin dans `index.php` :
+
+```php
+// public/index.php — adapter le chemin si l'arborescence est modifiée
+require __DIR__.'/../mesreleves/vendor/autoload.php';
+$app = require_once __DIR__.'/../mesreleves/bootstrap/app.php';
+```
+
+
+
+
+Nginx
+
+```nginx
+server {
+ listen 80;
+ server_name votre-domaine.fr;
+ root /var/www/mesreleves/public;
+
+ index index.php;
+
+ location / {
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+
+ location ~ \.php$ {
+ fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
+ fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
+ include fastcgi_params;
+ }
+}
+```
+
+
+
+---
+
+### Étape 3 — Lancer l'assistant d'installation
+
+Ouvrez votre navigateur sur `https://votre-domaine.fr/setup`.
+
+L'assistant vous guide à travers **5 étapes** :
+
+1. **Prérequis** — vérification automatique des extensions PHP et des droits d'écriture
+2. **Base de données** — saisie des paramètres MySQL/PostgreSQL ; un bouton « Tester la connexion » valide la configuration avant de continuer
+3. **Application** — nom du site, URL de base, activation des inscriptions publiques
+4. **Compte administrateur** — création du premier compte admin
+5. **Installation** — migrations, génération de la clé d'application, résumé
+
+> L'assistant crée automatiquement le fichier `.env` et exécute toutes les migrations.
+> Une fois terminé, la page `/setup` est désactivée.
+
+---
+
+### Étape 4 — Configurer les tâches planifiées (optionnel)
+
+Pour activer les notifications par e-mail et la vérification automatique des mises à jour, ajoutez cette ligne à votre `crontab` (via le panneau de contrôle de l'hébergement → **Tâches planifiées / Cron**) :
+
+```
+* * * * * php /chemin/absolu/vers/mesreleves/artisan schedule:run >> /dev/null 2>&1
+```
+
+Remplacez `/chemin/absolu/vers/mesreleves/` par le chemin réel sur votre serveur (visible dans le gestionnaire de fichiers, généralement `/home/user/www/mesreleves/`).
+
+---
+
+### Mise à jour
+
+Dans **Administration → Paramètres du site → Version du logiciel**, le tableau de bord signale automatiquement les nouvelles versions disponibles (si la vérification n'est pas désactivée et que les tâches planifiées sont actives).
+
+**Pour appliquer une mise à jour manuellement :**
+
+1. Télécharger la nouvelle archive `mesreleves-X.Y.Z.tar.gz`
+2. Décompresser et écraser les fichiers existants (**sauf** `.env` et `storage/`)
+3. Exécuter les migrations depuis un terminal SSH :
+ ```bash
+ php artisan migrate --force
+ php artisan optimize:clear
+ ```
+
+---
+
## Fonctionnalités
-- **Saisie collaborative** — formulaires dynamiques pilotés par des types de sources configurables ; champs libres stockés en JSONB PostgreSQL
+- **Saisie collaborative** — formulaires dynamiques pilotés par des types de sources configurables
- **Calendriers** — saisie en calendrier grégorien, julien ou républicain avec conversion automatique
-- **Recherche plein texte** — recherche PostgreSQL native sur les relevés, filtrable par type de source, lieu (avec subdivisions récursives) et plage d'années
-- **Gestion des lieux** — arbre hiérarchique (pays → région → département → commune…), types de lieux configurables, recherche par picker contextuel
+- **Recherche plein texte** — filtrable par type de source, lieu (avec subdivisions récursives) et plage d'années
+- **Gestion des lieux** — arbre hiérarchique (pays → région → département → commune…), types configurables
- **Workflow de validation** — statuts `à faire → en cours → à valider → terminé`, notifications mail + in-app
- **Export GEDCOM 5.5.1** — par source ou par sélection de recherche, conversion des dates vers le grégorien
- **Gestion des rôles** — administrateur, responsable de section, membre ; autorisations granulaires par source
-- **Interface admin** — tableau de bord statistiques, gestion des utilisateurs, sections, dépôts, types de sources et de lieux
-- **Mises à jour automatiques** — vérification quotidienne via l'API Gitea, application sans rebuild Docker
+- **Interface admin** — tableau de bord, gestion des utilisateurs, sections, dépôts d'archives, types de sources
+- **Import / export CSV** — gestion en masse des utilisateurs
+- **Mode sombre** — détection automatique, commutable manuellement (clair / sombre / automatique)
+- **2FA par e-mail** — code PIN à 6 chiffres à la connexion, activé dès qu'un serveur SMTP est configuré
+
+---
## Stack technique
| Composant | Technologie |
|---|---|
-| Backend | PHP 8.5 · Laravel 12 |
-| Base de données | PostgreSQL 18 (JSONB, full-text search, CTE récursives) |
-| Cache / Sessions | Redis 7 |
+| Backend | PHP 8.2+ · Laravel 12 |
+| Base de données | MySQL 8.0+ / MariaDB 10.5+ · ou PostgreSQL 16+ |
| Frontend | Blade · Alpine.js · Tailwind CSS |
| Auth | Laravel Breeze (sessions) |
-| Conteneurs | Docker + Docker Compose |
---
-## Installation
+## Docker
+
+Pour une installation avec Docker (PostgreSQL, Redis, php-fpm) :
### Prérequis
- Docker Engine ≥ 24
-- Docker Compose v2 (`docker compose version`)
+- Docker Compose v2
### Première installation
-**1. Télécharger la dernière release**
-
-Récupérez l'archive `mesreleves-X.Y.Z.tar.gz` depuis la page des [releases](https://git.barbel.synology.me/CGL/mesreleves-php/releases) et extrayez-la :
-
```bash
tar -xzf mesreleves-X.Y.Z.tar.gz
-cd mesreleves-X.Y.Z
+cd mesreleves
+./install.sh
```
-**2. Lancer le script d'installation**
+Le script crée un `.env` depuis `.env.example`. Éditez-le avec vos paramètres, puis relancez :
```bash
./install.sh
```
-Le script crée un `.env` depuis `.env.example` puis s'arrête pour vous laisser le configurer.
-Éditez `.env` avec vos paramètres :
+L'application est accessible sur le port 80.
-```env
-APP_URL=https://votre-domaine.fr
-APP_KEY= # généré automatiquement au démarrage
-
-DB_PASSWORD=mot_de_passe_fort
-
-MAIL_MAILER=smtp
-MAIL_HOST=smtp.example.com
-MAIL_PORT=587
-MAIL_USERNAME=...
-MAIL_PASSWORD=...
-MAIL_FROM_ADDRESS=mesreleves@example.com
-```
-
-**3. Relancer le script**
-
-```bash
-./install.sh
-```
-
-L'application est accessible sur le port 80 (ou la valeur de `APP_URL`).
-
-**4. Activer les tâches planifiées** (optionnel — nécessaire pour la vérification automatique des mises à jour)
-
-Ajoutez à votre crontab (`crontab -e`) la ligne affichée à la fin du script d'installation :
+### Tâches planifiées (Docker)
```
* * * * * cd /chemin/vers/mesreleves && docker compose -f docker-compose.prod.yml exec -T app php artisan schedule:run >> /dev/null 2>&1
```
----
-
-## Mises à jour
-
-### Vérifier la version installée et les mises à jour disponibles
-
-```bash
-docker compose -f docker-compose.prod.yml exec app php artisan app:check-update
-```
-
-### Appliquer une mise à jour
+### Mises à jour (Docker)
```bash
docker compose -f docker-compose.prod.yml exec app php artisan app:update
```
-Le processus :
-1. Sauvegarde PostgreSQL dans `storage/app/backups/`
-2. Téléchargement de la nouvelle archive
-3. Synchronisation des fichiers (`.env` et `storage/` préservés)
-4. `composer install --no-dev`
-5. Migrations
-6. Rechargement gracieux de php-fpm
-7. L'application est disponible pendant toute l'opération (sauf la fenêtre de migration)
-
-### Mise à jour automatique
-
-Pour activer la mise à jour automatique lors de la vérification planifiée, ajoutez dans `.env` :
-
-```env
-AUTO_UPDATE=true
-```
-
-> Par défaut `AUTO_UPDATE=false` : la vérification quotidienne notifie uniquement dans le tableau de bord admin.
-
-### Rollback
-
-En cas de problème, lister les sauvegardes disponibles :
-
-```bash
-docker compose -f docker-compose.prod.yml exec app php artisan app:rollback --list
-```
-
-Restaurer la base de données :
-
-```bash
-docker compose -f docker-compose.prod.yml exec app php artisan app:rollback
-```
-
---
## Développement
### Prérequis
-- PHP 8.2+, Composer, Node.js 20+, npm
-- PostgreSQL 16+ ou Docker
+- PHP 8.2+, Composer, Node.js 20+
+- MySQL 8+ / MariaDB 10.5+ ou PostgreSQL 16+
### Démarrage rapide
```bash
-# Cloner et installer les dépendances
composer install
npm install && npm run build
-# Configuration
cp .env.example .env
php artisan key:generate
-# Démarrer PostgreSQL et Redis (Docker)
+# Démarrer la base de données (Docker)
docker compose up -d
-# Base de données
php artisan migrate
php artisan migrate:fresh --seed # reset + données de test
-# Serveur de développement
-php artisan serve # http://localhost:8000
-npm run dev # Vite en watch (CSS/JS)
+php artisan serve # http://localhost:8000
+npm run dev # Vite en watch (CSS/JS)
```
-Compte administrateur créé par le seeder :
+Comptes de test créés par le seeder :
-| Champ | Valeur |
-|---|---|
-| E-mail | `admin@example.com` |
-| Mot de passe | `password` |
+| E-mail | Rôle | Mot de passe |
+|---|---|---|
+| `admin@mesreleves.local` | Administrateur | `password` |
+| `responsable@mesreleves.local` | Responsable de section | `password` |
+| `membre@mesreleves.local` | Membre | `password` |
### Commandes utiles
@@ -180,26 +239,18 @@ php artisan test # tous les tests
php artisan test --filter=NomTest # un test précis
./vendor/bin/pint # formatage PHP (Laravel Pint)
./vendor/bin/phpstan analyse # analyse statique
-
-php artisan app:check-update # vérifier les mises à jour
-php artisan app:update # appliquer une mise à jour
-php artisan app:rollback --list # lister les sauvegardes
```
### Créer une release
```bash
-# Modifier VERSION (ex : 1.1.0)
echo "1.1.0" > VERSION
git add VERSION && git commit -m "bump version 1.1.0"
-# Construire l'archive
bin/build-release.sh
-# → mesreleves-1.1.0.tar.gz + mesreleves-1.1.0.tar.gz.sha256
+# → mesreleves-1.1.0.tar.gz
-# Publier
git tag v1.1.0 && git push origin v1.1.0
-# Créer une release sur Gitea et joindre les deux fichiers
```
---
@@ -210,26 +261,28 @@ git tag v1.1.0 && git push origin v1.1.0
app/
Models/ Eloquent : User, Source, Releve, Lieu, Section, Depot…
Http/
- Controllers/ Un controller par entité (+ Admin/ pour la gestion)
- Middleware/ RoleMiddleware (admin, section_manager, member)
- Requests/ Form requests avec validation dynamique
- Policies/ Autorisation par modèle (Gates/Policies)
- Services/ GedcomExportService, DateConversionService, UpdateService
+ Controllers/ Un controller par entité (+ Admin/ + Auth/)
+ Middleware/ RoleMiddleware, CheckInstallation, EnsureUserIsActive
+ Requests/ Form requests avec validation
+ Policies/ Autorisation par modèle
+ Services/ GedcomExportService, DateConversionService, UpdateService,
+ SiteSettingsService
Enums/ SourceStatus, UserRole, CalendarType, FieldType
database/
- migrations/ 10 migrations (lieux, sections, sources, relevés…)
+ migrations/ Schéma complet (lieux, sections, sources, relevés…)
seeders/ Données de démonstration
resources/views/
- layouts/ Navigation, app layout
- components/ lieu-picker (Alpine.js + AJAX)
+ layouts/ Navigation (sélecteur de thème), app layout, guest layout
+ components/ lieu-picker, user-picker (recherche modale), dropdown…
+ setup/ Assistant d'installation en 5 étapes
sources/ CRUD + workflow de statut
releves/ Formulaire dynamique par type de source
recherche/ Recherche plein texte + filtres
- admin/ Tableau de bord, utilisateurs, sections, dépôts…
-bin/
- build-release.sh Construction de l'archive de distribution
+ admin/ Tableau de bord, utilisateurs, sections, dépôts, paramètres
```
+---
+
## Licence
Usage interne — association de généalogie.
diff --git a/VERSION b/VERSION
index 3eefcb9..7dea76e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
+1.0.1
diff --git a/app/Http/Controllers/Admin/SettingController.php b/app/Http/Controllers/Admin/SettingController.php
index d0a7a60..93ce0ce 100644
--- a/app/Http/Controllers/Admin/SettingController.php
+++ b/app/Http/Controllers/Admin/SettingController.php
@@ -18,14 +18,16 @@ class SettingController extends Controller
{
public function index(UpdateService $updates): View
{
+ $updatesDisabled = SiteSettingsService::updatesDisabled();
$installedVersion = $updates->getInstalledVersion();
- $latestRelease = $updates->fetchLatestRelease();
+ $latestRelease = $updatesDisabled ? null : $updates->fetchLatestRelease();
$updateAvailable = $latestRelease
&& version_compare($latestRelease['version'], $installedVersion, '>');
return view('admin.parametres.index', [
'logoUrl' => SiteSettingsService::logoUrl(),
'registrationEnabled' => SiteSettingsService::registrationEnabled(),
+ 'updatesDisabled' => $updatesDisabled,
'installedVersion' => $installedVersion,
'latestRelease' => $latestRelease,
'updateAvailable' => $updateAvailable,
@@ -144,6 +146,17 @@ class SettingController extends Controller
}
}
+ // ── Mises à jour ─────────────────────────────────────────────────────────
+
+ public function updateUpdates(Request $request): RedirectResponse
+ {
+ SiteSettingsService::set('updates_disabled', $request->boolean('updates_disabled'));
+
+ return back()->with('success', $request->boolean('updates_disabled')
+ ? 'Vérification automatique des mises à jour désactivée.'
+ : 'Vérification automatique des mises à jour activée.');
+ }
+
// ── Paramètres généraux ───────────────────────────────────────────────────
public function updateSettings(Request $request): RedirectResponse
diff --git a/app/Services/SiteSettingsService.php b/app/Services/SiteSettingsService.php
index 0b0e879..c77e7dd 100644
--- a/app/Services/SiteSettingsService.php
+++ b/app/Services/SiteSettingsService.php
@@ -87,4 +87,11 @@ class SiteSettingsService
// Désactivées par défaut
return (bool) self::get('registration_enabled', false);
}
+
+ // ── Mises à jour ──────────────────────────────────────────────────────────
+
+ public static function updatesDisabled(): bool
+ {
+ return (bool) self::get('updates_disabled', false);
+ }
}
diff --git a/resources/css/app.css b/resources/css/app.css
index b5c61c9..de7488b 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -1,3 +1,5 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+[x-cloak] { display: none !important; }
diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php
index b81ce1c..49b3e90 100644
--- a/resources/views/admin/dashboard.blade.php
+++ b/resources/views/admin/dashboard.blade.php
@@ -1,20 +1,20 @@
-
Tableau de bord — Administration
+
Tableau de bord — Administration
{{-- Bandeau mise à jour disponible --}}
@if($updateAvailable)
-