mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 05:12:16 +03:00
fix(dashboard): encode chatgpt-session credentials with the shared predicate
Both connection modals wrapped the pasted Cookie header in the {version, cookie,
runtimeKey} envelope only when provider === "chatgpt-web-codex", but the create and
update routes send every provider accepted by usesChatGptBrowserSessionCredentials()
through finalizeValidatedChatGptWebCodexSecrets, whose first statement is JSON.parse. A
chatgpt-session save therefore always failed with 400 "Unexpected token '_',
"__Secure-n"... is not valid JSON" — the dashboard could never create or update a
connection.
Both modals now key the envelope off the same predicate the routes use, so client and
server cannot drift again, and omit runtimeKey when empty (this provider never has one).
The two failure paths returned error.message raw, echoing the first characters of the
pasted credential; they now go through sanitizeErrorMessage, and their untranslated
German fallback is replaced with provider-neutral English.
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Button, Badge, Input, Modal, Toggle, TALL_MODAL_PROPS } from "@/shared/components";
|
||||
import { CHATGPT_WEB_CODEX_CONNECTOR_NAME } from "@/shared/constants/chatgptWebCodex";
|
||||
import {
|
||||
CHATGPT_WEB_CODEX_CONNECTOR_NAME,
|
||||
usesChatGptBrowserSessionCredentials,
|
||||
} from "@/shared/constants/chatgptWebCodex";
|
||||
import {
|
||||
providerAllowsOptionalApiKey,
|
||||
supportsBulkApiKey,
|
||||
@@ -97,6 +100,12 @@ export default function AddApiKeyModal({
|
||||
const isLocalSelfHostedProvider = !!localProviderMetadata;
|
||||
const isGooglePse = provider === "google-pse-search";
|
||||
const isChatGptWebCodex = provider === "chatgpt-web-codex";
|
||||
// The credential ENVELOPE is decided by the shared browser-session lifecycle predicate,
|
||||
// not by the codex id: `/api/providers` routes every provider this predicate accepts into
|
||||
// `finalizeValidatedChatGptWebCodexSecrets`, which starts with `JSON.parse`. Posting a raw
|
||||
// cookie for one of them fails the save with a JSON parse error, so client and server must
|
||||
// read the same predicate.
|
||||
const usesBrowserSessionCredential = usesChatGptBrowserSessionCredentials(provider);
|
||||
const isAwsPolly = provider === "aws-polly";
|
||||
const webSessionCredential = getWebSessionCredentialRequirement(provider);
|
||||
const isNoAuthWebSessionCredential = webSessionCredential?.kind === "none";
|
||||
@@ -402,11 +411,12 @@ export default function AddApiKeyModal({
|
||||
...(validatedProviderSpecificData || {}),
|
||||
};
|
||||
|
||||
const encodedCredential = isChatGptWebCodex
|
||||
const encodedCredential = usesBrowserSessionCredential
|
||||
? JSON.stringify({
|
||||
version: 1,
|
||||
cookie: credentialInput.trim().replace(/^cookie\s*:\s*/i, ""),
|
||||
runtimeKey: formData.runtimeKey.trim(),
|
||||
// Only chatgpt-web-codex ever has a runtime key; omit the field entirely otherwise.
|
||||
...(formData.runtimeKey.trim() ? { runtimeKey: formData.runtimeKey.trim() } : {}),
|
||||
})
|
||||
: credentialInput.trim();
|
||||
const payload = {
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { Button, Badge, Input, Modal, Toggle, Select } from "@/shared/components";
|
||||
import { CHATGPT_WEB_CODEX_CONNECTOR_NAME } from "@/shared/constants/chatgptWebCodex";
|
||||
import {
|
||||
CHATGPT_WEB_CODEX_CONNECTOR_NAME,
|
||||
usesChatGptBrowserSessionCredentials,
|
||||
} from "@/shared/constants/chatgptWebCodex";
|
||||
import {
|
||||
isOpenAICompatibleProvider,
|
||||
isAnthropicCompatibleProvider,
|
||||
@@ -230,6 +233,11 @@ export default function EditConnectionModal({
|
||||
const isLocalSelfHostedProvider = !!localProviderMetadata;
|
||||
const isGooglePse = provider === "google-pse-search";
|
||||
const isChatGptWebCodex = provider === "chatgpt-web-codex";
|
||||
// The credential ENVELOPE is decided by the shared browser-session lifecycle predicate,
|
||||
// not by the codex id: `/api/providers/[id]` routes every provider this predicate accepts
|
||||
// into `decodeChatGptWebCodexSecrets` + `finalizeValidatedChatGptWebCodexSecrets`, both of
|
||||
// which expect the JSON envelope. Client and server must read the same predicate.
|
||||
const usesBrowserSessionCredential = usesChatGptBrowserSessionCredentials(provider);
|
||||
const isAwsPolly = provider === "aws-polly";
|
||||
const isM365TierCapable = isM365TierCapableProvider(provider);
|
||||
const webSessionCredential = getWebSessionCredentialRequirement(provider);
|
||||
@@ -648,7 +656,7 @@ export default function EditConnectionModal({
|
||||
}
|
||||
}
|
||||
if (isValid) {
|
||||
updates.apiKey = isChatGptWebCodex
|
||||
updates.apiKey = usesBrowserSessionCredential
|
||||
? JSON.stringify({
|
||||
version: 1,
|
||||
cookie: formData.apiKey.trim().replace(/^cookie\s*:\s*/i, ""),
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
decodeChatGptWebCodexSecrets,
|
||||
encodeChatGptWebCodexSecrets,
|
||||
} from "@omniroute/open-sse/services/chatgptWebCodexAdmin.ts";
|
||||
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error.ts";
|
||||
import { rejectRetiredCommonChatGptWebProvider } from "@/lib/providers/chatgptWebRetirementResponse";
|
||||
import { usesChatGptBrowserSessionCredentials } from "@/shared/constants/chatgptWebCodex";
|
||||
|
||||
@@ -192,10 +193,11 @@ export async function PUT(request: Request, { params }: { params: Promise<{ id:
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error: sanitizeErrorMessage(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Die ChatGPT-Browserprüfung konnte nicht abgeschlossen werden.",
|
||||
: "The browser session verification could not be completed."
|
||||
),
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
|
||||
@@ -48,6 +48,7 @@ import {
|
||||
getModelSyncInternalBaseUrl,
|
||||
} from "@/shared/services/modelSyncScheduler";
|
||||
import { finalizeValidatedChatGptWebCodexSecrets } from "@omniroute/open-sse/services/chatgptWebCodexAdmin.ts";
|
||||
import { sanitizeErrorMessage } from "@omniroute/open-sse/utils/error.ts";
|
||||
import { usesChatGptBrowserSessionCredentials } from "@/shared/constants/chatgptWebCodex";
|
||||
import { isAutoFetchModelsEnabled } from "@/lib/providerModels/modelDiscovery";
|
||||
import { testSingleConnection } from "./[id]/test/route";
|
||||
@@ -212,10 +213,11 @@ export async function POST(request: Request) {
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
error: sanitizeErrorMessage(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Die ChatGPT-Browserprüfung konnte nicht abgeschlossen werden.",
|
||||
: "The browser session verification could not be completed."
|
||||
),
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user