From 1ed3afd2e20cf05ff954c82f623200d216cbe442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20P=C3=B6ttker?= Date: Sun, 10 May 2026 22:21:01 +0200 Subject: [PATCH] feat: add database indexes, implement CORS configuration, and lazy-load frontend routes --- .env.example | 6 ++ .../src/database/entities/email.entity.ts | 4 +- .../entities/label-print-job.entity.ts | 3 + .../src/database/entities/task.entity.ts | 4 +- paperless-backend/src/main.ts | 2 +- paperless-frontend/src/App.tsx | 68 ++++++++++--------- 6 files changed, 52 insertions(+), 35 deletions(-) diff --git a/.env.example b/.env.example index 3f16301..54a1a9f 100644 --- a/.env.example +++ b/.env.example @@ -44,3 +44,9 @@ VITE_API_URL= # Platzhalter {Jahr} wird zur Laufzeit durch das Jahr des Eingangsdatums ersetzt BELEGNUMMER_GET_URL=https://beispiel-api.de/get-number/{Jahr} BELEGNUMMER_SET_URL=https://beispiel-api.de/set-number/{Jahr}/{Nummer} + +# --- CORS --- +# Erlaubte Frontend-Origin für CORS. In Produktion PFLICHT (z.B. https://paperless.example.com). +# Leer lassen für lokale Entwicklung (erlaubt alle Origins). +# NODE_ENV=production ohne CORS_ORIGIN blockiert alle Cross-Origin-Anfragen. +CORS_ORIGIN= diff --git a/paperless-backend/src/database/entities/email.entity.ts b/paperless-backend/src/database/entities/email.entity.ts index 85dde38..ce061dd 100644 --- a/paperless-backend/src/database/entities/email.entity.ts +++ b/paperless-backend/src/database/entities/email.entity.ts @@ -1,4 +1,4 @@ -import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'; +import { Entity, PrimaryGeneratedColumn, Column, Index, OneToMany } from 'typeorm'; import { Attachment } from './attachment.entity'; @Entity('Emails') @@ -18,12 +18,14 @@ export class Email { @Column({ type: 'varchar', length: 500 }) Subject!: string; + @Index() @Column({ type: 'datetime' }) Date!: Date; @Column({ type: 'longtext' }) Body!: string; + @Index() @Column({ type: 'int', default: 0 }) Status!: number; diff --git a/paperless-backend/src/database/entities/label-print-job.entity.ts b/paperless-backend/src/database/entities/label-print-job.entity.ts index 95af2fc..5d5fdee 100644 --- a/paperless-backend/src/database/entities/label-print-job.entity.ts +++ b/paperless-backend/src/database/entities/label-print-job.entity.ts @@ -2,6 +2,7 @@ import { Entity, PrimaryGeneratedColumn, Column, + Index, CreateDateColumn, } from 'typeorm'; @@ -10,6 +11,7 @@ export class LabelPrintJob { @PrimaryGeneratedColumn() Id!: number; + @Index() @Column({ type: 'varchar', length: 20, default: 'pending' }) Status!: 'pending' | 'printed' | 'error'; @@ -28,6 +30,7 @@ export class LabelPrintJob { @Column({ type: 'simple-json', nullable: true }) LabelVariables!: Record | null; + @Index() @Column({ type: 'datetime', nullable: true }) LockedAt!: Date | null; diff --git a/paperless-backend/src/database/entities/task.entity.ts b/paperless-backend/src/database/entities/task.entity.ts index bb151aa..8f7e775 100644 --- a/paperless-backend/src/database/entities/task.entity.ts +++ b/paperless-backend/src/database/entities/task.entity.ts @@ -1,10 +1,11 @@ -import { Entity, PrimaryColumn, Column } from 'typeorm'; +import { Entity, PrimaryColumn, Column, Index } from 'typeorm'; @Entity('tasks') export class Task { @PrimaryColumn({ type: 'varchar', length: 36 }) TaskId!: string; + @Index() @Column({ type: 'varchar', length: 50 }) InterneBelegnummer!: string; @@ -14,6 +15,7 @@ export class Task { @Column({ type: 'datetime', nullable: true }) Eingangsdatum!: Date | null; + @Index() @Column({ type: 'tinyint', nullable: true }) Fertig!: number | null; diff --git a/paperless-backend/src/main.ts b/paperless-backend/src/main.ts index f510fe9..57e4274 100644 --- a/paperless-backend/src/main.ts +++ b/paperless-backend/src/main.ts @@ -7,7 +7,7 @@ async function bootstrap(): Promise { const port = process.env.PORT ?? 3100; app.enableCors({ - origin: '*', // Für lokale Entwicklung zulassen, oder spezifisch: 'http://localhost:8080' + origin: process.env.CORS_ORIGIN ?? (process.env.NODE_ENV === 'production' ? false : '*'), methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS', credentials: true, }); diff --git a/paperless-frontend/src/App.tsx b/paperless-frontend/src/App.tsx index 19bf781..b3320eb 100644 --- a/paperless-frontend/src/App.tsx +++ b/paperless-frontend/src/App.tsx @@ -1,3 +1,4 @@ +import { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom'; import { ConfigProvider, theme, App as AntdApp } from 'antd'; import deDE from 'antd/locale/de_DE'; @@ -6,18 +7,19 @@ import { saveReturnUrl } from './auth/sessionRedirect'; import { ThemeProvider, useTheme } from './theme/ThemeContext'; import AuthCallback from './auth/AuthCallback'; import AppLayout from './layouts/AppLayout'; -import InboxPage from './pages/InboxPage'; -import InboxDetailPage from './pages/InboxDetailPage'; -import PosteingangPage from './pages/PosteingangPage'; -import ManuellBearbeitenPage from './pages/ManuellBearbeitenPage'; -import MailpostfachPage from './pages/MailpostfachPage'; -import MailDetailPage from './pages/MailDetailPage'; -import SettingsPage from './pages/SettingsPage'; -import UserSettingsPage from './pages/UserSettingsPage'; -import LoginPage from './pages/LoginPage'; -import DashboardPage from './pages/DashboardPage'; import { Spin, Result, Button } from 'antd'; import type { ReactNode } from 'react'; + +const InboxPage = lazy(() => import('./pages/InboxPage')); +const InboxDetailPage = lazy(() => import('./pages/InboxDetailPage')); +const PosteingangPage = lazy(() => import('./pages/PosteingangPage')); +const ManuellBearbeitenPage = lazy(() => import('./pages/ManuellBearbeitenPage')); +const MailpostfachPage = lazy(() => import('./pages/MailpostfachPage')); +const MailDetailPage = lazy(() => import('./pages/MailDetailPage')); +const SettingsPage = lazy(() => import('./pages/SettingsPage')); +const UserSettingsPage = lazy(() => import('./pages/UserSettingsPage')); +const LoginPage = lazy(() => import('./pages/LoginPage')); +const DashboardPage = lazy(() => import('./pages/DashboardPage')); import { Permission } from './auth/permissions'; function UnauthorizedPage() { @@ -109,28 +111,30 @@ function ThemedApp() { - - } /> - } /> - - - - } - > - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - + }> + + } /> + } /> + + + + } + > + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + +