fix: resolve all ESLint errors in backend and frontend

Backend 958→0 errors, frontend 98→0 errors. Builds and tsc clean.

Echte Fixes:
- Auth: AuthenticatedUser/AuthenticatedRequest, JwtStrategy + alle 5
  Controller von `@Request() req: any` auf typisierten Request umgestellt
- Error-Handling: neuer getErrorMessage/Stack/Code/getResponseData-Helper;
  alle 50 `catch (err: any)`-Blöcke auf `unknown` + Helper umgestellt
- 24 echte Bugs: require-await, require-imports→ES-Imports, useless-escape,
  misused-promises, tote Imports/Vars, leere catch-Blöcke kommentiert
- document-pipeline: OCR-Ergebnis wird nicht gespeichert (als TODO markiert)

Pragmatisch auf warn herabgestuft (untypisierte Paperless-NGX-API):
no-unsafe-*, restrict-template-expressions, no-base-to-string,
no-explicit-any (FE), react-refresh/only-export-components

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 21:33:37 +02:00
parent d96e06e86d
commit 07dfd7e840
43 changed files with 399 additions and 204 deletions
+21 -16
View File
@@ -21,6 +21,8 @@ import { BarcodeScannerService } from '../barcode/barcode-scanner.service';
import { UserSettingsService } from '../user-settings/user-settings.service';
import { RequirePermissions } from '../auth/permissions.decorator';
import { Permission } from '../auth/permissions.enum';
import type { AuthenticatedRequest } from '../auth/authenticated-request';
import type { InboxSource } from '../database/entities/inbox-document.entity';
@Controller('api/inbox')
@RequirePermissions(Permission.VIEW_SCANNER)
@@ -33,7 +35,7 @@ export class InboxController {
) {}
@Get()
async list(@Request() req: any) {
async list(@Request() req: AuthenticatedRequest) {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
return this.inboxService.listFiles(preferredUsername);
@@ -47,7 +49,7 @@ export class InboxController {
@Get(':id/preview')
async preview(
@Param('id') id: string,
@Request() req: any,
@Request() req: AuthenticatedRequest,
@Res({ passthrough: true }) res: Response,
): Promise<StreamableFile> {
const preferredUsername: string | null =
@@ -69,7 +71,7 @@ export class InboxController {
async pageThumbnail(
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Request() req: any,
@Request() req: AuthenticatedRequest,
@Res({ passthrough: true }) res: Response,
): Promise<StreamableFile> {
const preferredUsername: string | null =
@@ -88,7 +90,10 @@ export class InboxController {
@Delete(':id')
@HttpCode(204)
async remove(@Param('id') id: string, @Request() req: any): Promise<void> {
async remove(
@Param('id') id: string,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
await this.inboxService.deleteDocument(id, preferredUsername);
@@ -99,7 +104,7 @@ export class InboxController {
async removePage(
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
@@ -111,7 +116,7 @@ export class InboxController {
async toggleManualSplit(
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
@@ -122,7 +127,7 @@ export class InboxController {
@HttpCode(204)
async resetEdits(
@Param('id') id: string,
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
@@ -132,7 +137,7 @@ export class InboxController {
@Post(':id/postprocess')
async postprocess(
@Param('id') id: string,
@Request() req: any,
@Request() req: AuthenticatedRequest,
@Body()
body: {
sectionOffset?: number;
@@ -158,7 +163,7 @@ export class InboxController {
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Body() body: { rotation?: number },
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const rotation = Number(body?.rotation);
if (!Number.isFinite(rotation)) {
@@ -178,7 +183,7 @@ export class InboxController {
async pagePreview(
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Request() req: any,
@Request() req: AuthenticatedRequest,
@Res({ passthrough: true }) res: Response,
): Promise<StreamableFile> {
const preferredUsername: string | null =
@@ -200,7 +205,7 @@ export class InboxController {
@Param('id') id: string,
@Param('page', ParseIntPipe) page: number,
@Body() body: { x: number; y: number; w: number; h: number },
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<{ found: string[] }> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
@@ -219,8 +224,8 @@ export class InboxController {
@HttpCode(204)
async updateSource(
@Param('id') id: string,
@Body() body: { source: any },
@Request() req: any,
@Body() body: { source: InboxSource },
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
@@ -231,7 +236,7 @@ export class InboxController {
async downloadSegment(
@Param('id') id: string,
@Body() body: { pages: number[] },
@Request() req: any,
@Request() req: AuthenticatedRequest,
@Res({ passthrough: true }) res: Response,
): Promise<StreamableFile> {
const preferredUsername: string | null =
@@ -263,13 +268,13 @@ export class InboxController {
segments: { pages: number[]; filename: string }[];
sender?: string;
},
@Request() req: any,
@Request() req: AuthenticatedRequest,
): Promise<void> {
const preferredUsername: string | null =
req.user?.preferredUsername ?? null;
const smtpOverride =
body.sender === 'user'
? await this.userSettingsService.getSmtpConfig(req.user.userId)
? await this.userSettingsService.getSmtpConfig(req.user!.userId)
: null;
await this.inboxService.sendAsEmail(id, preferredUsername, {
...body,