Checkpoint: Correction du bug d'émargement formateur bloqué sur la saisie d'email

- Ajout de la détection automatique formateur/apprenant dans EmargementScan.tsx
- Nouvelle procédure tRPC getSequenceByToken pour récupérer les infos de séquence
- Interface adaptée selon le type d'utilisateur (apprenant ou formateur)
- Déploiement réussi sur le VPS de production

Le système détecte maintenant automatiquement si l'email correspond à un apprenant ou un formateur, et affiche l'interface appropriée pour chaque cas.
This commit is contained in:
Manus
2026-02-02 14:18:46 -05:00
parent e8410230a9
commit f9983adada
81 changed files with 3734 additions and 27745 deletions

View File

@@ -0,0 +1,229 @@
#!/bin/bash
###############################################################################
# Script de création de l'utilisateur administrateur (version simplifiée)
# Utilise un hash bcrypt pré-calculé pour éviter les dépendances Node.js
###############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Création de l'utilisateur administrateur ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier que le fichier .env existe
if [ ! -f ".env" ]; then
echo -e "${RED}[ERREUR]${NC} Fichier .env non trouvé"
exit 1
fi
# Charger les variables d'environnement
export $(cat .env | grep -v '^#' | xargs 2>/dev/null)
# Vérifier que DATABASE_URL est définie
if [ -z "$DATABASE_URL" ]; then
echo -e "${RED}[ERREUR]${NC} DATABASE_URL n'est pas définie dans .env"
exit 1
fi
# Vérifier/Générer JWT_SECRET
if [ -z "$JWT_SECRET" ]; then
echo -e "${YELLOW}[WARN]${NC} JWT_SECRET n'est pas définie"
echo "🔑 Génération automatique de JWT_SECRET..."
NEW_JWT_SECRET=$(openssl rand -base64 32)
echo "JWT_SECRET=$NEW_JWT_SECRET" >> .env
export JWT_SECRET=$NEW_JWT_SECRET
echo -e "${GREEN}[OK]${NC} JWT_SECRET ajouté à .env"
echo ""
fi
# Extraire les informations de connexion de DATABASE_URL
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
# Afficher les informations (masquer le mot de passe)
echo "📋 Configuration de la base de données:"
echo " Hôte: $DB_HOST:$DB_PORT"
echo " Base: $DB_NAME"
echo " Utilisateur: $DB_USER"
echo ""
# Vérifier MySQL
if ! command -v mysql &> /dev/null; then
echo -e "${RED}[ERREUR]${NC} MySQL client n'est pas installé"
echo "Installez-le avec: sudo apt install mysql-client"
exit 1
fi
# Tester la connexion
echo "🔌 Test de connexion à la base de données..."
if ! mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -e "SELECT 1;" 2>/dev/null; then
echo -e "${RED}[ERREUR]${NC} Impossible de se connecter à la base de données"
echo "Vérifiez DATABASE_URL dans .env"
exit 1
fi
echo -e "${GREEN}[OK]${NC} Connexion réussie"
echo ""
# Vérifier que la base de données existe
echo "🔍 Vérification de la base de données '$DB_NAME'..."
if ! mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -e "USE $DB_NAME;" 2>/dev/null; then
echo -e "${RED}[ERREUR]${NC} La base de données '$DB_NAME' n'existe pas"
exit 1
fi
echo -e "${GREEN}[OK]${NC} Base de données trouvée"
echo ""
# Vérifier que la table users existe
echo "🔍 Vérification de la table 'users'..."
TABLE_EXISTS=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -se "SHOW TABLES LIKE 'users';" 2>/dev/null)
if [ -z "$TABLE_EXISTS" ]; then
echo -e "${RED}[ERREUR]${NC} La table 'users' n'existe pas"
echo "Exécutez d'abord: pnpm db:push"
exit 1
fi
echo -e "${GREEN}[OK]${NC} Table 'users' trouvée"
echo ""
# Informations de l'utilisateur
USERNAME="adminServFormation"
PASSWORD="Itinova69!"
EMAIL="admin@formation.local"
NAME="Administrateur"
OPENID="local-admin-$(date +%s)" # OpenID unique pour l'utilisateur local
# Générer le hash bcrypt pour le mot de passe
echo "🔐 Génération du hash bcrypt..."
# Vérifier que bcryptjs est installé
if [ ! -d "node_modules/bcryptjs" ]; then
echo -e "${RED}[ERREUR]${NC} bcryptjs n'est pas installé"
echo "Installation de bcryptjs..."
pnpm install bcryptjs
fi
# Générer le hash avec Node.js
PASSWORD_HASH=$(node -p "require('bcryptjs').hashSync('$PASSWORD', 10)" 2>/dev/null)
if [ -z "$PASSWORD_HASH" ]; then
echo -e "${RED}[ERREUR]${NC} Impossible de générer le hash bcrypt"
echo "Vérifiez que Node.js et bcryptjs sont installés"
exit 1
fi
echo -e "${GREEN}[OK]${NC} Hash généré: ${PASSWORD_HASH:0:30}..."
echo ""
echo "📋 Informations de l'utilisateur:"
echo " Identifiant: $USERNAME"
echo " Mot de passe: $PASSWORD"
echo " Email: $EMAIL"
echo " Rôle: admin"
echo ""
# Vérifier si l'utilisateur existe déjà
echo "🔍 Vérification de l'existence de l'utilisateur..."
USER_COUNT=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -se "SELECT COUNT(*) FROM users WHERE username='$USERNAME';" 2>/dev/null)
if [ "$USER_COUNT" = "1" ]; then
echo -e "${YELLOW}[INFO]${NC} L'utilisateur existe déjà"
echo ""
read -p "Voulez-vous réinitialiser le mot de passe? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Opération annulée"
exit 0
fi
echo "🔄 Réinitialisation du mot de passe..."
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME <<EOF 2>&1
UPDATE users
SET
password = '$PASSWORD_HASH',
email = '$EMAIL',
name = '$NAME',
role = 'admin',
isActive = 1,
loginMethod = 'local',
updatedAt = NOW()
WHERE username = '$USERNAME';
EOF
if [ $? -eq 0 ]; then
echo -e "${GREEN}[OK]${NC} Mot de passe réinitialisé"
else
echo -e "${RED}[ERREUR]${NC} Échec de la réinitialisation"
exit 1
fi
else
echo -e "${YELLOW}[INFO]${NC} L'utilisateur n'existe pas"
echo " Création de l'utilisateur..."
# Créer l'utilisateur avec affichage des erreurs
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME <<EOF 2>&1
INSERT INTO users (openId, username, password, email, name, role, isActive, loginMethod, createdAt, updatedAt)
VALUES (
'$OPENID',
'$USERNAME',
'$PASSWORD_HASH',
'$EMAIL',
'$NAME',
'admin',
1,
'local',
NOW(),
NOW()
);
EOF
if [ $? -eq 0 ]; then
echo -e "${GREEN}[OK]${NC} Utilisateur créé avec succès"
else
echo -e "${RED}[ERREUR]${NC} Échec de la création de l'utilisateur"
echo ""
echo "Vérification de la structure de la table..."
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -e "DESCRIBE users;" 2>&1
exit 1
fi
fi
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Opération terminée avec succès! ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
echo "🔑 Identifiants de connexion:"
echo " Identifiant: $USERNAME"
echo " Mot de passe: $PASSWORD"
echo ""
echo "⚠️ IMPORTANT: Changez le mot de passe après la première connexion"
echo ""
# Vérifier et redémarrer le service si disponible
if command -v systemctl &> /dev/null; then
if systemctl list-unit-files | grep -q "formation-manager"; then
echo "🔄 Redémarrage du service formation-manager..."
if sudo systemctl restart formation-manager 2>/dev/null; then
echo -e "${GREEN}[OK]${NC} Service redémarré"
else
echo -e "${YELLOW}[WARN]${NC} Impossible de redémarrer le service (permissions?)"
echo "Exécutez manuellement: sudo systemctl restart formation-manager"
fi
fi
fi
echo ""
echo "✅ Terminé! Vous pouvez maintenant vous connecter."

View File

@@ -0,0 +1,96 @@
#!/bin/bash
# Script de mise à jour manuel pour le serveur VPS (sans Git)
# Formation Manager Itinova
# Version: dcb709b3
set -e # Arrêter en cas d'erreur
# Charger les variables d'environnement
if [ -f .env ]; then
export $(grep -v '^#' .env | xargs)
fi
echo "========================================="
echo "Mise à jour Formation Manager Itinova"
echo "Mode manuel (sans Git)"
echo "========================================="
echo ""
# Couleurs pour les messages
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
echo -e "${RED}Erreur: package.json non trouvé. Êtes-vous dans le bon répertoire ?${NC}"
exit 1
fi
echo -e "${YELLOW}1. Sauvegarde de la base de données...${NC}"
# Créer un répertoire de backup s'il n'existe pas
mkdir -p backups
BACKUP_FILE="backups/db-backup-$(date +%Y%m%d-%H%M%S).sql"
# Extraire les informations de connexion depuis DATABASE_URL
if [ -z "$DATABASE_URL" ]; then
echo -e "${RED}Erreur: DATABASE_URL n'est pas définie${NC}"
exit 1
fi
# Parser DATABASE_URL
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
echo "Sauvegarde de la base de données $DB_NAME..."
mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_FILE"
echo -e "${GREEN}✓ Sauvegarde créée: $BACKUP_FILE${NC}"
echo ""
echo -e "${YELLOW}2. Arrêt du serveur...${NC}"
pm2 stop formation-manager || echo "Le serveur n'était pas démarré"
echo -e "${GREEN}✓ Serveur arrêté${NC}"
echo ""
echo -e "${YELLOW}3. Les fichiers ont été transférés via SFTP${NC}"
echo "Assurez-vous d'avoir transféré tous les fichiers modifiés avant de continuer."
read -p "Appuyez sur Entrée pour continuer..."
echo ""
echo -e "${YELLOW}4. Installation des dépendances...${NC}"
pnpm install
echo -e "${GREEN}✓ Dépendances installées${NC}"
echo ""
echo -e "${YELLOW}5. Application des migrations de base de données...${NC}"
pnpm db:push
echo -e "${GREEN}✓ Migrations appliquées${NC}"
echo ""
echo -e "${YELLOW}6. Compilation du projet...${NC}"
pnpm build
echo -e "${GREEN}✓ Projet compilé${NC}"
echo ""
echo -e "${YELLOW}7. Redémarrage du serveur...${NC}"
pm2 restart formation-manager || pm2 start npm --name "formation-manager" -- start
echo -e "${GREEN}✓ Serveur redémarré${NC}"
echo ""
echo -e "${YELLOW}8. Vérification du statut...${NC}"
pm2 status formation-manager
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN}Mise à jour terminée avec succès !${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo "Sauvegarde de la base de données: $BACKUP_FILE"
echo "Pour consulter les logs: pm2 logs formation-manager"
echo "Pour arrêter le serveur: pm2 stop formation-manager"
echo ""

View File

@@ -0,0 +1,62 @@
#!/bin/bash
# Script mise à jour avec archive .tar.gz
set -e
# Charger les variables d'environnement
if [ -f .env ]; then
export $(grep -v '^#' .env | xargs)
fi
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo "========================================="
echo "Mise à jour Formation Manager Itinova"
echo "========================================="
if [ -z "$1" ]; then
echo -e "${RED}Usage: $0 /chemin/vers/archive.tar.gz${NC}"
exit 1
fi
ARCHIVE_PATH="$1"
PROJECT_DIR=$(pwd)
TEMP_DIR="/tmp/formation-update-$$"
echo -e "${YELLOW}1. Sauvegarde BDD...${NC}"
mkdir -p backups
BACKUP_FILE="backups/db-backup-$(date +%Y%m%d-%H%M%S).sql"
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" --no-tablespaces "$DB_NAME" > "$BACKUP_FILE"
echo -e "${GREEN}✓ Backup OK${NC}"
echo -e "${YELLOW}2. Arrêt serveur...${NC}"
pm2 stop formation-manager || true
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}3. Extraction...${NC}"
mkdir -p "$TEMP_DIR"
tar -xzf "$ARCHIVE_PATH" -C "$TEMP_DIR"
if [ -d "$TEMP_DIR/formation-manager-itinova" ]; then
EXTRACTED_DIR="$TEMP_DIR/formation-manager-itinova"
else
EXTRACTED_DIR="$TEMP_DIR"
fi
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}4. Copie fichiers...${NC}"
rsync -av --exclude='node_modules' --exclude='dist' --exclude='backups' "$EXTRACTED_DIR/" "$PROJECT_DIR/"
rm -rf "$TEMP_DIR"
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}5. pnpm install...${NC}"
pnpm install
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}6. pnpm db:push...${NC}"
pnpm db:push
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}7. pnpm build...${NC}"
pnpm build
echo -e "${GREEN}✓ OK${NC}"
echo -e "${YELLOW}8. Redémarrage...${NC}"
pm2 restart formation-manager || pm2 start npm --name "formation-manager" -- start
echo -e "${GREEN}✓ OK${NC}"
pm2 status formation-manager
echo -e "${GREEN}Mise à jour terminée !${NC}"

View File

@@ -0,0 +1,98 @@
#!/bin/bash
# Script de mise à jour pour le serveur VPS
# Formation Manager Itinova
# Version: d0d9d870
set -e # Arrêter en cas d'erreur
# Charger les variables d'environnement
if [ -f .env ]; then
export $(grep -v '^#' .env | xargs)
fi
echo "========================================="
echo "Mise à jour Formation Manager Itinova"
echo "========================================="
echo ""
# Couleurs pour les messages
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
echo -e "${RED}Erreur: package.json non trouvé. Êtes-vous dans le bon répertoire ?${NC}"
exit 1
fi
echo -e "${YELLOW}1. Sauvegarde de la base de données...${NC}"
# Créer un répertoire de backup s'il n'existe pas
mkdir -p backups
BACKUP_FILE="backups/db-backup-$(date +%Y%m%d-%H%M%S).sql"
# Extraire les informations de connexion depuis DATABASE_URL
# Format: mysql://user:password@host:port/database
if [ -z "$DATABASE_URL" ]; then
echo -e "${RED}Erreur: DATABASE_URL n'est pas définie${NC}"
exit 1
fi
# Parser DATABASE_URL
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
echo "Sauvegarde de la base de données $DB_NAME..."
mysqldump -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$BACKUP_FILE"
echo -e "${GREEN}✓ Sauvegarde créée: $BACKUP_FILE${NC}"
echo ""
echo -e "${YELLOW}2. Arrêt du serveur...${NC}"
pm2 stop formation-manager || echo "Le serveur n'était pas démarré"
echo -e "${GREEN}✓ Serveur arrêté${NC}"
echo ""
echo -e "${YELLOW}3. Récupération des dernières modifications...${NC}"
git fetch origin
git checkout main
git pull origin main
echo -e "${GREEN}✓ Code mis à jour${NC}"
echo ""
echo -e "${YELLOW}4. Installation des dépendances...${NC}"
pnpm install
echo -e "${GREEN}✓ Dépendances installées${NC}"
echo ""
echo -e "${YELLOW}5. Application des migrations de base de données...${NC}"
pnpm db:push
echo -e "${GREEN}✓ Migrations appliquées${NC}"
echo ""
echo -e "${YELLOW}6. Compilation du projet...${NC}"
pnpm build
echo -e "${GREEN}✓ Projet compilé${NC}"
echo ""
echo -e "${YELLOW}7. Redémarrage du serveur...${NC}"
pm2 restart formation-manager || pm2 start npm --name "formation-manager" -- start
echo -e "${GREEN}✓ Serveur redémarré${NC}"
echo ""
echo -e "${YELLOW}8. Vérification du statut...${NC}"
pm2 status formation-manager
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN}Mise à jour terminée avec succès !${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo "Sauvegarde de la base de données: $BACKUP_FILE"
echo "Pour consulter les logs: pm2 logs formation-manager"
echo "Pour arrêter le serveur: pm2 stop formation-manager"
echo ""

View File

@@ -0,0 +1,273 @@
#!/bin/bash
###############################################################################
# Script de déploiement - Gestion des Formations Manager Itinova
# Version: 1.0.0
# Description: Script automatisé pour déployer l'application en production
###############################################################################
set -e # Arrêter en cas d'erreur
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Fonction pour afficher les messages
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Fonction pour vérifier les prérequis
check_prerequisites() {
log_info "Vérification des prérequis..."
# Vérifier Node.js
if ! command -v node &> /dev/null; then
log_error "Node.js n'est pas installé"
exit 1
fi
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
if [ "$NODE_VERSION" -lt 18 ]; then
log_error "Node.js version 18+ est requis (version actuelle: $(node -v))"
exit 1
fi
log_info "Node.js version: $(node -v)"
# Vérifier pnpm
if ! command -v pnpm &> /dev/null; then
log_warn "pnpm n'est pas installé. Installation..."
npm install -g pnpm
fi
log_info "pnpm version: $(pnpm -v)"
# Vérifier MySQL
if ! command -v mysql &> /dev/null; then
log_warn "MySQL client n'est pas installé"
else
log_info "MySQL client: ✓"
fi
}
# Fonction pour créer le fichier .env si nécessaire
setup_env() {
log_info "Configuration des variables d'environnement..."
if [ ! -f .env ]; then
log_warn "Fichier .env non trouvé. Création à partir du template..."
cat > .env << 'EOF'
# Base de données
DATABASE_URL=mysql://user:password@localhost:3306/formation_manager
# JWT Secret (IMPORTANT: Générer une clé aléatoire sécurisée)
JWT_SECRET=changez_cette_cle_secrete_par_une_valeur_aleatoire_tres_longue
# OAuth Manus
OAUTH_SERVER_URL=https://api.manus.im
VITE_OAUTH_PORTAL_URL=https://login.manus.im
VITE_APP_ID=
# Propriétaire
OWNER_OPEN_ID=
OWNER_NAME=
# Application
VITE_APP_TITLE=Gestion des Formations Manager Itinova
VITE_APP_LOGO=/logo.svg
# APIs Manus (optionnel)
BUILT_IN_FORGE_API_URL=https://forge.manus.im
BUILT_IN_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_URL=https://forge.manus.im
# Analytics (optionnel)
VITE_ANALYTICS_ENDPOINT=
VITE_ANALYTICS_WEBSITE_ID=
# Environnement
NODE_ENV=production
EOF
log_warn "Fichier .env créé. IMPORTANT: Modifiez les valeurs avant de continuer!"
log_warn "Éditez le fichier .env avec vos paramètres de production"
read -p "Appuyez sur Entrée après avoir configuré le fichier .env..."
else
log_info "Fichier .env trouvé ✓"
fi
}
# Fonction pour installer les dépendances
install_dependencies() {
log_info "Installation des dépendances..."
pnpm install --frozen-lockfile
log_info "Dépendances installées ✓"
}
# Fonction pour sauvegarder la base de données
backup_database() {
if [ -z "$DATABASE_URL" ]; then
log_warn "DATABASE_URL non définie, sauvegarde de la base de données ignorée"
return
fi
log_info "Sauvegarde de la base de données..."
BACKUP_DIR="./backups"
mkdir -p $BACKUP_DIR
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/db_backup_$TIMESTAMP.sql"
# Extraire les informations de connexion de DATABASE_URL
# Format: mysql://user:password@host:port/database
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
if command -v mysqldump &> /dev/null; then
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE 2>/dev/null || {
log_warn "Impossible de créer la sauvegarde de la base de données"
return
}
gzip $BACKUP_FILE
log_info "Sauvegarde créée: $BACKUP_FILE.gz ✓"
# Supprimer les sauvegardes de plus de 30 jours
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +30 -delete
else
log_warn "mysqldump non disponible, sauvegarde ignorée"
fi
}
# Fonction pour appliquer les migrations
run_migrations() {
log_info "Application des migrations de base de données..."
pnpm db:push
log_info "Migrations appliquées ✓"
}
# Fonction pour build l'application
build_app() {
log_info "Build de l'application..."
pnpm build
log_info "Build terminé ✓"
}
# Fonction pour redémarrer le service
restart_service() {
if command -v systemctl &> /dev/null; then
SERVICE_NAME="formation-manager"
if systemctl is-active --quiet $SERVICE_NAME; then
log_info "Redémarrage du service $SERVICE_NAME..."
sudo systemctl restart $SERVICE_NAME
# Attendre que le service soit actif
sleep 3
if systemctl is-active --quiet $SERVICE_NAME; then
log_info "Service redémarré avec succès ✓"
else
log_error "Échec du redémarrage du service"
sudo systemctl status $SERVICE_NAME
exit 1
fi
else
log_warn "Le service $SERVICE_NAME n'est pas actif"
log_info "Démarrage du service..."
sudo systemctl start $SERVICE_NAME
fi
else
log_warn "systemctl non disponible. Redémarrage manuel requis."
fi
}
# Fonction pour vérifier le déploiement
verify_deployment() {
log_info "Vérification du déploiement..."
# Vérifier que le serveur répond
if command -v curl &> /dev/null; then
sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
log_info "Application accessible ✓"
else
log_warn "L'application ne répond pas correctement (HTTP $HTTP_CODE)"
fi
fi
}
# Fonction principale
main() {
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Déploiement - Gestion des Formations Manager Itinova ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
log_error "Ce script doit être exécuté depuis la racine du projet"
exit 1
fi
# Étapes de déploiement
check_prerequisites
setup_env
# Charger les variables d'environnement
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi
# Demander confirmation avant de continuer
echo ""
log_warn "Le déploiement va:"
echo " 1. Sauvegarder la base de données"
echo " 2. Installer les dépendances"
echo " 3. Appliquer les migrations"
echo " 4. Builder l'application"
echo " 5. Redémarrer le service"
echo ""
read -p "Continuer? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "Déploiement annulé"
exit 0
fi
backup_database
install_dependencies
run_migrations
build_app
restart_service
verify_deployment
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Déploiement terminé avec succès! ✓ ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
log_info "L'application est maintenant accessible"
log_info "Vérifiez les logs avec: sudo journalctl -u formation-manager -f"
}
# Exécuter le script
main "$@"

View File

@@ -0,0 +1,233 @@
#!/bin/bash
###############################################################################
# Script de diagnostic - Gestion des Formations Manager Itinova
# Vérifie la configuration et l'état de l'application
###############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Diagnostic - Formation Manager Itinova ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
echo -e "${RED}[ERREUR]${NC} Ce script doit être exécuté depuis la racine du projet"
exit 1
fi
# Charger les variables d'environnement
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
echo -e "${GREEN}[OK]${NC} Fichier .env trouvé"
else
echo -e "${RED}[ERREUR]${NC} Fichier .env non trouvé"
exit 1
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 1. VÉRIFICATION DES VARIABLES D'ENVIRONNEMENT"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Vérifier DATABASE_URL
if [ -z "$DATABASE_URL" ]; then
echo -e "${RED}[ERREUR]${NC} DATABASE_URL n'est pas définie"
else
echo -e "${GREEN}[OK]${NC} DATABASE_URL est définie"
# Masquer le mot de passe
MASKED_URL=$(echo $DATABASE_URL | sed 's/:\/\/[^:]*:[^@]*@/:\/\/***:***@/')
echo " $MASKED_URL"
fi
# Vérifier JWT_SECRET
if [ -z "$JWT_SECRET" ]; then
echo -e "${RED}[ERREUR]${NC} JWT_SECRET n'est pas définie"
echo -e "${YELLOW}[INFO]${NC} L'authentification locale ne fonctionnera pas sans JWT_SECRET"
else
echo -e "${GREEN}[OK]${NC} JWT_SECRET est définie"
SECRET_LENGTH=${#JWT_SECRET}
if [ $SECRET_LENGTH -lt 32 ]; then
echo -e "${YELLOW}[WARN]${NC} JWT_SECRET est trop courte ($SECRET_LENGTH caractères, recommandé: 32+)"
else
echo -e "${GREEN}[OK]${NC} JWT_SECRET a une longueur suffisante ($SECRET_LENGTH caractères)"
fi
fi
# Vérifier NODE_ENV
if [ -z "$NODE_ENV" ]; then
echo -e "${YELLOW}[WARN]${NC} NODE_ENV n'est pas définie (défaut: development)"
else
echo -e "${GREEN}[OK]${NC} NODE_ENV = $NODE_ENV"
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 2. VÉRIFICATION DE LA BASE DE DONNÉES"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Extraire les informations de connexion
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
# Tester la connexion MySQL
if command -v mysql &> /dev/null; then
if mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -e "USE $DB_NAME;" 2>/dev/null; then
echo -e "${GREEN}[OK]${NC} Connexion à la base de données réussie"
# Vérifier les tables
TABLES=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -e "SHOW TABLES;" 2>/dev/null | tail -n +2)
if [ -z "$TABLES" ]; then
echo -e "${YELLOW}[WARN]${NC} Aucune table trouvée dans la base de données"
echo -e "${YELLOW}[INFO]${NC} Exécutez 'pnpm db:push' pour créer les tables"
else
echo -e "${GREEN}[OK]${NC} Tables trouvées:"
echo "$TABLES" | while read table; do
echo " - $table"
done
# Vérifier la table users
if echo "$TABLES" | grep -q "users"; then
USER_COUNT=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -e "SELECT COUNT(*) FROM users;" 2>/dev/null | tail -n 1)
echo ""
echo -e "${GREEN}[OK]${NC} Table 'users' existe"
echo " Nombre d'utilisateurs: $USER_COUNT"
# Vérifier si adminServFormation existe
ADMIN_EXISTS=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -e "SELECT COUNT(*) FROM users WHERE username='adminServFormation';" 2>/dev/null | tail -n 1)
if [ "$ADMIN_EXISTS" = "1" ]; then
echo -e "${GREEN}[OK]${NC} Utilisateur 'adminServFormation' existe"
# Vérifier le mot de passe
PASSWORD_HASH=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS -D $DB_NAME -e "SELECT password FROM users WHERE username='adminServFormation';" 2>/dev/null | tail -n 1)
if [ -z "$PASSWORD_HASH" ] || [ "$PASSWORD_HASH" = "NULL" ]; then
echo -e "${RED}[ERREUR]${NC} Le mot de passe de 'adminServFormation' est vide ou NULL"
else
echo -e "${GREEN}[OK]${NC} Le mot de passe est défini (hash: ${PASSWORD_HASH:0:20}...)"
fi
else
echo -e "${RED}[ERREUR]${NC} Utilisateur 'adminServFormation' n'existe pas"
echo -e "${YELLOW}[INFO]${NC} Utilisez le script 'reset-admin.sh' pour le créer"
fi
else
echo -e "${RED}[ERREUR]${NC} Table 'users' n'existe pas"
echo -e "${YELLOW}[INFO]${NC} Exécutez 'pnpm db:push' pour créer les tables"
fi
fi
else
echo -e "${RED}[ERREUR]${NC} Impossible de se connecter à la base de données"
echo -e "${YELLOW}[INFO]${NC} Vérifiez les paramètres de connexion dans .env"
fi
else
echo -e "${YELLOW}[WARN]${NC} MySQL client non installé, impossible de vérifier la base de données"
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 3. VÉRIFICATION DES DÉPENDANCES"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Vérifier node_modules
if [ -d "node_modules" ]; then
echo -e "${GREEN}[OK]${NC} Dossier node_modules existe"
# Vérifier bcryptjs
if [ -d "node_modules/bcryptjs" ]; then
echo -e "${GREEN}[OK]${NC} bcryptjs est installé"
else
echo -e "${RED}[ERREUR]${NC} bcryptjs n'est pas installé"
echo -e "${YELLOW}[INFO]${NC} Exécutez 'pnpm install' pour installer les dépendances"
fi
# Vérifier jsonwebtoken
if [ -d "node_modules/jsonwebtoken" ]; then
echo -e "${GREEN}[OK]${NC} jsonwebtoken est installé"
else
echo -e "${RED}[ERREUR]${NC} jsonwebtoken n'est pas installé"
echo -e "${YELLOW}[INFO]${NC} Exécutez 'pnpm install' pour installer les dépendances"
fi
else
echo -e "${RED}[ERREUR]${NC} Dossier node_modules n'existe pas"
echo -e "${YELLOW}[INFO]${NC} Exécutez 'pnpm install' pour installer les dépendances"
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 4. VÉRIFICATION DU SERVICE"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Vérifier si le service systemd existe
if command -v systemctl &> /dev/null; then
if systemctl list-unit-files | grep -q "formation-manager"; then
echo -e "${GREEN}[OK]${NC} Service systemd 'formation-manager' existe"
if systemctl is-active --quiet formation-manager; then
echo -e "${GREEN}[OK]${NC} Service est actif"
else
echo -e "${YELLOW}[WARN]${NC} Service n'est pas actif"
fi
if systemctl is-enabled --quiet formation-manager; then
echo -e "${GREEN}[OK]${NC} Service est activé au démarrage"
else
echo -e "${YELLOW}[WARN]${NC} Service n'est pas activé au démarrage"
fi
else
echo -e "${YELLOW}[INFO]${NC} Service systemd 'formation-manager' n'existe pas"
fi
fi
# Vérifier si l'application répond
echo ""
if command -v curl &> /dev/null; then
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
echo -e "${GREEN}[OK]${NC} Application répond (HTTP $HTTP_CODE)"
else
echo -e "${YELLOW}[WARN]${NC} Application ne répond pas correctement (HTTP $HTTP_CODE)"
fi
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " RÉSUMÉ DU DIAGNOSTIC"
echo "═══════════════════════════════════════════════════════════════"
echo ""
if [ -z "$JWT_SECRET" ]; then
echo -e "${RED}[ACTION REQUISE]${NC} Définir JWT_SECRET dans .env"
echo " Générer avec: openssl rand -base64 32"
fi
if [ "$ADMIN_EXISTS" != "1" ]; then
echo -e "${RED}[ACTION REQUISE]${NC} Créer l'utilisateur adminServFormation"
echo " Exécuter: ./reset-admin.sh"
fi
if [ -z "$TABLES" ]; then
echo -e "${RED}[ACTION REQUISE]${NC} Initialiser la base de données"
echo " Exécuter: pnpm db:push"
fi
echo ""
echo "Diagnostic terminé."

View File

@@ -0,0 +1,62 @@
#!/bin/bash
###############################################################################
# Script de réinitialisation de l'utilisateur administrateur
# Wrapper pour le script Node.js reset-admin.js
###############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
echo -e "${RED}[ERREUR]${NC} Ce script doit être exécuté depuis la racine du projet"
exit 1
fi
# Vérifier que le fichier .env existe
if [ ! -f ".env" ]; then
echo -e "${RED}[ERREUR]${NC} Fichier .env non trouvé"
echo -e "${YELLOW}[INFO]${NC} Créez un fichier .env avec DATABASE_URL et JWT_SECRET"
exit 1
fi
# Charger les variables d'environnement
export $(cat .env | grep -v '^#' | xargs)
# Vérifier que DATABASE_URL est définie
if [ -z "$DATABASE_URL" ]; then
echo -e "${RED}[ERREUR]${NC} DATABASE_URL n'est pas définie dans .env"
exit 1
fi
# Vérifier que JWT_SECRET est définie
if [ -z "$JWT_SECRET" ]; then
echo -e "${YELLOW}[WARN]${NC} JWT_SECRET n'est pas définie dans .env"
echo -e "${YELLOW}[INFO]${NC} L'authentification locale nécessite JWT_SECRET"
echo ""
echo "Générer une clé JWT sécurisée:"
echo " openssl rand -base64 32"
echo ""
read -p "Voulez-vous générer automatiquement JWT_SECRET? (y/N) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
NEW_JWT_SECRET=$(openssl rand -base64 32)
echo "JWT_SECRET=$NEW_JWT_SECRET" >> .env
export JWT_SECRET=$NEW_JWT_SECRET
echo -e "${GREEN}[OK]${NC} JWT_SECRET ajouté à .env"
echo ""
else
echo -e "${RED}[ERREUR]${NC} JWT_SECRET est requis. Ajoutez-le manuellement dans .env"
exit 1
fi
fi
# Exécuter le script Node.js
node reset-admin.js

View File

@@ -0,0 +1,159 @@
#!/bin/bash
###############################################################################
# Script de configuration du fichier .env pour production
###############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Configuration du fichier .env pour production ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier si .env existe déjà
if [ -f ".env" ]; then
echo -e "${YELLOW}[WARN]${NC} Le fichier .env existe déjà"
read -p "Voulez-vous le remplacer? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Configuration annulée"
exit 0
fi
# Sauvegarder l'ancien
cp .env .env.backup.$(date +%Y%m%d_%H%M%S)
echo -e "${GREEN}[OK]${NC} Ancien fichier sauvegardé"
fi
echo "Ce script va créer un fichier .env avec les paramètres minimaux requis."
echo ""
# Demander DATABASE_URL
echo "═══════════════════════════════════════════════════════════════"
echo " 1. Configuration de la base de données"
echo "═══════════════════════════════════════════════════════════════"
echo ""
read -p "Hôte MySQL (défaut: localhost): " DB_HOST
DB_HOST=${DB_HOST:-localhost}
read -p "Port MySQL (défaut: 3306): " DB_PORT
DB_PORT=${DB_PORT:-3306}
read -p "Nom de la base de données (défaut: formation_manager): " DB_NAME
DB_NAME=${DB_NAME:-formation_manager}
read -p "Utilisateur MySQL: " DB_USER
read -sp "Mot de passe MySQL: " DB_PASS
echo ""
DATABASE_URL="mysql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 2. Génération du JWT_SECRET"
echo "═══════════════════════════════════════════════════════════════"
echo ""
JWT_SECRET=$(openssl rand -base64 32)
echo -e "${GREEN}[OK]${NC} JWT_SECRET généré: ${JWT_SECRET:0:20}..."
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " 3. Configuration de l'application"
echo "═══════════════════════════════════════════════════════════════"
echo ""
read -p "Port de l'application (défaut: 3000): " PORT
PORT=${PORT:-3000}
read -p "Titre de l'application (défaut: Gestion des Formations Manager Itinova): " APP_TITLE
APP_TITLE=${APP_TITLE:-Gestion des Formations Manager Itinova}
# Créer le fichier .env
cat > .env << EOF
# ============================================================================
# CONFIGURATION DE PRODUCTION - Formation Manager Itinova
# Généré le $(date)
# ============================================================================
# ----------------------------------------------------------------------------
# Base de données
# ----------------------------------------------------------------------------
DATABASE_URL=${DATABASE_URL}
# ----------------------------------------------------------------------------
# Sécurité - JWT
# ----------------------------------------------------------------------------
JWT_SECRET=${JWT_SECRET}
# ----------------------------------------------------------------------------
# Application
# ----------------------------------------------------------------------------
PORT=${PORT}
NODE_ENV=production
# Titre de l'application
VITE_APP_TITLE=${APP_TITLE}
# Logo de l'application
VITE_APP_LOGO=/logo-itinova.png
# ----------------------------------------------------------------------------
# OAuth Manus (configuration minimale pour éviter les erreurs)
# ----------------------------------------------------------------------------
VITE_APP_ID=formation-manager-itinova
OAUTH_SERVER_URL=https://api.manus.im
VITE_OAUTH_PORTAL_URL=https://portal.manus.im
OWNER_OPEN_ID=local-owner
OWNER_NAME=Administrateur
# ----------------------------------------------------------------------------
# SMTP - Configuration email (optionnel)
# ----------------------------------------------------------------------------
# Laissez vide si vous n'utilisez pas l'envoi d'emails
SMTP_HOST=
SMTP_PORT=
SMTP_USER=
SMTP_PASS=
SMTP_FROM=
# ----------------------------------------------------------------------------
# Analytics (optionnel)
# ----------------------------------------------------------------------------
VITE_ANALYTICS_ENDPOINT=
VITE_ANALYTICS_WEBSITE_ID=
# ----------------------------------------------------------------------------
# API Forge Manus (optionnel)
# ----------------------------------------------------------------------------
BUILT_IN_FORGE_API_URL=
BUILT_IN_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_URL=
EOF
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Fichier .env créé avec succès! ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
echo "📄 Fichier créé: $(pwd)/.env"
echo ""
echo "⚠️ IMPORTANT:"
echo " 1. Le fichier .env contient des informations sensibles"
echo " 2. Ne le partagez jamais publiquement"
echo " 3. Assurez-vous qu'il n'est pas accessible via le web"
echo ""
echo "🔄 Prochaines étapes:"
echo " 1. Vérifiez la configuration: cat .env"
echo " 2. Appliquez les migrations: pnpm db:push"
echo " 3. Compilez l'application: pnpm build"
echo " 4. Redémarrez le service: sudo systemctl restart formation-manager"
echo ""

View File

@@ -0,0 +1,256 @@
#!/bin/bash
###############################################################################
# Script d'installation automatique de HTTPS avec Let's Encrypt
# Pour l'application Formation Manager Itinova
###############################################################################
set -e
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Installation HTTPS avec Let's Encrypt et nginx ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier que le script est exécuté en tant que root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}[ERREUR]${NC} Ce script doit être exécuté en tant que root (sudo)"
exit 1
fi
# Demander le nom de domaine
echo "═══════════════════════════════════════════════════════════════"
echo " Configuration du domaine"
echo "═══════════════════════════════════════════════════════════════"
echo ""
read -p "Nom de domaine (ex: formations.itinova.org): " DOMAIN
if [ -z "$DOMAIN" ]; then
echo -e "${RED}[ERREUR]${NC} Le nom de domaine est obligatoire"
exit 1
fi
# Demander l'email pour Let's Encrypt
read -p "Email pour les notifications Let's Encrypt: " EMAIL
if [ -z "$EMAIL" ]; then
echo -e "${RED}[ERREUR]${NC} L'email est obligatoire"
exit 1
fi
# Demander le chemin de l'application
read -p "Chemin de l'application (défaut: /var/www/formation-manager-itinova): " APP_PATH
APP_PATH=${APP_PATH:-/var/www/formation-manager-itinova}
# Demander le port de l'application
read -p "Port de l'application (défaut: 3000): " APP_PORT
APP_PORT=${APP_PORT:-3000}
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Résumé de la configuration"
echo "═══════════════════════════════════════════════════════════════"
echo ""
echo "Domaine: $DOMAIN"
echo "Email: $EMAIL"
echo "Chemin application: $APP_PATH"
echo "Port application: $APP_PORT"
echo ""
read -p "Continuer avec cette configuration? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Installation annulée"
exit 0
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 1/6 : Mise à jour du système"
echo "═══════════════════════════════════════════════════════════════"
echo ""
apt update
apt upgrade -y
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 2/6 : Installation de nginx et certbot"
echo "═══════════════════════════════════════════════════════════════"
echo ""
apt install -y nginx certbot python3-certbot-nginx
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 3/6 : Configuration de nginx (HTTP)"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Créer la configuration nginx
cat > /etc/nginx/sites-available/formation-manager << EOF
server {
listen 80;
listen [::]:80;
server_name $DOMAIN;
# Logs
access_log /var/log/nginx/formation-manager-access.log;
error_log /var/log/nginx/formation-manager-error.log;
# Proxy vers l'application Node.js
location / {
proxy_pass http://localhost:$APP_PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
EOF
# Activer la configuration
ln -sf /etc/nginx/sites-available/formation-manager /etc/nginx/sites-enabled/
# Supprimer la configuration par défaut
rm -f /etc/nginx/sites-enabled/default
# Tester la configuration
nginx -t
# Redémarrer nginx
systemctl restart nginx
systemctl enable nginx
echo -e "${GREEN}[OK]${NC} Configuration nginx créée et activée"
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 4/6 : Vérification DNS"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Vérifier que le domaine pointe vers ce serveur
SERVER_IP=$(curl -s ifconfig.me)
DOMAIN_IP=$(dig +short $DOMAIN | tail -n1)
echo "IP du serveur: $SERVER_IP"
echo "IP du domaine: $DOMAIN_IP"
if [ "$SERVER_IP" != "$DOMAIN_IP" ]; then
echo -e "${YELLOW}[WARN]${NC} Le domaine ne pointe pas vers ce serveur"
echo "Veuillez configurer votre DNS avant de continuer"
read -p "Continuer quand même? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Installation annulée"
exit 0
fi
fi
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 5/6 : Obtention du certificat SSL"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Obtenir le certificat avec certbot
certbot --nginx -d $DOMAIN --non-interactive --agree-tos --email $EMAIL --redirect
echo -e "${GREEN}[OK]${NC} Certificat SSL obtenu et installé"
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Étape 6/6 : Configuration avancée de nginx"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Ajouter des optimisations à la configuration HTTPS
# Trouver le bloc server HTTPS (port 443) et ajouter les optimisations
cat > /tmp/nginx-ssl-additions << 'EOF'
# Compression gzip
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# Sécurité headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Cache des fichiers statiques
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://localhost:$APP_PORT;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Limiter la taille des uploads
client_max_body_size 10M;
EOF
echo -e "${GREEN}[OK]${NC} Optimisations ajoutées"
# Tester et recharger nginx
nginx -t
systemctl reload nginx
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo " Mise à jour de la configuration de l'application"
echo "═══════════════════════════════════════════════════════════════"
echo ""
# Modifier la configuration des cookies pour HTTPS
if [ -f "$APP_PATH/server/_core/cookies.ts" ]; then
sed -i 's/sameSite: "lax"/sameSite: "none"/g' "$APP_PATH/server/_core/cookies.ts"
echo -e "${GREEN}[OK]${NC} Configuration des cookies mise à jour (SameSite=None)"
# Recompiler l'application
echo "Recompilation de l'application..."
cd $APP_PATH
pnpm build
# Redémarrer le service
systemctl restart formation-manager
echo -e "${GREEN}[OK]${NC} Application recompilée et redémarrée"
else
echo -e "${YELLOW}[WARN]${NC} Fichier cookies.ts non trouvé, modification manuelle nécessaire"
fi
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Installation HTTPS terminée! ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
echo -e "${GREEN}✅ Votre site est maintenant accessible en HTTPS${NC}"
echo ""
echo "🌐 URL: https://$DOMAIN"
echo ""
echo "📋 Prochaines étapes:"
echo " 1. Testez votre site: https://$DOMAIN"
echo " 2. Vérifiez la sécurité SSL: https://www.ssllabs.com/ssltest/"
echo " 3. Le certificat se renouvellera automatiquement tous les 90 jours"
echo ""
echo "📝 Commandes utiles:"
echo " - Recharger nginx: sudo systemctl reload nginx"
echo " - Voir les logs nginx: sudo tail -f /var/log/nginx/error.log"
echo " - Renouveler le certificat: sudo certbot renew"
echo " - Tester le renouvellement: sudo certbot renew --dry-run"
echo ""