feat: add OIDC/SSO authentication (#3)

Add OpenID Connect (OIDC) authentication alongside existing
username/password login. Users can log in via any standards-compliant
OIDC provider (Keycloak, Authentik, Authelia, Google, Azure AD, Okta)
while preserving full backward compatibility.

- OIDC Fastify plugin with lazy discovery, PKCE, cookie-based sessions
- Login page OIDC button, auth hook updates, settings dialog badges
- 28 integration tests, OIDC setup guide with provider examples
- Fix pre-existing test failures (content-aware-crop, watermark, SVGZ)
- WAL checkpoint fix for SQLite test stability

Closes #3

# Conflicts:
#	apps/api/src/lib/env.ts
#	apps/api/src/routes/tools/watermark-image.ts
#	pnpm-lock.yaml
#	tests/integration/color-palette.test.ts
#	tests/integration/compare.test.ts
#	tests/integration/watermark-image.test.ts
This commit is contained in:
SnapOtter
2026-05-14 22:31:26 +08:00
32 changed files with 3503 additions and 149 deletions
+3 -3
View File
@@ -23,7 +23,7 @@ export function registerWatermarkImage(app: FastifyInstance) {
let mainBuffer: Buffer | null = null;
let watermarkBuffer: Buffer | null = null;
let filename = "image";
let wmFilename = "watermark";
let watermarkFilename = "watermark";
let settingsRaw: string | null = null;
try {
@@ -37,7 +37,7 @@ export function registerWatermarkImage(app: FastifyInstance) {
const buf = Buffer.concat(chunks);
if (part.fieldname === "watermark") {
watermarkBuffer = buf;
wmFilename = sanitizeFilename(part.filename ?? "watermark");
watermarkFilename = sanitizeFilename(part.filename ?? "watermark");
} else {
mainBuffer = buf;
filename = sanitizeFilename(part.filename ?? "image");
@@ -119,7 +119,7 @@ export function registerWatermarkImage(app: FastifyInstance) {
}
mainBuffer = await autoOrient(mainBuffer);
const valWm = await validateImageBuffer(watermarkBuffer, wmFilename);
const valWm = await validateImageBuffer(watermarkBuffer, watermarkFilename);
if (!valWm.valid) {
return reply.status(400).send({ error: `Invalid watermark image: ${valWm.reason}` });
}