mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-02 01:20:23 +08:00
fix(admin): address Copilot review findings
- Reflect built-in defaults for boolean settings (ALLOW_PRIVATE_URLS defaults on) and allow clearing a saved boolean back to default, so the SSRF toggle matches actual runtime behavior. - Harden JSON loading: filter settings values to strings only, and schema-validate stored ADMIN_PROVIDERS entries, dropping malformed ones instead of letting them reach runtime code. - Set beforeunload returnValue so the unsaved-changes prompt shows in all browsers; reject non-finite numbers in settings validation. - Fix README/CN/JA docs that claimed the panel auto-generates AI_MODELS_CONFIG (providers are merged at read time, not written). - Add unit tests for corrupted-file value filtering and provider schema validation.
This commit is contained in:
@@ -3,8 +3,10 @@ import os from "os"
|
||||
import path from "path"
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest"
|
||||
import {
|
||||
ADMIN_PROVIDERS_KEY,
|
||||
adminProvidersToConfig,
|
||||
deriveEnvUpdates,
|
||||
loadAdminProviders,
|
||||
mergeSecrets,
|
||||
type StoredAdminProvider,
|
||||
validateAdminProviders,
|
||||
@@ -328,3 +330,38 @@ describe("validateAdminProviders", () => {
|
||||
expect(validateAdminProviders(list)).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe("loadAdminProviders", () => {
|
||||
it("returns [] when nothing is stored", () => {
|
||||
expect(loadAdminProviders()).toEqual([])
|
||||
})
|
||||
|
||||
it("loads valid stored providers", () => {
|
||||
saveSettings({ [ADMIN_PROVIDERS_KEY]: JSON.stringify([provider()]) })
|
||||
expect(loadAdminProviders()).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("drops malformed entries and keeps valid ones", () => {
|
||||
saveSettings({
|
||||
[ADMIN_PROVIDERS_KEY]: JSON.stringify([
|
||||
provider({ id: "good" }),
|
||||
{ id: "missing-fields" }, // no provider/models
|
||||
{ provider: "openai", models: ["x"] }, // no id
|
||||
"not-an-object",
|
||||
]),
|
||||
})
|
||||
const loaded = loadAdminProviders()
|
||||
expect(loaded).toHaveLength(1)
|
||||
expect(loaded[0].id).toBe("good")
|
||||
})
|
||||
|
||||
it("returns [] when the stored value is not an array", () => {
|
||||
saveSettings({ [ADMIN_PROVIDERS_KEY]: JSON.stringify({ nope: true }) })
|
||||
expect(loadAdminProviders()).toEqual([])
|
||||
})
|
||||
|
||||
it("returns [] on invalid JSON", () => {
|
||||
saveSettings({ [ADMIN_PROVIDERS_KEY]: "{ broken" })
|
||||
expect(loadAdminProviders()).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -39,6 +39,31 @@ describe("loadSettings", () => {
|
||||
)
|
||||
expect(loadSettings()).toEqual({ TEST_ADMIN_VAR: "abc" })
|
||||
})
|
||||
|
||||
it("drops non-string values from a corrupted file", () => {
|
||||
fs.writeFileSync(
|
||||
process.env.SETTINGS_FILE!,
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
values: {
|
||||
GOOD: "ok",
|
||||
NUM: 5,
|
||||
OBJ: { nested: true },
|
||||
ARR: [1, 2],
|
||||
NULL: null,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(loadSettings()).toEqual({ GOOD: "ok" })
|
||||
})
|
||||
|
||||
it("returns empty object when values is null or an array", () => {
|
||||
fs.writeFileSync(
|
||||
process.env.SETTINGS_FILE!,
|
||||
JSON.stringify({ version: 1, values: null }),
|
||||
)
|
||||
expect(loadSettings()).toEqual({})
|
||||
})
|
||||
})
|
||||
|
||||
describe("applyToEnv / saveSettings", () => {
|
||||
|
||||
Reference in New Issue
Block a user