chore: add project documentation, restrict email import permissions, and set date format in InboxPage
Build and Push Multi-Platform Images / build-and-push (push) Successful in 32s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 32s
This commit is contained in:
@@ -0,0 +1,134 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Paperless Manager is a document automation platform that extends [Paperless-NGX](https://github.com/paperless-ngx/paperless-ngx). It provides:
|
||||||
|
- Scanner inbox management with PDF processing (splitting, rotation, barcode detection)
|
||||||
|
- Email import with attachment extraction
|
||||||
|
- Rule-based postprocessing (tag, export, send mail)
|
||||||
|
- OCR via Ollama (vision model)
|
||||||
|
- Label printing agent with SSE-based job queue
|
||||||
|
|
||||||
|
UI labels and comments are in **German**.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
paperless-backend/ # NestJS API (port 3100)
|
||||||
|
paperless-frontend/ # React 19 + Ant Design + Vite
|
||||||
|
docker-compose.yml # Production (backend + frontend/nginx + MySQL)
|
||||||
|
.env.example # All required environment variables
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
**Backend** (in `paperless-backend/`):
|
||||||
|
```bash
|
||||||
|
npm run start:dev # Dev server with watch mode
|
||||||
|
npm run build # Compile TypeScript
|
||||||
|
npm run test # Jest unit tests
|
||||||
|
npm run test:e2e # End-to-end tests
|
||||||
|
npm run lint # ESLint with auto-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
**Frontend** (in `paperless-frontend/`):
|
||||||
|
```bash
|
||||||
|
npm run dev # Vite dev server (proxies /api to backend)
|
||||||
|
npm run build # TypeScript check + Vite build
|
||||||
|
npm run lint # ESLint
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backend Architecture
|
||||||
|
|
||||||
|
### Module Overview
|
||||||
|
|
||||||
|
| Module | Purpose |
|
||||||
|
|--------|---------|
|
||||||
|
| `auth` | JWT (OIDC/Authentik) + API Key guards, permission system |
|
||||||
|
| `database` | TypeORM entities + MySQL config (synchronize: true) |
|
||||||
|
| `inbox` | Scanner document management (list, preview, rotate, split) |
|
||||||
|
| `paperless` | Paperless-NGX REST API client |
|
||||||
|
| `preprocessing` | PDF→images, OCR, QR extraction, task creation |
|
||||||
|
| `postprocessing` | Rule engine: filter conditions → actions |
|
||||||
|
| `email` | IMAP intake, PDF conversion, correspondent mapping |
|
||||||
|
| `email-download` | External email retrieval, ZUGFeRD invoice parsing |
|
||||||
|
| `barcode` | QR/barcode detection, template-based split actions |
|
||||||
|
| `label-print-agent` | SVG label rendering, RxJS-based print job queue + SSE |
|
||||||
|
| `inbox-postprocessor` | Applies edits/splits to PDFs, variable substitution |
|
||||||
|
| `scanner` | chokidar file system watcher for scan directory |
|
||||||
|
| `settings` | Global configuration |
|
||||||
|
| `user-settings` | Per-user SMTP and preferences |
|
||||||
|
|
||||||
|
### Authentication & Permissions
|
||||||
|
|
||||||
|
Global guards apply to all routes:
|
||||||
|
1. `JwtOrApiKeyGuard` — validates Bearer JWT (OIDC) or `X-API-Key` header
|
||||||
|
2. `PermissionsGuard` — enforces `@RequirePermissions()` decorator
|
||||||
|
|
||||||
|
Decorate controllers/handlers with:
|
||||||
|
```typescript
|
||||||
|
@RequirePermissions(Permission.VIEW_SCANNER)
|
||||||
|
```
|
||||||
|
|
||||||
|
Permissions map from OIDC groups (`PM_Admin`, `PM_Belege`, etc.) to the `Permission` enum in `src/auth/permissions.enum.ts`.
|
||||||
|
|
||||||
|
Use `@Public()` to bypass auth guards entirely.
|
||||||
|
|
||||||
|
### Database
|
||||||
|
|
||||||
|
- TypeORM with MySQL 8+, UTF8MB4, `synchronize: true` (schema auto-migrates)
|
||||||
|
- 23 entities in `src/database/entities/`
|
||||||
|
- JSON columns use transformers to normalize empty arrays/objects to `null`
|
||||||
|
- Key entities: `InboxDocument`, `Task`, `Email`, `Attachment`, `Postprocessing`, `BarcodeTemplate`, `LabelPrintJob`, `ApiKey`, `Setting`
|
||||||
|
|
||||||
|
### Document Processing Pipeline
|
||||||
|
|
||||||
|
**Preprocessing** (`preprocessing/document-pipeline.service.ts`):
|
||||||
|
1. PDF → PNG page images (200 DPI via pdf-lib + sharp)
|
||||||
|
2. QR code extraction from page 1 (jsqr)
|
||||||
|
3. OCR via Ollama (llava vision model)
|
||||||
|
4. Auto-generated internal document number (YYYY-000001)
|
||||||
|
5. DB task entry creation, archive original (GoBD compliance)
|
||||||
|
|
||||||
|
**Postprocessing** (`postprocessing/postprocessing.service.ts`):
|
||||||
|
1. Load rules ordered by priority with filter conditions (JSON)
|
||||||
|
2. Evaluate filters (field operators: eq, contains, in, etc.)
|
||||||
|
3. Execute actions: tag, update field, send mail, export WebDAV
|
||||||
|
4. Log results; apply error tag on failure; stop if `NoFurther` flag set
|
||||||
|
|
||||||
|
**Inbox Postprocessor** (`inbox-postprocessor/`):
|
||||||
|
- Applies virtual edits (page deletions, rotations, splits) stored in DB to original PDF
|
||||||
|
- Resolves variable templates from barcode/task data
|
||||||
|
- Returns PDF buffer for upload to Paperless-NGX
|
||||||
|
|
||||||
|
### Label Print Agent
|
||||||
|
|
||||||
|
- Uses RxJS `Subject` (`newJob$`) to stream print jobs via SSE to connected agents
|
||||||
|
- Jobs are locked for 5 minutes to prevent race conditions
|
||||||
|
- SVG templates rendered to PNG via `@resvg/resvg-js`
|
||||||
|
- API documented in `docs/BACKEND_API.md`
|
||||||
|
|
||||||
|
## Frontend Architecture
|
||||||
|
|
||||||
|
- **Auth**: OIDC flow via `oidc-client-ts`, `AuthContext` provides user identity and tokens
|
||||||
|
- **API layer**: Axios-based client methods in `src/api/` (one file per domain)
|
||||||
|
- **Routing**: React Router v7 in `src/App.tsx`
|
||||||
|
- **Key components**: `DocumentEditModal`, `PdfSplitViewer`, `WysiwygEditor` (TipTap), `BarcodePositioner`
|
||||||
|
- During dev, Vite proxies `/api` to `localhost:3100`
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Key variables (see `.env.example` for full list):
|
||||||
|
|
||||||
|
| Variable | Purpose |
|
||||||
|
|----------|---------|
|
||||||
|
| `DB_*` | MySQL connection |
|
||||||
|
| `PAPERLESS_URL`, `PAPERLESS_TOKEN` | Paperless-NGX API |
|
||||||
|
| `OIDC_ISSUER`, `OIDC_CLIENT_ID` | OIDC provider (Authentik) |
|
||||||
|
| `OLLAMA_URL`, `OLLAMA_MODEL` | OCR service |
|
||||||
|
| `SCANNER_WATCH_DIR`, `SCANNER_ARCHIVE_DIR` | File system paths |
|
||||||
|
| `BELEGNUMMER_GET_URL`, `BELEGNUMMER_SET_URL` | External invoice number API |
|
||||||
|
| `PORT` | Backend port (default 3100) |
|
||||||
|
| `VITE_API_URL` | Override API URL in frontend (dev only) |
|
||||||
@@ -132,7 +132,7 @@ export class EmailImportController {
|
|||||||
|
|
||||||
// --- Final Import ---
|
// --- Final Import ---
|
||||||
@Post('execute')
|
@Post('execute')
|
||||||
@RequirePermissions(Permission.MANAGE_ALL)
|
@RequirePermissions(Permission.VIEW_MAIL)
|
||||||
async executeImport(@Body() importData: any) {
|
async executeImport(@Body() importData: any) {
|
||||||
try {
|
try {
|
||||||
const result = await this.importService.executeImport(importData);
|
const result = await this.importService.executeImport(importData);
|
||||||
|
|||||||
@@ -434,6 +434,7 @@ export default function InboxPage() {
|
|||||||
{field.type === 'date' ? (
|
{field.type === 'date' ? (
|
||||||
<DatePicker
|
<DatePicker
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
format="DD.MM.YYYY"
|
||||||
value={fieldValues[field.name] ? dayjs(fieldValues[field.name]) : null}
|
value={fieldValues[field.name] ? dayjs(fieldValues[field.name]) : null}
|
||||||
onChange={(d) =>
|
onChange={(d) =>
|
||||||
setFieldValues((prev) => ({
|
setFieldValues((prev) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user