From ba94e7cc7dd2e0f51379b1d1d4efe658d03f57c6 Mon Sep 17 00:00:00 2001
From: Michael SCHAL
Date: Tue, 24 Mar 2026 21:19:49 +0100
Subject: [PATCH] feat: Add MinIO endpoint/public URL configuration via
settings UI
Store endpointUrl and publicUrl in cloudinary_config DB table so
MinIO connection can be fully configured from the app settings
without needing environment variables.
- DB migration: adds endpoint_url and public_url columns
- Schema: adds endpointUrl/publicUrl to cloudinaryConfig table
- MinIO service: reads endpoint from DB (falls back to MINIO_ENDPOINT env)
- buildMinioUrl: accepts optional publicUrl override from DB config
- All routes updated to pass config.publicUrl to buildMinioUrl
- Settings UI (desktop + mobile): adds Endpoint URL and Public URL fields
Co-Authored-By: Claude Sonnet 4.6
---
client/src/pages/mobile/settings.tsx | 38 +++++++++++++++++++++++++++-
client/src/pages/settings.tsx | 36 +++++++++++++++++++++++++-
server/migrate.ts | 12 +++++++++
server/routes.ts | 4 +--
server/routes/reels.ts | 4 +--
server/routes/remotion.ts | 2 +-
server/services/minio.ts | 28 ++++++++++----------
shared/schema.ts | 2 ++
8 files changed, 105 insertions(+), 21 deletions(-)
diff --git a/client/src/pages/mobile/settings.tsx b/client/src/pages/mobile/settings.tsx
index 4901190..4014866 100644
--- a/client/src/pages/mobile/settings.tsx
+++ b/client/src/pages/mobile/settings.tsx
@@ -20,6 +20,8 @@ export default function SettingsMobile() {
const [cloudName, setCloudName] = useState("");
const [apiKey, setApiKey] = useState("");
const [apiSecret, setApiSecret] = useState("");
+ const [endpointUrl, setEndpointUrl] = useState("");
+ const [publicUrl, setPublicUrl] = useState("");
const [openrouterApiKey, setOpenrouterApiKey] = useState("");
const [openrouterModel, setOpenrouterModel] = useState("anthropic/claude-3.5-sonnet");
const [openrouterSystemPrompt, setOpenrouterSystemPrompt] = useState("Tu es un expert en marketing des réseaux sociaux. Génère 3 variations de textes engageants pour des publications Facebook et Instagram à partir des informations produit fournies. Chaque variation doit être unique, captivante et optimisée pour l'engagement.");
@@ -50,6 +52,8 @@ export default function SettingsMobile() {
if (cloudinaryConfig) {
setCloudName((cloudinaryConfig as any).cloudName || "");
setApiKey((cloudinaryConfig as any).apiKey || "");
+ setEndpointUrl((cloudinaryConfig as any).endpointUrl || "");
+ setPublicUrl((cloudinaryConfig as any).publicUrl || "");
if ((cloudinaryConfig as any).logoUrl) {
setLogoPreview((cloudinaryConfig as any).logoUrl);
@@ -70,6 +74,8 @@ export default function SettingsMobile() {
mutationFn: () => {
const payload: any = {
cloudName,
+ endpointUrl: endpointUrl || undefined,
+ publicUrl: publicUrl || undefined,
};
if (apiKey && apiKey.trim() !== "") {
@@ -368,7 +374,7 @@ export default function SettingsMobile() {
Configuration Stockage MinIO
- Configurez MinIO pour le stockage des médias (endpoint via variable MINIO_ENDPOINT)
+ Configurez MinIO pour le stockage des médias
@@ -414,6 +420,36 @@ export default function SettingsMobile() {
Votre Secret Key restera sécurisé et ne sera jamais exposé
+
+
+
setEndpointUrl(e.target.value)}
+ placeholder="http://minio:9000"
+ className="min-h-[48px]"
+ data-testid="input-endpoint-url"
+ />
+
+ URL interne de votre serveur MinIO (ex: http://192.168.1.10:9000)
+
+
+
+
+
setPublicUrl(e.target.value)}
+ placeholder="https://media.votre-domaine.com"
+ className="min-h-[48px]"
+ data-testid="input-public-url"
+ />
+
+ URL publique pour accéder aux fichiers depuis internet
+
+