refactor and limits change

This commit is contained in:
Gamosoft 2026-04-21 18:00:50 +02:00
parent 7edbc28a9c
commit 82cdd12d19
2 changed files with 58 additions and 33 deletions

View File

@ -626,7 +626,7 @@ async def get_media(media_path: str):
@api_router.put("/media/{media_path:path}", tags=["Media"]) @api_router.put("/media/{media_path:path}", tags=["Media"])
@limiter.limit("30/minute") @limiter.limit("120/minute")
async def put_media(media_path: str, request: Request): async def put_media(media_path: str, request: Request):
""" """
Overwrite an existing media file in place (used for saving drawing PNGs). Overwrite an existing media file in place (used for saving drawing PNGs).
@ -662,6 +662,10 @@ async def put_media(media_path: str, request: Request):
detail=f"File too large. Maximum size: {UPLOAD_MAX_IMAGE_MB}MB", detail=f"File too large. Maximum size: {UPLOAD_MAX_IMAGE_MB}MB",
) )
# Reject non-PNG payloads (defense in depth; path already restricts to .png)
if len(body) < 8 or body[:8] != b"\x89PNG\r\n\x1a\n":
raise HTTPException(status_code=400, detail="Body must be a valid PNG image")
try: try:
with open(full_path, 'wb') as f: with open(full_path, 'wb') as f:
f.write(body) f.write(body)

View File

@ -508,6 +508,10 @@ function noteApp() {
drawingIsPointerDown: false, drawingIsPointerDown: false,
/** True after the PNG from disk has been decoded into _drawingBaseImage; false after Clear. */ /** True after the PNG from disk has been decoded into _drawingBaseImage; false after Clear. */
drawingHasRasterFromFile: false, drawingHasRasterFromFile: false,
/** Prevents overlapping drawingSave() runs (Ctrl+S + autosave + fast retries). */
_drawingSaveInFlight: false,
/** If true, run drawingSave again after the current one finishes (coalesce). */
_drawingSaveQueued: false,
_drawingAutosaveTimeout: null, _drawingAutosaveTimeout: null,
// DOM element cache (to avoid repeated querySelector calls) // DOM element cache (to avoid repeated querySelector calls)
@ -3268,6 +3272,12 @@ function noteApp() {
*/ */
async drawingSave() { async drawingSave() {
if (!this.currentMedia || this.currentMediaType !== 'drawing') return; if (!this.currentMedia || this.currentMediaType !== 'drawing') return;
if (this._drawingSaveInFlight) {
this._drawingSaveQueued = true;
return;
}
this._drawingSaveInFlight = true;
try {
this._drawingCancelAutosave(); this._drawingCancelAutosave();
const canvas = this._drawingCanvasEl; const canvas = this._drawingCanvasEl;
const ctx = this._drawingCtx; const ctx = this._drawingCtx;
@ -3306,6 +3316,17 @@ function noteApp() {
} finally { } finally {
this.isSaving = false; this.isSaving = false;
} }
} finally {
this._drawingSaveInFlight = false;
if (this._drawingSaveQueued) {
this._drawingSaveQueued = false;
queueMicrotask(() => {
if (this.currentMedia && this.currentMediaType === 'drawing') {
this.drawingSave();
}
});
}
}
}, },
// Handle clicks on internal links in preview // Handle clicks on internal links in preview