mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-23 07:08:05 +02:00
URL publique du site réglable depuis le backoffice
Connecter un réseau social imposait de poser NEXT_PUBLIC_SITE_URL dans docker-compose et de redémarrer le conteneur. L'écran Réseaux sociaux porte désormais le champ, pré-rempli avec l'adresse par laquelle l'administrateur consulte la page. - Nouveau réglage `site_public_url` ; `siteUrl()` lit la base puis retombe sur les variables d'environnement, donc les déploiements actuels ne bougent pas. - `siteUrl()`, `redirectUri()`, `authorizeUrl()`, `promoLink()` et `buildPromoMessage()` deviennent asynchrones. - Seule l'origine est conservée : le schéma est ajouté s'il manque, un chemin est retiré, et une adresse invalide revient sur l'écran avec un message au lieu d'une page d'erreur brute. - `saveSiteSettings` saute cette clé : le formulaire Paramètres ne la contient pas et l'aurait écrasée à chaque enregistrement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
This commit is contained in:
9 files changed
+146
-37
No files matched your search
@@ -952,6 +952,9 @@ export async function saveSiteSettings(formData: FormData) {
|
||||
const updatedAt = new Date();
|
||||
|
||||
for (const key of Object.keys(SITE_SETTING_DEFAULTS)) {
|
||||
// Réglée sur l'écran Réseaux sociaux : ce formulaire ne la contient pas et
|
||||
// l'écraserait avec une chaîne vide.
|
||||
if (key === "site_public_url") continue;
|
||||
await db
|
||||
.insert(siteSettings)
|
||||
.values({ key, value: asString(formData, key), updatedAt })
|
||||
@@ -1133,6 +1136,45 @@ export async function setContactStatus(formData: FormData) {
|
||||
revalidatePath("/backend");
|
||||
}
|
||||
|
||||
// ---- URL publique de l'application ----
|
||||
// Sert à l'adresse de retour OAuth et au lien inséré dans les publications.
|
||||
export async function saveSitePublicUrl(formData: FormData) {
|
||||
const { role } = await requireRole();
|
||||
if (!can(role, "manageSettings")) throw new Error("Accès refusé");
|
||||
|
||||
const raw = asString(formData, "sitePublicUrl");
|
||||
let value = "";
|
||||
if (raw) {
|
||||
// Le schéma est facultatif à la saisie ; seul l'origine est conservée, un
|
||||
// chemin ou des paramètres casseraient l'adresse de retour OAuth.
|
||||
const candidate = /^[a-z][a-z0-9+.-]*:\/\//i.test(raw) ? raw : `https://${raw}`;
|
||||
let parsed: URL | null = null;
|
||||
try {
|
||||
parsed = new URL(candidate);
|
||||
} catch {
|
||||
parsed = null;
|
||||
}
|
||||
if (!parsed || !["http:", "https:"].includes(parsed.protocol) || !parsed.hostname) {
|
||||
// Message rendu par le bandeau de l'écran, plutôt qu'une page d'erreur brute.
|
||||
redirect(
|
||||
`/backend/reseaux?error=${encodeURIComponent(
|
||||
"Adresse invalide : indiquez par exemple https://pleinr.example.fr"
|
||||
)}`
|
||||
);
|
||||
}
|
||||
value = parsed.origin;
|
||||
}
|
||||
|
||||
const updatedAt = new Date();
|
||||
await db
|
||||
.insert(siteSettings)
|
||||
.values({ key: "site_public_url", value, updatedAt })
|
||||
.onConflictDoUpdate({ target: siteSettings.key, set: { value, updatedAt } });
|
||||
|
||||
revalidatePath("/backend/reseaux");
|
||||
revalidatePath("/backend/parametres");
|
||||
}
|
||||
|
||||
// ---- Réseaux sociaux : identifiants d'application et connexion ----
|
||||
export async function saveSocialApp(formData: FormData) {
|
||||
const { role } = await requireRole();
|
||||
|
||||
Reference in new issue
Block a user