mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: added OPENAPI_ENABLED & API_ENABLED variables
This commit is contained in:
@@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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\/?$/,
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
Reference in New Issue
Block a user