fix: seed anonymous user row in DB and add comprehensive test coverage

When AUTH_ENABLED=false, seed an "anonymous" user row in the users
table so API keys, pipelines, and user files don't fail with FK
constraint violations. Previously, the synthetic anonymous user only
existed in memory (attached by the middleware), but any DB operation
referencing userId "anonymous" would violate foreign key constraints.

Also adds 25 new tests covering:
- Integration: ensureAnonymousUser, FK constraints, settings save,
  API key and pipeline operations for anonymous mode
- Frontend: useAuth hook anonymous happy path (role, permissions,
  hasPermission, session endpoint bypass)
- Frontend: settings dialog nav filtering (authRequired hides
  security/people/teams/roles when auth disabled)
- Backend: session endpoint returns admin role when auth disabled
This commit is contained in:
SnapOtter
2026-05-16 12:36:06 +08:00
parent 0d0fd760e5
commit 4c997f73e0
6 changed files with 552 additions and 3 deletions
+8 -2
View File
@@ -15,7 +15,12 @@ import { buildCsp } from "./lib/csp.js";
import { ensureAiDirs, recoverInterruptedInstalls } from "./lib/feature-status.js";
import { shutdownWorkerPool } from "./lib/worker-pool.js";
import { requirePermission } from "./permissions.js";
import { authMiddleware, authRoutes, ensureDefaultAdmin } from "./plugins/auth.js";
import {
authMiddleware,
authRoutes,
ensureAnonymousUser,
ensureDefaultAdmin,
} from "./plugins/auth.js";
import { oidcRoutes } from "./plugins/oidc.js";
import { registerStatic } from "./plugins/static.js";
import { registerUpload } from "./plugins/upload.js";
@@ -41,9 +46,10 @@ import { userFileRoutes } from "./routes/user-files.js";
runMigrations();
console.log("Database initialized");
// Create default admin user if no users exist and auth is enabled
if (env.AUTH_ENABLED) {
await ensureDefaultAdmin();
} else {
ensureAnonymousUser();
}
function ensureInstanceId() {
+16
View File
@@ -136,6 +136,22 @@ export function createSessionToken(): string {
// ── Default admin creation ─────────────────────────────────────────
export function ensureAnonymousUser(): void {
const existing = db.select().from(schema.users).where(eq(schema.users.id, "anonymous")).get();
if (existing) return;
db.insert(schema.users)
.values({
id: "anonymous",
username: "anonymous",
role: "admin",
mustChangePassword: false,
authProvider: "local",
})
.onConflictDoNothing()
.run();
}
export async function ensureDefaultAdmin(): Promise<void> {
const existingUsers = db.select().from(schema.users).all();
if (existingUsers.length > 0) return;