From 56cd6fd058ef804d11bca9ee1b5d2a68a5e9f4a5 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 29 Jun 2026 21:10:44 +0200 Subject: [PATCH] Fix Nitro client launcher: read the nitro_path setting The /client launcher read a non-existent `nitro_client_url` setting, so it always fell through to "No client configured" and the client never launched. Faithful to AtomCMS's NitroController + nitro.blade.php, build the launch URL as {nitro_path}/index.html?sso= plus the toolbar colour params, via a shared buildNitroClientUrl helper. The Flash launcher's Nitro fallback used the same dead key and is fixed too. --- src/app/client/flash/page.tsx | 21 +++++++++-------- src/app/client/page.tsx | 26 +++++++++------------ src/lib/services/clients.ts | 39 +++++++++++++++++++++++++++++++ src/lib/services/site-settings.ts | 2 +- 4 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 src/lib/services/clients.ts diff --git a/src/app/client/flash/page.tsx b/src/app/client/flash/page.tsx index 8df12767..af0aecb5 100644 --- a/src/app/client/flash/page.tsx +++ b/src/app/client/flash/page.tsx @@ -3,6 +3,7 @@ import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { issueSsoTicket } from "@/lib/auth/sso-ticket"; +import { buildNitroClientUrl } from "@/lib/services/clients"; import { auth } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; @@ -14,17 +15,13 @@ export default async function FlashClientPage() { if (!session?.user?.id) redirect("/login"); const userId = Number(session.user.id); - // The Flash client URL may be stored under either key depending on the - // AtomCMS settings seed — try both, then fall back to the Nitro URL so the - // launcher still issues a working SSO ticket. - const [hotelName, flashUrl, flashUrlAlt, nitroUrl] = await Promise.all([ + // The Flash client base URL may be stored under either settings key. + const [hotelNameRaw, flashUrl, flashUrlAlt] = await Promise.all([ siteSettings.get("hotel_name", "Atom").catch(() => "Atom"), siteSettings.get("flash_client_url", "").catch(() => ""), siteSettings.get("client_flash_url", "").catch(() => ""), - siteSettings.get("nitro_client_url", "").catch(() => ""), ]); - - const clientUrl = flashUrl || flashUrlAlt || nitroUrl || ""; + const hotelName = hotelNameRaw ?? "Atom"; const hdrs = await headers(); const ip = @@ -32,11 +29,15 @@ export default async function FlashClientPage() { // Faithful to AtomCMS's client controllers: issue (and persist) the SSO ticket // on the launcher render, then hand it to the Flash client. - const ticket = await issueSsoTicket(prisma, userId, hotelName ?? "Atom", ip); + const ticket = await issueSsoTicket(prisma, userId, hotelName, ip); - const src = clientUrl - ? `${clientUrl}${clientUrl.includes("?") ? "&" : "?"}sso=${encodeURIComponent(ticket)}` + // Use a configured Flash base URL (with the SSO ticket appended); otherwise + // fall back to the Nitro client so the launcher still works. + const flashBase = flashUrl || flashUrlAlt || ""; + const flashSrc = flashBase + ? `${flashBase}${flashBase.includes("?") ? "&" : "?"}sso=${encodeURIComponent(ticket)}` : ""; + const src = flashSrc || (await buildNitroClientUrl(ticket)); return (
diff --git a/src/app/client/page.tsx b/src/app/client/page.tsx index 432bcf9a..e1dea63d 100644 --- a/src/app/client/page.tsx +++ b/src/app/client/page.tsx @@ -3,6 +3,7 @@ import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { issueSsoTicket } from "@/lib/auth/sso-ticket"; +import { buildNitroClientUrl } from "@/lib/services/clients"; import { auth } from "@/lib/auth"; import { prisma } from "@/lib/prisma"; import { siteSettings } from "@/lib/services/site-settings"; @@ -14,28 +15,22 @@ export default async function ClientPage() { if (!session?.user?.id) redirect("/login"); const userId = Number(session.user.id); - const [hotelName, clientUrl] = await Promise.all([ - siteSettings.get("hotel_name", "Atom"), - siteSettings.get("nitro_client_url", ""), - ]); + const hotelName = (await siteSettings.get("hotel_name", "Atom")) ?? "Atom"; const hdrs = await headers(); const ip = hdrs.get("x-forwarded-for")?.split(",")[0]?.trim() ?? hdrs.get("x-real-ip") ?? "0.0.0.0"; // Faithful to AtomCMS's NitroController: issue (and persist) the SSO ticket on - // the launcher render, then hand it to the client. - const ticket = await issueSsoTicket(prisma, userId, hotelName ?? "Atom", ip); - - const src = clientUrl - ? `${clientUrl}${clientUrl.includes("?") ? "&" : "?"}sso=${encodeURIComponent(ticket)}` - : ""; + // the launcher render, then hand it to the Nitro client at {nitro_path}. + const ticket = await issueSsoTicket(prisma, userId, hotelName, ip); + const src = await buildNitroClientUrl(ticket); return (
@@ -49,14 +44,15 @@ export default async function ClientPage() {