mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-06 12:41:25 +02:00
add provider specific auth modes
This commit is contained in:
@@ -19,9 +19,7 @@ import config from "@server/lib/config";
|
||||
import { decrypt } from "@server/lib/crypto";
|
||||
import {
|
||||
AiProviderAuthType,
|
||||
AiProviderRoutingMode,
|
||||
AiProviderType,
|
||||
resolveAiProviderConfig
|
||||
applyAiProviderAuthHeaders
|
||||
} from "@server/lib/aiProviderDefaults";
|
||||
import {
|
||||
SESSION_COOKIE_NAME,
|
||||
@@ -499,12 +497,8 @@ export async function chatCompletions(
|
||||
const secret = config.getRawConfig().server.secret!;
|
||||
const apiKey = decrypt(provider.apiKey, secret);
|
||||
|
||||
const { upstreamUrl, authType } = resolveAiProviderConfig({
|
||||
type: provider.type as AiProviderType,
|
||||
upstreamUrl: provider.upstreamUrl,
|
||||
authType: provider.authType as AiProviderAuthType | null,
|
||||
routingMode: provider.routingMode as AiProviderRoutingMode | null
|
||||
});
|
||||
const upstreamUrl = provider.upstreamUrl;
|
||||
const authType = provider.authType as AiProviderAuthType;
|
||||
|
||||
if (!upstreamUrl) {
|
||||
return res.status(HttpCode.INTERNAL_SERVER_ERROR).json({
|
||||
@@ -541,8 +535,7 @@ export async function chatCompletions(
|
||||
}
|
||||
headers[key] = Array.isArray(value) ? value.join(", ") : value;
|
||||
}
|
||||
// TODO: temporary hardcoded auth for testing; restore bearer from authType
|
||||
headers["x-api-key"] = apiKey;
|
||||
applyAiProviderAuthHeaders(headers, authType, apiKey);
|
||||
|
||||
// No dedicated per-request TLS agent is wired up (no extra deps for
|
||||
// this v1 gateway) - toggle the process-wide Node TLS check instead.
|
||||
|
||||
@@ -9,6 +9,7 @@ import { fromError } from "zod-validation-error";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { encrypt } from "@server/lib/crypto";
|
||||
import config from "@server/lib/config";
|
||||
import { resolveAiProviderCreateFields } from "@server/lib/aiProviderDefaults";
|
||||
import type { CreateOrEditAiProviderResponse } from "@server/routers/aiProvider/types";
|
||||
import { toPublicAiProvider } from "@server/routers/aiProvider/types";
|
||||
import {
|
||||
@@ -28,7 +29,7 @@ const bodySchema = z
|
||||
type: aiProviderTypeSchema,
|
||||
upstreamUrl: z.url().optional().nullable(),
|
||||
apiKey: z.string().optional(),
|
||||
authType: aiAuthTypeSchema.optional().nullable(),
|
||||
authType: aiAuthTypeSchema.optional(),
|
||||
routingMode: aiRoutingModeSchema.optional(),
|
||||
skipTlsVerification: z.boolean().optional(),
|
||||
enabled: z.boolean().optional()
|
||||
@@ -101,8 +102,12 @@ export async function createAiProvider(
|
||||
const encryptedApiKey = apiKey ? encrypt(apiKey, key) : null;
|
||||
const apiKeyLastChars = apiKey ? apiKey.slice(-4) : null;
|
||||
const now = Date.now();
|
||||
const resolvedRoutingMode =
|
||||
type === "custom" ? (routingMode ?? "url") : "url";
|
||||
const resolved = resolveAiProviderCreateFields({
|
||||
type,
|
||||
upstreamUrl,
|
||||
authType,
|
||||
routingMode
|
||||
});
|
||||
|
||||
const [provider] = await db
|
||||
.insert(aiProviders)
|
||||
@@ -110,14 +115,11 @@ export async function createAiProvider(
|
||||
orgId,
|
||||
name,
|
||||
type,
|
||||
upstreamUrl:
|
||||
resolvedRoutingMode === "target"
|
||||
? null
|
||||
: (upstreamUrl ?? null),
|
||||
upstreamUrl: resolved.upstreamUrl,
|
||||
apiKey: encryptedApiKey,
|
||||
apiKeyLastChars,
|
||||
authType: authType ?? null,
|
||||
routingMode: resolvedRoutingMode,
|
||||
authType: resolved.authType,
|
||||
routingMode: resolved.routingMode,
|
||||
skipTlsVerification: skipTlsVerification ?? false,
|
||||
enabled: enabled ?? true,
|
||||
createdAt: now,
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import type { AiModel, AiProvider } from "@server/db";
|
||||
import type { PaginatedResponse } from "@server/types/Pagination";
|
||||
import {
|
||||
resolveAiProviderConfig,
|
||||
type AiProviderAuthType,
|
||||
type AiProviderRoutingMode,
|
||||
type AiProviderType
|
||||
} from "@server/lib/aiProviderDefaults";
|
||||
import type { AiProviderAuthType } from "@server/lib/aiProviderDefaults";
|
||||
import { decrypt } from "@server/lib/crypto";
|
||||
import config from "@server/lib/config";
|
||||
|
||||
@@ -13,7 +8,7 @@ export type AiProviderPublic = Omit<AiProvider, "apiKey"> & {
|
||||
/** Decrypted API key. Only included on get/create/update of a single provider. */
|
||||
apiKey?: string | null;
|
||||
effectiveUpstreamUrl: string | null;
|
||||
effectiveAuthType: AiProviderAuthType | null;
|
||||
effectiveAuthType: AiProviderAuthType;
|
||||
};
|
||||
|
||||
export type ListAiProvidersResponse = PaginatedResponse<{
|
||||
@@ -45,12 +40,6 @@ export function toPublicAiProvider(
|
||||
options?: { includeApiKey?: boolean }
|
||||
): AiProviderPublic {
|
||||
const { apiKey: encryptedApiKey, ...rest } = provider;
|
||||
const resolved = resolveAiProviderConfig({
|
||||
type: provider.type as AiProviderType,
|
||||
upstreamUrl: provider.upstreamUrl,
|
||||
authType: provider.authType as AiProviderAuthType | null,
|
||||
routingMode: provider.routingMode as AiProviderRoutingMode | null
|
||||
});
|
||||
|
||||
let apiKey: string | null | undefined;
|
||||
if (options?.includeApiKey) {
|
||||
@@ -67,7 +56,7 @@ export function toPublicAiProvider(
|
||||
return {
|
||||
...rest,
|
||||
...(options?.includeApiKey ? { apiKey } : {}),
|
||||
effectiveUpstreamUrl: resolved.upstreamUrl,
|
||||
effectiveAuthType: resolved.authType
|
||||
effectiveUpstreamUrl: provider.upstreamUrl,
|
||||
effectiveAuthType: provider.authType as AiProviderAuthType
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
refineProviderUpstreamFields
|
||||
} from "@server/routers/aiProvider/validation";
|
||||
import type {
|
||||
AiProviderAuthType,
|
||||
AiProviderRoutingMode,
|
||||
AiProviderType
|
||||
} from "@server/lib/aiProviderDefaults";
|
||||
@@ -31,7 +32,7 @@ const bodySchema = z.strictObject({
|
||||
name: z.string().nonempty().optional(),
|
||||
upstreamUrl: z.url().optional().nullable(),
|
||||
apiKey: z.string().optional(),
|
||||
authType: aiAuthTypeSchema.optional().nullable(),
|
||||
authType: aiAuthTypeSchema.optional(),
|
||||
routingMode: aiRoutingModeSchema.optional(),
|
||||
skipTlsVerification: z.boolean().optional(),
|
||||
enabled: z.boolean().optional()
|
||||
@@ -116,17 +117,16 @@ export async function updateAiProvider(
|
||||
body.upstreamUrl !== undefined
|
||||
? body.upstreamUrl
|
||||
: existing.upstreamUrl;
|
||||
const nextAuthType =
|
||||
const nextAuthType: AiProviderAuthType =
|
||||
body.authType !== undefined
|
||||
? body.authType
|
||||
: (existing.authType ??
|
||||
(providerType === "custom" ? "bearer" : null));
|
||||
: (existing.authType as AiProviderAuthType);
|
||||
|
||||
const validation = z
|
||||
.object({
|
||||
type: aiProviderTypeSchema,
|
||||
upstreamUrl: z.string().nullable().optional(),
|
||||
authType: aiAuthTypeSchema.nullable().optional(),
|
||||
authType: aiAuthTypeSchema,
|
||||
routingMode: aiRoutingModeSchema.optional()
|
||||
})
|
||||
.superRefine((data, ctx) => refineProviderUpstreamFields(data, ctx))
|
||||
@@ -167,13 +167,6 @@ export async function updateAiProvider(
|
||||
}
|
||||
if (body.authType !== undefined) {
|
||||
updateData.authType = body.authType;
|
||||
} else if (
|
||||
providerType === "custom" &&
|
||||
!existing.authType &&
|
||||
nextAuthType
|
||||
) {
|
||||
// Backfill required authType for custom providers created without one
|
||||
updateData.authType = nextAuthType;
|
||||
}
|
||||
|
||||
if (body.apiKey !== undefined) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { z } from "zod";
|
||||
import {
|
||||
AI_PROVIDER_AUTH_TYPES,
|
||||
providerRequiresUpstreamUrl,
|
||||
type AiProviderAuthType,
|
||||
type AiProviderRoutingMode,
|
||||
type AiProviderType
|
||||
} from "@server/lib/aiProviderDefaults";
|
||||
@@ -17,7 +19,7 @@ export const aiProviderTypeSchema = z.enum([
|
||||
"custom"
|
||||
]);
|
||||
|
||||
export const aiAuthTypeSchema = z.enum(["bearer"]);
|
||||
export const aiAuthTypeSchema = z.enum(AI_PROVIDER_AUTH_TYPES);
|
||||
|
||||
export const aiRoutingModeSchema = z.enum(["url", "target"]);
|
||||
|
||||
@@ -25,7 +27,7 @@ export function refineProviderUpstreamFields(
|
||||
data: {
|
||||
type: AiProviderType;
|
||||
upstreamUrl?: string | null;
|
||||
authType?: "bearer" | null;
|
||||
authType?: AiProviderAuthType | null;
|
||||
routingMode?: AiProviderRoutingMode | null;
|
||||
},
|
||||
ctx: z.RefinementCtx
|
||||
|
||||
Reference in New Issue
Block a user