mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-02 01:20:23 +08:00
fix(admin): address follow-up Copilot findings on the prior fixes
- loadAdminProviders now validates against a stored-shape schema where
secrets are plain strings, so a hand-edited ADMIN_PROVIDERS holding an
{isSet} marker is dropped instead of later crashing maskSecret().
- loadSettings guards against array values (typeof [] === 'object'),
which would otherwise overlay numeric keys onto process.env.
- Admin SecretInput uses the bare id so the shared component's
<Label htmlFor> stays associated (only one ProviderDetail mounts).
- Add tests: marker-secret rejection, array-values guard, bedrock
multi-secret round-trip.
This commit is contained in:
@@ -45,6 +45,16 @@ export const AdminProviderSchema = z.object({
|
||||
|
||||
export const AdminProvidersSchema = z.array(AdminProviderSchema)
|
||||
|
||||
// Stored shape: secrets are plain strings (never {isSet} markers, which
|
||||
// only exist in transit). Used to validate ADMIN_PROVIDERS on load so a
|
||||
// hand-edited/corrupted value can't slip a marker object past maskSecret.
|
||||
const StoredAdminProviderSchema = AdminProviderSchema.extend({
|
||||
apiKey: z.string().optional(),
|
||||
awsAccessKeyId: z.string().optional(),
|
||||
awsSecretAccessKey: z.string().optional(),
|
||||
vertexApiKey: z.string().optional(),
|
||||
})
|
||||
|
||||
export type AdminProviderInput = z.infer<typeof AdminProviderSchema>
|
||||
|
||||
// Stored form: secrets are plain strings
|
||||
@@ -95,7 +105,7 @@ export function loadAdminProviders(): StoredAdminProvider[] {
|
||||
// Validate each entry's shape — a malformed/hand-edited value must
|
||||
// not reach runtime code that assumes provider/models exist.
|
||||
return parsed.flatMap((entry) => {
|
||||
const result = AdminProviderSchema.safeParse(entry)
|
||||
const result = StoredAdminProviderSchema.safeParse(entry)
|
||||
return result.success ? [result.data as StoredAdminProvider] : []
|
||||
})
|
||||
} catch {
|
||||
|
||||
@@ -33,11 +33,14 @@ export function loadSettings(): Record<string, string> {
|
||||
// hold null/arrays/numbers that would otherwise be overlaid onto
|
||||
// process.env and coerce to junk like "[object Object]".
|
||||
const values: Record<string, string> = {}
|
||||
const raw_values =
|
||||
parsed && typeof parsed.values === "object" && parsed.values
|
||||
const rawValues =
|
||||
parsed &&
|
||||
typeof parsed.values === "object" &&
|
||||
parsed.values &&
|
||||
!Array.isArray(parsed.values)
|
||||
? parsed.values
|
||||
: {}
|
||||
for (const [key, value] of Object.entries(raw_values)) {
|
||||
for (const [key, value] of Object.entries(rawValues)) {
|
||||
if (typeof value === "string") values[key] = value
|
||||
}
|
||||
cachedSettings = values
|
||||
|
||||
Reference in New Issue
Block a user