optional purgatory, fix mem usage screenshot wall

This commit is contained in:
KingKDot
2026-05-22 09:32:03 -05:00
parent bd47b233d6
commit ce5095ad61
4 changed files with 190 additions and 11 deletions
@@ -1,5 +1,5 @@
import { authenticateRequest } from "../../auth";
import { getConfig } from "../../config";
import { getConfig, updateEnrollmentConfig } from "../../config";
import {
getPendingClients,
getEnrollmentStats,
@@ -114,6 +114,33 @@ export async function handleEnrollmentRoutes(
});
}
// POST /api/enrollment/settings
if (req.method === "POST" && url.pathname === "/api/enrollment/settings") {
const user = await authenticateRequest(req);
if (!user) return new Response("Unauthorized", { status: 401 });
if (user.role !== "admin") return new Response("Forbidden", { status: 403 });
let body: any;
try { body = await req.json(); } catch { return Response.json({ error: "Invalid JSON" }, { status: 400 }); }
if (typeof body?.requireApproval !== "boolean") {
return Response.json({ error: "requireApproval must be a boolean" }, { status: 400 });
}
const updated = await updateEnrollmentConfig({ requireApproval: body.requireApproval });
logAudit({
timestamp: Date.now(),
username: user.username,
ip: "server",
action: AuditAction.ENROLLMENT_SETTINGS,
success: true,
details: JSON.stringify({ requireApproval: body.requireApproval }),
});
return Response.json({ ok: true, requireApproval: updated.requireApproval });
}
// POST /api/enrollment/:id/approve
const approveMatch = url.pathname.match(/^\/api\/enrollment\/([^/]+)\/approve$/);
if (req.method === "POST" && approveMatch) {
+35 -9
View File
@@ -14,17 +14,41 @@ async function getSharp(): Promise<any> {
}
}
const THUMBNAIL_WIDTH = Math.max(64, Number(process.env.OVERLORD_THUMBNAIL_WIDTH || 1920));
const THUMBNAIL_HEIGHT = Math.max(48, Number(process.env.OVERLORD_THUMBNAIL_HEIGHT || 1080));
const THUMBNAIL_WIDTH = Math.max(64, Number(process.env.OVERLORD_THUMBNAIL_WIDTH || 400));
const THUMBNAIL_HEIGHT = Math.max(48, Number(process.env.OVERLORD_THUMBNAIL_HEIGHT || 225));
const THUMBNAIL_QUALITY = Math.min(95, Math.max(40, Number(process.env.OVERLORD_THUMBNAIL_QUALITY || 88)));
const MAX_THUMBNAIL_SOURCE_BYTES = Math.max(
256 * 1024,
Number(process.env.OVERLORD_THUMBNAIL_MAX_SOURCE_BYTES || 16 * 1024 * 1024),
Number(process.env.OVERLORD_THUMBNAIL_MAX_SOURCE_BYTES || 8 * 1024 * 1024),
);
const THUMBNAIL_CACHE_MAX = Math.max(
64,
Number(process.env.OVERLORD_THUMBNAIL_CACHE_MAX || 2000),
);
const MAX_CONCURRENT_THUMBNAIL_GEN = Math.max(
1,
Number(process.env.OVERLORD_THUMBNAIL_CONCURRENCY || 4),
);
let _activeThumbnailGen = 0;
const _thumbnailGenQueue: Array<() => void> = [];
function withThumbnailSlot<T>(fn: () => Promise<T>): Promise<T> {
return new Promise<T>((resolve, reject) => {
const run = () => {
_activeThumbnailGen++;
fn().then(resolve, reject).finally(() => {
_activeThumbnailGen--;
const next = _thumbnailGenQueue.shift();
if (next) next();
});
};
if (_activeThumbnailGen < MAX_CONCURRENT_THUMBNAIL_GEN) {
run();
} else {
_thumbnailGenQueue.push(run);
}
});
}
type ThumbnailRecord = {
bytes: Uint8Array;
@@ -157,12 +181,14 @@ export async function requestThumbnailRegen(id: string): Promise<boolean> {
state.inFlight = true;
let didGenerate = false;
try {
while (true) {
state.pending = false;
const ok = await generateThumbnail(id);
if (ok) didGenerate = true;
if (!state.pending) break;
}
await withThumbnailSlot(async () => {
while (true) {
state!.pending = false;
const ok = await generateThumbnail(id);
if (ok) didGenerate = true;
if (!state!.pending) break;
}
});
} finally {
state.inFlight = false;
if (thumbnailGenState.get(id) === state && !state.pending) {