fix: added OPENAPI_ENABLED & API_ENABLED variables

This commit is contained in:
charles-gauthereau
2026-05-28 22:08:49 +02:00
parent d49d8f52c4
commit 174ff0886c
9 changed files with 88 additions and 63 deletions
+1 -1
View File
@@ -4,6 +4,6 @@ export async function GET() {
return NextResponse.json({ return NextResponse.json({
PROJECT_URL: process.env.PROJECT_URL, PROJECT_URL: process.env.PROJECT_URL,
PROJECT_NAME: process.env.PROJECT_NAME, PROJECT_NAME: process.env.PROJECT_NAME,
PROJECT_DESCRIPTION: process.env.PROJECT_DESCRIPTION, PROJECT_DESCRIPTION: process.env.PROJECT_DESCRIPTION
}); });
} }
+27 -10
View File
@@ -6,8 +6,6 @@ import { headers } from "next/headers";
import { env } from "@/env.mjs"; import { env } from "@/env.mjs";
import {User} from "@/db/schema/02_user"; import {User} from "@/db/schema/02_user";
const OPENAPI_ENABLED = String(env.OPENAPI_ENABLED).toLowerCase() === "true";
export async function proxy(request: NextRequest) { export async function proxy(request: NextRequest) {
const url = request.nextUrl.clone(); const url = request.nextUrl.clone();
const redirectUrl = encodeURIComponent(request.nextUrl.pathname); const redirectUrl = encodeURIComponent(request.nextUrl.pathname);
@@ -44,6 +42,33 @@ export async function proxy(request: NextRequest) {
} }
if (url.pathname.startsWith("/api")) { if (url.pathname.startsWith("/api")) {
if (url.pathname.startsWith("/api/v1")) {
const apiEnabled = String(env.API_ENABLED) === "true";
if (!apiEnabled) {
return new NextResponse(
JSON.stringify({
message: "This API route does not exist.",
status: 404,
}),
{ status: 404, headers: { "Content-Type": "application/json" } },
);
}
const openapiEnabled = String(env.OPENAPI_ENABLED) === "true";
if (
!openapiEnabled &&
(url.pathname.startsWith("/api/v1/docs") ||
url.pathname.startsWith("/api/v1/openapi"))
) {
return new NextResponse(
JSON.stringify({
message: "This API route does not exist.",
status: 404,
}),
{ status: 404, headers: { "Content-Type": "application/json" } },
);
}
}
const routeExists = checkRouteExists(url.pathname); const routeExists = checkRouteExists(url.pathname);
if (!routeExists) { if (!routeExists) {
return new NextResponse( return new NextResponse(
@@ -80,16 +105,8 @@ function checkRouteExists(pathname: string) {
/^\/api\/health\/?$/, /^\/api\/health\/?$/,
/^\/api\/google\/drive\/callback\/?$/, /^\/api\/google\/drive\/callback\/?$/,
// v1 external API // v1 external API
...(OPENAPI_ENABLED
? [
/^\/api\/v1\/docs\/?$/, /^\/api\/v1\/docs\/?$/,
/^\/api\/v1\/openapi\/?$/, /^\/api\/v1\/openapi\/?$/,
]
: []),
/^\/api\/v1\/agents\/?$/, /^\/api\/v1\/agents\/?$/,
/^\/api\/v1\/agents\/[^/]+\/?$/, /^\/api\/v1\/agents\/[^/]+\/?$/,
/^\/api\/v1\/agents\/[^/]+\/key\/?$/, /^\/api\/v1\/agents\/[^/]+\/key\/?$/,
+6
View File
@@ -103,6 +103,11 @@ export const env = createEnv({
.enum(["true", "false"]) .enum(["true", "false"])
.transform((val) => val === "true") .transform((val) => val === "true")
.default("false"), .default("false"),
API_ENABLED: z
.enum(["true", "false"])
.transform((val) => val === "true")
.default("false"),
}, },
client: { client: {
NEXT_PUBLIC_PROJECT_VERSION: z.string().optional(), NEXT_PUBLIC_PROJECT_VERSION: z.string().optional(),
@@ -177,5 +182,6 @@ export const env = createEnv({
AUTH_DEFAULT_PASSWORD: process.env.AUTH_DEFAULT_PASSWORD, AUTH_DEFAULT_PASSWORD: process.env.AUTH_DEFAULT_PASSWORD,
OPENAPI_ENABLED: process.env.OPENAPI_ENABLED, OPENAPI_ENABLED: process.env.OPENAPI_ENABLED,
API_ENABLED: process.env.API_ENABLED,
}, },
}); });
@@ -2,6 +2,7 @@ import { currentUser } from "@/lib/auth/current-user";
import { getAccounts, getSession, getSessions } from "@/lib/auth/auth"; import { getAccounts, getSession, getSessions } from "@/lib/auth/auth";
import { LoggedInButtonClient } from "./logged-in-button"; import { LoggedInButtonClient } from "./logged-in-button";
import { SUPPORTED_PROVIDERS } from "@/lib/auth/config"; import { SUPPORTED_PROVIDERS } from "@/lib/auth/config";
import { env } from "@/env.mjs";
export const LoggedInButton = async () => { export const LoggedInButton = async () => {
const user = await currentUser(); const user = await currentUser();
@@ -11,6 +12,7 @@ export const LoggedInButton = async () => {
if (!user) return null; if (!user) return null;
return ( return (
<LoggedInButtonClient <LoggedInButtonClient
user={user} user={user}
@@ -19,6 +21,7 @@ export const LoggedInButton = async () => {
currentSession={currentSession.session} currentSession={currentSession.session}
accounts={accounts} accounts={accounts}
providers={SUPPORTED_PROVIDERS.filter((p) => p.isActive)} providers={SUPPORTED_PROVIDERS.filter((p) => p.isActive)}
apiEnabled={env.API_ENABLED}
/> />
); );
}; };
+3 -1
View File
@@ -14,9 +14,10 @@ type LoggedInButtonClientProps = {
currentSession: Session; currentSession: Session;
accounts: Account[]; accounts: Account[];
providers: AuthProviderConfig[]; providers: AuthProviderConfig[];
apiEnabled: boolean;
}; };
export const LoggedInButtonClient = ({ user, sessions, currentSession, accounts, providers }: LoggedInButtonClientProps) => { export const LoggedInButtonClient = ({ user, sessions, currentSession, accounts, providers, apiEnabled }: LoggedInButtonClientProps) => {
return ( return (
<LoggedInDropdown <LoggedInDropdown
user={user} user={user}
@@ -27,6 +28,7 @@ export const LoggedInButtonClient = ({ user, sessions, currentSession, accounts,
// @ts-ignore // @ts-ignore
accounts={accounts} accounts={accounts}
providers={providers} providers={providers}
apiEnabled={apiEnabled}
> >
<SidebarMenuButton type="button" className="h-auto justify-between py-2" data-testid="profile-dropdown"> <SidebarMenuButton type="button" className="h-auto justify-between py-2" data-testid="profile-dropdown">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
+3 -1
View File
@@ -16,9 +16,10 @@ export type LoggedInDropdownProps = PropsWithChildren<{
accounts: Account[]; accounts: Account[];
children: ReactNode; children: ReactNode;
providers: AuthProviderConfig[]; providers: AuthProviderConfig[];
apiEnabled: boolean;
}>; }>;
export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, children, providers }: LoggedInDropdownProps) => { export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, children, providers, apiEnabled }: LoggedInDropdownProps) => {
const router = useRouter(); const router = useRouter();
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
@@ -33,6 +34,7 @@ export const LoggedInDropdown = ({ user, sessions, currentSession, accounts, chi
open={isModalOpen} open={isModalOpen}
onOpenChange={setIsModalOpen} onOpenChange={setIsModalOpen}
providers={providers} providers={providers}
apiEnabled={apiEnabled}
/> />
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger> <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
+3 -2
View File
@@ -19,9 +19,10 @@ type ProfileModalProps = {
accounts: Account[]; accounts: Account[];
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
providers: AuthProviderConfig[]; providers: AuthProviderConfig[];
apiEnabled: boolean;
}; };
export const ProfileModal = ({ user, sessions, currentSession, accounts, open, onOpenChange, providers }: ProfileModalProps) => { export const ProfileModal = ({ user, sessions, currentSession, accounts, open, onOpenChange, providers, apiEnabled }: ProfileModalProps) => {
return ( return (
<Dialog open={open} onOpenChange={onOpenChange}> <Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="w-[95vw] h-[90vh] max-w-md lg:max-w-[1000px] lg:h-[800px] pb-6 p-0 overflow-hidden flex flex-col outline-none gap-0 rounded-xl bg-background"> <DialogContent className="w-[95vw] h-[90vh] max-w-md lg:max-w-[1000px] lg:h-[800px] pb-6 p-0 overflow-hidden flex flex-col outline-none gap-0 rounded-xl bg-background">
@@ -54,7 +55,7 @@ export const ProfileModal = ({ user, sessions, currentSession, accounts, open, o
</TabsContent> </TabsContent>
<TabsContent value="account" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0"> <TabsContent value="account" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0">
<ProfileAccount user={user} /> <ProfileAccount user={user} apiEnabled={apiEnabled} />
</TabsContent> </TabsContent>
<TabsContent value="appearance" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0"> <TabsContent value="appearance" className="mt-0 h-full p-6 lg:p-10 outline-none focus-visible:ring-0">
+5 -15
View File
@@ -48,9 +48,11 @@ import { copyToClipboardWithMeta } from "@/components/common/copy-button";
interface ProfileAccountProps { interface ProfileAccountProps {
user: User; user: User;
apiEnabled: boolean;
} }
export function ProfileAccount({ user }: ProfileAccountProps) { export function ProfileAccount({ user, apiEnabled }: ProfileAccountProps) {
const router = useRouter(); const router = useRouter();
const [isAddApiKeyOpen, setIsAddApiKeyOpen] = useState(false); const [isAddApiKeyOpen, setIsAddApiKeyOpen] = useState(false);
@@ -159,20 +161,6 @@ export function ProfileAccount({ user }: ProfileAccountProps) {
const { mutate: addApiKey, isPending: isAddingApikey } = useMutation({ const { mutate: addApiKey, isPending: isAddingApikey } = useMutation({
mutationFn: async () => { mutationFn: async () => {
// const permissions = {
// organization: ["read", "read-write"],
// }
//
// const result = await authClient.apiKey.create({
// name: apiKeyName || "My API Key",
// prefix: "sk_",
// permissions
// });
//
// if (result?.error) {
// throw result.error;
// }
const result = await createApiKeysAction({ const result = await createApiKeysAction({
name: apiKeyName || "My API Key" name: apiKeyName || "My API Key"
}); });
@@ -335,6 +323,7 @@ export function ProfileAccount({ user }: ProfileAccountProps) {
</Form> </Form>
</div> </div>
{apiEnabled === true && (
<div className="space-y-6"> <div className="space-y-6">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="space-y-1"> <div className="space-y-1">
@@ -434,6 +423,7 @@ export function ProfileAccount({ user }: ProfileAccountProps) {
)} )}
</div> </div>
</div> </div>
)}
</div> </div>
<Dialog <Dialog
+4
View File
@@ -132,6 +132,8 @@ export const auth = betterAuth({
}, },
}, },
plugins: [ plugins: [
...(env.API_ENABLED
? [
apiKey([ apiKey([
{ {
configId: "public", configId: "public",
@@ -163,6 +165,8 @@ export const auth = betterAuth({
}, },
}, },
]), ]),
]
: []),
sso({ sso({
defaultSSO: oidcProviders.map((p) => ({ defaultSSO: oidcProviders.map((p) => ({
oidcConfig: { oidcConfig: {