feat: normaliser les URL production par entité
Some checks failed
Validation applicative / TypeScript, tests et build (push) Failing after 1m35s

This commit is contained in:
Santinova Deployment
2026-10-24 17:06:48 +00:00
parent a7845f5b06
commit 9e097e585a
12 changed files with 37 additions and 36 deletions

View File

@@ -22,7 +22,7 @@ nano .env
### 3. Ajouter la variable APP_PUBLIC_URL
Ajoutez cette ligne dans le fichier `.env` :
```
APP_PUBLIC_URL=https://formations.itinova.org
APP_PUBLIC_URL=https://formations-itinova.santinova-soft.org
```
### 4. Redémarrer l'application
@@ -38,7 +38,7 @@ sudo systemctl restart formation-manager-itinova
1. Connectez-vous à l'interface formateur
2. Générez un nouveau QR code pour une séquence
3. Scannez le QR code avec votre téléphone
4. Vérifiez que l'URL commence par `https://formations.itinova.org/emargement/...`
4. Vérifiez que l'URL commence par `https://formations-itinova.santinova-soft.org/emargement/...`
## Alternative : Utiliser DOMAIN_NAME
Si vous préférez, vous pouvez aussi utiliser :

View File

@@ -101,7 +101,7 @@ server {
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;
@@ -170,12 +170,12 @@ Si tout se passe bien, vous verrez un message de succès indiquant que le certif
Testez que votre site est accessible en HTTPS :
```bash
curl -I https://formations.itinova.org
curl -I https://formations-itinova.santinova-soft.org
```
Vous devriez voir une réponse HTTP/2 200 OK.
Ouvrez votre navigateur et accédez à `https://formations.itinova.org`. Vous devriez voir :
Ouvrez votre navigateur et accédez à `https://formations-itinova.santinova-soft.org`. Vous devriez voir :
- Un cadenas vert dans la barre d'adresse
- Votre application fonctionnant normalement
- Aucun avertissement de sécurité
@@ -387,6 +387,6 @@ Pour aller plus loin, vous pouvez configurer un pare-feu (ufw), mettre en place
---
**Auteur** : Manus AI
**Date** : 23 novembre 2025
**Auteur** : Manus AI
**Date** : 23 novembre 2025
**Version** : 1.0

View File

@@ -3,8 +3,8 @@
"name": "Formation Manager",
"category": "ITINOVA",
"urls": {
"recette": "https://formations.recette.santinova-soft.org",
"prod": "https://formations.santinova-soft.org"
"recette": "https://formations-itinova.recette.santinova-soft.org",
"prod": "https://formations-itinova.santinova-soft.org"
},
"containerName": "formation-manager-itinova",
"image": "images/formation-manager.png",

View File

@@ -163,7 +163,7 @@ export default function AdminEmailTemplates() {
.replace(/\{\{formateur\}\}/g, 'Jean Martin')
.replace(/\{\{couleurPrincipale\}\}/g, formData.couleurPrincipale)
.replace(/\{\{couleurSecondaire\}\}/g, formData.couleurSecondaire)
.replace(/\{\{lienReinitialisation\}\}/g, 'https://formations.itinova.org/reset-password/token123')
.replace(/\{\{lienReinitialisation\}\}/g, 'https://formations-itinova.santinova-soft.org/reset-password/token123')
.replace(/\{\{datesHTML\}\}/g, '<div class="date-item"><strong>Date 1 :</strong> lundi 15 janvier 2025</div><div class="date-item"><strong>Date 2 :</strong> mardi 16 janvier 2025</div>');
};
@@ -369,7 +369,7 @@ export default function AdminEmailTemplates() {
<div>
<Label htmlFor="bodyContent">Corps du message</Label>
{/* Boutons de variables dynamiques */}
<div className="flex flex-wrap gap-2 mb-2">
<Button

View File

@@ -14,14 +14,14 @@ import DashboardLayout from "@/components/DashboardLayout";
export default function AdminParametres() {
const { data: parametres, isLoading, refetch } = trpc.parametres.get.useQuery();
const { data: historique, isLoading: isLoadingHistorique } = trpc.parametres.getHistorique.useQuery({ limit: 20 });
const [urlPublique, setUrlPublique] = useState("");
const [delaiExpirationQR, setDelaiExpirationQR] = useState(30);
const [dureeValiditeToken, setDureeValiditeToken] = useState(24);
const [notificationsActives, setNotificationsActives] = useState(true);
const [testUrlStatus, setTestUrlStatus] = useState<{ loading: boolean; result?: { accessible: boolean; message: string } }>({ loading: false });
// Initialiser les valeurs quand les données sont chargées
useEffect(() => {
if (parametres) {
@@ -60,7 +60,7 @@ export default function AdminParametres() {
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Validation de l'URL
try {
new URL(urlPublique);
@@ -129,7 +129,7 @@ export default function AdminParametres() {
<Input
id="urlPublique"
type="url"
placeholder="https://formations.itinova.org"
placeholder="https://formations-itinova.santinova-soft.org"
value={urlPublique}
onChange={(e) => {
setUrlPublique(e.target.value);
@@ -168,8 +168,8 @@ export default function AdminParametres() {
</Button>
</div>
<p className="text-sm text-muted-foreground">
Cette URL est utilisée pour générer les QR codes d'émargement.
Exemple : https://formations.itinova.org (sans slash à la fin)
Cette URL est utilisée pour générer les QR codes d'émargement.
Exemple : https://formations-itinova.santinova-soft.org (sans slash à la fin)
</p>
</div>
@@ -225,8 +225,8 @@ export default function AdminParametres() {
</div>
<div className="flex items-center gap-2 pt-4">
<Button
type="submit"
<Button
type="submit"
disabled={updateMutation.isPending}
className="gap-2"
>

View File

@@ -18,6 +18,7 @@ services:
env_file:
- .env
environment:
APP_PUBLIC_URL: https://formations-itinova.santinova-soft.org
NODE_ENV: production
PORT: 3000
TRUST_PROXY: 1
@@ -29,7 +30,7 @@ services:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.http.routers.formations-prod.entrypoints=websecure"
- "traefik.http.routers.formations-prod.rule=Host(`formations.santinova-soft.org`)"
- "traefik.http.routers.formations-prod.rule=Host(`formations.santinova-soft.org`) || Host(`formations-itinova.santinova-soft.org`)"
- "traefik.http.routers.formations-prod.tls=true"
- "traefik.http.routers.formations-prod.tls.certresolver=letsencrypt"
- "traefik.http.routers.formations-prod.service=formations-prod-svc"

View File

@@ -571,7 +571,7 @@ export type InsertLogNotification = typeof logsNotifications.$inferInsert;
export const parametres = mysqlTable("parametres", {
id: int("id").autoincrement().primaryKey(),
/** URL publique de l'application pour les QR codes d'émargement */
urlPublique: varchar("urlPublique", { length: 500 }).notNull().default("https://formations.itinova.org"),
urlPublique: varchar("urlPublique", { length: 500 }).notNull().default("https://formations-itinova.santinova-soft.org"),
/** Délai d'expiration des QR codes en minutes (par défaut 30 minutes) */
delaiExpirationQR: int("delaiExpirationQR").default(30).notNull(),
/** Durée de validité des tokens d'émargement en heures (par défaut 24 heures) */

View File

@@ -237,7 +237,7 @@ else
fi
execute_sql "Ajout de la colonne urlPublique" \
"ALTER TABLE parametres ADD COLUMN urlPublique VARCHAR(500) NOT NULL DEFAULT 'https://formations.itinova.org' AFTER id;"
"ALTER TABLE parametres ADD COLUMN urlPublique VARCHAR(500) NOT NULL DEFAULT 'https://formations-itinova.santinova-soft.org' AFTER id;"
execute_sql "Ajout de la colonne delaiExpirationQR" \
"ALTER TABLE parametres ADD COLUMN delaiExpirationQR INT NOT NULL DEFAULT 30 AFTER urlPublique;"

View File

@@ -20,7 +20,7 @@ if [ ! -f "$ENV_FILE" ]; then
fi
# Demander l'URL publique
echo "Entrez l'URL publique de votre application (ex: https://formations.itinova.org) :"
echo "Entrez l'URL publique de votre application (ex: https://formations-itinova.santinova-soft.org) :"
read PUBLIC_URL
# Vérifier que l'URL commence par http:// ou https://

View File

@@ -17,7 +17,7 @@ describe("modèle d’e-mail de réinitialisation", () => {
});
it("substitue le lien de réinitialisation dans le contenu du modèle", () => {
const link = "https://formations.recette.santinova-soft.org/reset-password?token=abc123";
const link = "https://formations-itinova.recette.santinova-soft.org/reset-password?token=abc123";
const result = replaceEmailVariables(
'<a href="{{lienReinitialisation}}">Réinitialiser</a>',
{ lienReinitialisation: link },
@@ -38,7 +38,7 @@ describe("modèle d’e-mail de réinitialisation", () => {
});
const { generateEmailFromTemplate } = await import("../emailTemplateGenerator");
const resetLink = "https://formations.recette.santinova-soft.org/reset-password?token=abc123";
const resetLink = "https://formations-itinova.recette.santinova-soft.org/reset-password?token=abc123";
const html = await generateEmailFromTemplate(
"reset_password",
`<a href="${resetLink}">Réinitialiser</a>`,

View File

@@ -11,17 +11,17 @@ export async function getParametres() {
if (!db) throw new Error("Database not available");
const result = await db.select().from(parametres).limit(1);
if (result.length === 0) {
// Créer les paramètres par défaut
await db.insert(parametres).values({
urlPublique: "https://formations.itinova.org",
urlPublique: "https://formations-itinova.santinova-soft.org",
});
const newResult = await db.select().from(parametres).limit(1);
return newResult[0];
}
return result[0];
}
@@ -44,7 +44,7 @@ export async function updateParametres(
if (!db) throw new Error("Database not available");
const params = await getParametres();
// Enregistrer l'historique pour chaque champ modifié
for (const [key, value] of Object.entries(updates)) {
const oldValue = params[key as keyof typeof params];
@@ -58,12 +58,12 @@ export async function updateParametres(
});
}
}
// Mettre à jour les paramètres
await db.update(parametres)
.set(updates)
.where(eq(parametres.id, params.id));
return getParametres();
}
@@ -113,8 +113,8 @@ export async function testerUrl(url: string): Promise<{ accessible: boolean; mes
return {
accessible: response.ok,
message: response.ok
? "L'URL est accessible"
message: response.ok
? "L'URL est accessible"
: `L'URL a retourné une erreur HTTP ${response.status}`,
statusCode: response.status
};
@@ -125,7 +125,7 @@ export async function testerUrl(url: string): Promise<{ accessible: boolean; mes
message: "Format d'URL invalide"
};
}
return {
accessible: false,
message: `Erreur lors du test: ${error instanceof Error ? error.message : 'Erreur inconnue'}`

View File

@@ -689,7 +689,7 @@
- [x] Créer la page AdminParametres
- [x] Ajouter le lien dans le menu après "Configuration SMTP"
- [x] Modifier qrCodeGenerator pour utiliser l'URL de la BDD
- [x] Définir l'URL par défaut : https://formations.itinova.org
- [x] Définir l'URL par défaut : https://formations-itinova.santinova-soft.org
- [x] Ajouter DashboardLayout à la page AdminParametres
- [x] Ajouter DashboardLayout à la page FormateurEmargement