Files
dokploy/apps/dokploy/pages/swagger.tsx
T
Mauricio Siu c854a38adb fix: use temporary redirects for auth checks in getServerSideProps
Replace permanent (301) redirects with temporary (302) redirects across
all pages that check authentication state in getServerSideProps.

Permanent redirects are cached by the browser indefinitely, causing a
bug where users had to manually refresh after login: the browser would
cache the unauthenticated redirect (dashboard → login page) and replay
it even after a successful login, preventing navigation to the dashboard.

Fixes #4220
2026-04-30 18:46:12 -06:00

116 lines
2.9 KiB
TypeScript

import { validateRequest } from "@dokploy/server";
import { createServerSideHelpers } from "@trpc/react-query/server";
import type { GetServerSidePropsContext, NextPage } from "next";
import dynamic from "next/dynamic";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import "swagger-ui-react/swagger-ui.css";
import { useEffect, useState } from "react";
import superjson from "superjson";
const SwaggerUI = dynamic(() => import("swagger-ui-react"), { ssr: false });
const Home: NextPage = () => {
const { data } = api.settings.getOpenApiDocument.useQuery();
const [spec, setSpec] = useState({});
useEffect(() => {
if (data) {
const protocolAndHost = `${window.location.protocol}//${window.location.host}/api`;
// Force OpenAPI 3.0 so Swagger UI uses the 3.0 parser (avoids ApiDOM 3.1 refract bug)
const newSpec = {
...data,
openapi: "3.0.3",
servers: [{ url: protocolAndHost }],
externalDocs: {
url: `${protocolAndHost}/trpc/settings.getOpenApiDocument`,
},
};
// Remove 3.1-only fields that could confuse the 3.0 parser
if ("jsonSchemaDialect" in newSpec) {
delete (newSpec as Record<string, unknown>).jsonSchemaDialect;
}
setSpec(newSpec);
}
}, [data]);
return (
<div className="h-screen bg-white">
<SwaggerUI
spec={spec}
persistAuthorization={true}
plugins={[
{
statePlugins: {
auth: {
wrapActions: {
authorize: (ori: any) => (args: any) => {
const result = ori(args);
const apiKey = args?.apiKey?.value;
if (apiKey) {
localStorage.setItem("swagger_api_key", apiKey);
}
return result;
},
logout: (ori: any) => (args: any) => {
const result = ori(args);
localStorage.removeItem("swagger_api_key");
return result;
},
},
},
},
},
]}
requestInterceptor={(request: any) => {
const apiKey = localStorage.getItem("swagger_api_key");
if (apiKey) {
request.headers = request.headers || {};
request.headers["x-api-key"] = apiKey;
}
return request;
}}
/>
</div>
);
};
export default Home;
export async function getServerSideProps(context: GetServerSidePropsContext) {
const { req, res } = context;
const { user, session } = await validateRequest(context.req);
if (!user) {
return {
redirect: {
permanent: false,
destination: "/",
},
};
}
const helpers = createServerSideHelpers({
router: appRouter,
ctx: {
req: req as any,
res: res as any,
db: null as any,
session: session as any,
user: user as any,
},
transformer: superjson,
});
const userPermissions = await helpers.user.getPermissions.fetch();
if (!userPermissions?.api.read) {
return {
redirect: {
permanent: false,
destination: "/",
},
};
}
return {
props: {},
};
}