diff --git a/app/api/chat-stream/route.ts b/app/api/chat-stream/route.ts index 16c5950c..8803a425 100644 --- a/app/api/chat-stream/route.ts +++ b/app/api/chat-stream/route.ts @@ -2,19 +2,25 @@ import type { ChatRequest } from "../chat/typing"; import { createParser } from "eventsource-parser"; import { NextRequest } from "next/server"; -const apiKey = process.env.OPENAI_API_KEY; - -async function createStream(payload: ReadableStream) { +async function createStream(req: NextRequest) { const encoder = new TextEncoder(); const decoder = new TextDecoder(); + let apiKey = process.env.OPENAI_API_KEY; + + const userApiKey = req.headers.get("token"); + if (userApiKey) { + apiKey = userApiKey; + console.log("[Stream] using user api key"); + } + const res = await fetch("https://api.openai.com/v1/chat/completions", { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, method: "POST", - body: payload, + body: req.body, }); const stream = new ReadableStream({ @@ -49,7 +55,7 @@ async function createStream(payload: ReadableStream) { export async function POST(req: NextRequest) { try { - const stream = await createStream(req.body!); + const stream = await createStream(req); return new Response(stream); } catch (error) { console.error("[Chat Stream]", error); diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index c4e41ca3..18c7db14 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -1,23 +1,26 @@ import { OpenAIApi, Configuration } from "openai"; import { ChatRequest } from "./typing"; -const apiKey = process.env.OPENAI_API_KEY; - -const openai = new OpenAIApi( - new Configuration({ - apiKey, - }) -); - export async function POST(req: Request) { try { - const requestBody = (await req.json()) as ChatRequest; - const completion = await openai!.createChatCompletion( - { - ...requestBody, - } + let apiKey = process.env.OPENAI_API_KEY; + + const userApiKey = req.headers.get("token"); + if (userApiKey) { + apiKey = userApiKey; + } + + const openai = new OpenAIApi( + new Configuration({ + apiKey, + }) ); + const requestBody = (await req.json()) as ChatRequest; + const completion = await openai!.createChatCompletion({ + ...requestBody, + }); + return new Response(JSON.stringify(completion.data)); } catch (e) { console.error("[Chat] ", e); diff --git a/app/components/settings.tsx b/app/components/settings.tsx index a0a477af..56165daa 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -257,6 +257,20 @@ export function Settings(props: { closeSettings: () => void }) { <> )} + + { + accessStore.updateToken(e.currentTarget.value); + }} + > + + 0) { + headers["token"] = accessStore.token; + } + return headers; } diff --git a/app/store/access.ts b/app/store/access.ts index 4ec2111c..9c61dfa0 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -4,7 +4,9 @@ import { queryMeta } from "../utils"; export interface AccessControlStore { accessCode: string; + token: string; + updateToken: (_: string) => void; updateCode: (_: string) => void; enabledAccessControl: () => boolean; } @@ -14,6 +16,7 @@ export const ACCESS_KEY = "access-control"; export const useAccessStore = create()( persist( (set, get) => ({ + token: "", accessCode: "", enabledAccessControl() { return queryMeta("access") === "enabled"; @@ -21,6 +24,9 @@ export const useAccessStore = create()( updateCode(code: string) { set((state) => ({ accessCode: code })); }, + updateToken(token: string) { + set((state) => ({ token })); + }, }), { name: ACCESS_KEY, diff --git a/middleware.ts b/middleware.ts index 0ab3a101..7e671ff1 100644 --- a/middleware.ts +++ b/middleware.ts @@ -8,13 +8,14 @@ export const config = { export function middleware(req: NextRequest, res: NextResponse) { const accessCode = req.headers.get("access-code"); + const token = req.headers.get("token"); const hashedCode = md5.hash(accessCode ?? "").trim(); console.log("[Auth] allowed hashed codes: ", [...ACCESS_CODES]); console.log("[Auth] got access code:", accessCode); console.log("[Auth] hashed access code:", hashedCode); - if (ACCESS_CODES.size > 0 && !ACCESS_CODES.has(hashedCode)) { + if (ACCESS_CODES.size > 0 && !ACCESS_CODES.has(hashedCode) && !token) { return NextResponse.json( { needAccessCode: true,