perf: add database indexes, implement caching, enforce permission guards, and sanitize external URLs
Build and Push Multi-Platform Images / build-and-push (push) Successful in 48s

This commit is contained in:
2026-05-10 22:01:06 +02:00
parent 351938aa5c
commit aa4c181b0c
14 changed files with 94 additions and 40 deletions
@@ -1,6 +1,5 @@
import { Controller, Get, Param, Post, Put, Delete, UseGuards, UseInterceptors, UploadedFile, Body, Logger, HttpException, HttpStatus, Res, Query } from '@nestjs/common';
import type { Response } from 'express';
import { Public } from '../auth/public.decorator';
import { RequirePermissions } from '../auth/permissions.decorator';
import { Permission } from '../auth/permissions.enum';
@@ -46,7 +45,7 @@ export class PaperlessController {
) {
const params: any = {
page: page || '1',
page_size: pageSize || '20',
page_size: String(Math.min(parseInt(pageSize ?? '20', 10), 500)),
};
if (search) {
params.query = search; // Global search in Paperless
@@ -82,6 +81,7 @@ export class PaperlessController {
}
@Get('users')
@RequirePermissions(Permission.MANAGE_SETTINGS)
async getUsers() {
return this.paperlessService.getUsers();
}
@@ -142,7 +142,7 @@ export class PaperlessController {
}));
}
@Public()
@RequirePermissions(Permission.VIEW_INBOX)
@Get('inbox/preview/:id')
async getInboxPreview(@Param('id') id: string, @Res() res: Response) {
try {
@@ -151,6 +151,7 @@ export class PaperlessController {
'Content-Type': 'image/png',
'Content-Disposition': `inline; filename="${id}preview.png"`,
});
stream.on('error', () => { if (!res.headersSent) res.status(HttpStatus.INTERNAL_SERVER_ERROR).end(); else res.end(); });
stream.pipe(res);
} catch (error) {
if (!res.headersSent) {
@@ -159,7 +160,7 @@ export class PaperlessController {
}
}
@Public()
@RequirePermissions(Permission.VIEW_INBOX)
@Get('inbox/pdf/:id')
async getInboxPdf(@Param('id') id: string, @Res() res: Response) {
try {
@@ -168,6 +169,7 @@ export class PaperlessController {
'Content-Type': 'application/pdf',
'Content-Disposition': `inline; filename="${id}.pdf"`,
});
stream.on('error', () => { if (!res.headersSent) res.status(HttpStatus.INTERNAL_SERVER_ERROR).end(); else res.end(); });
stream.pipe(res);
} catch (error) {
if (!res.headersSent) {
@@ -249,6 +251,7 @@ export class PaperlessController {
}
@Put('inbox/:id')
@RequirePermissions(Permission.VIEW_INBOX)
async putInboxDocument(@Param('id') id: string, @Body() body: any) {
const documentId = parseInt(id, 10);
// Fetch from paperless