fix(security): Befunde aus dem Security-Audit beheben #7
No files matched your search
@@ -2,6 +2,7 @@ import { Permission } from '../auth/permissions.enum';
|
|||||||
import {
|
import {
|
||||||
POSTEINGANG_TAG_ID,
|
POSTEINGANG_TAG_ID,
|
||||||
darfDokumentBearbeiten,
|
darfDokumentBearbeiten,
|
||||||
|
dokumentKurzinfo,
|
||||||
} from './dokument-zugriff.util';
|
} from './dokument-zugriff.util';
|
||||||
|
|
||||||
const MANUELL = 6;
|
const MANUELL = 6;
|
||||||
@@ -43,3 +44,24 @@ describe('darfDokumentBearbeiten', () => {
|
|||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('dokumentKurzinfo', () => {
|
||||||
|
it('liefert nur Kennung, Titel, ASN und Datum – keinen OCR-Volltext', () => {
|
||||||
|
const doc = {
|
||||||
|
id: 5,
|
||||||
|
title: 'Rechnung',
|
||||||
|
archive_serial_number: 42,
|
||||||
|
created: '2026-01-02',
|
||||||
|
content: 'IBAN DE00 …',
|
||||||
|
owner: 3,
|
||||||
|
custom_fields: [{ field: 15, value: 'x' }],
|
||||||
|
notes: [{ note: 'intern' }],
|
||||||
|
};
|
||||||
|
expect(dokumentKurzinfo(doc)).toEqual({
|
||||||
|
id: 5,
|
||||||
|
title: 'Rechnung',
|
||||||
|
archive_serial_number: 42,
|
||||||
|
created: '2026-01-02',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -23,3 +23,29 @@ export function darfDokumentBearbeiten(
|
|||||||
permissions.includes(Permission.PROCESS_MANUALLY))
|
permissions.includes(Permission.PROCESS_MANUALLY))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DokumentKurzinfo {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
archive_serial_number: number | null;
|
||||||
|
created: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Für Suche und Verknüpfungsanzeige genügen Kennung, Titel, ASN und Datum.
|
||||||
|
* Das vollständige Paperless-Dokument enthält u.a. den OCR-Volltext und
|
||||||
|
* Statusfelder – die sollen über diese Routen nicht abrufbar sein.
|
||||||
|
*/
|
||||||
|
export function dokumentKurzinfo(doc: {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
archive_serial_number?: number | null;
|
||||||
|
created: string;
|
||||||
|
}): DokumentKurzinfo {
|
||||||
|
return {
|
||||||
|
id: doc.id,
|
||||||
|
title: doc.title,
|
||||||
|
archive_serial_number: doc.archive_serial_number ?? null,
|
||||||
|
created: doc.created,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -18,12 +18,16 @@ import {
|
|||||||
Query,
|
Query,
|
||||||
Request,
|
Request,
|
||||||
ForbiddenException,
|
ForbiddenException,
|
||||||
|
ParseIntPipe,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import type { Response } from 'express';
|
import type { Response } from 'express';
|
||||||
import { AllowApiKey, RequirePermissions } from '../auth/permissions.decorator';
|
import { AllowApiKey, RequirePermissions } from '../auth/permissions.decorator';
|
||||||
import { Permission } from '../auth/permissions.enum';
|
import { Permission } from '../auth/permissions.enum';
|
||||||
import { entferneGeschuetzteStatusfelder } from './status-felder.util';
|
import { entferneGeschuetzteStatusfelder } from './status-felder.util';
|
||||||
import { darfDokumentBearbeiten } from './dokument-zugriff.util';
|
import {
|
||||||
|
darfDokumentBearbeiten,
|
||||||
|
dokumentKurzinfo,
|
||||||
|
} from './dokument-zugriff.util';
|
||||||
|
|
||||||
import { FileInterceptor } from '@nestjs/platform-express';
|
import { FileInterceptor } from '@nestjs/platform-express';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
@@ -42,6 +46,15 @@ import { ErechnungService } from '../erechnung/erechnung.service';
|
|||||||
/** Setting.Tag-Schlüssel für die manuell gepflegte Steuertag-Liste */
|
/** Setting.Tag-Schlüssel für die manuell gepflegte Steuertag-Liste */
|
||||||
export const STEUERTAG_SETTING_KEY = 'steuertag_ids';
|
export const STEUERTAG_SETTING_KEY = 'steuertag_ids';
|
||||||
|
|
||||||
|
/** Von JwtStrategy gesetzt; die globalen Guards lassen nur Angemeldete durch. */
|
||||||
|
interface BenutzerRequest {
|
||||||
|
user: {
|
||||||
|
userId: string;
|
||||||
|
permissions?: Permission[];
|
||||||
|
preferredUsername?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Controller('api/paperless')
|
@Controller('api/paperless')
|
||||||
export class PaperlessController {
|
export class PaperlessController {
|
||||||
private readonly logger = new Logger(PaperlessController.name);
|
private readonly logger = new Logger(PaperlessController.name);
|
||||||
@@ -94,8 +107,9 @@ export class PaperlessController {
|
|||||||
return this.paperlessService.pruefeBelegnummer(belegnummer ?? '');
|
return this.paperlessService.pruefeBelegnummer(belegnummer ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Dokumentsuche für Verknüpfungsfelder im Bearbeiten-Dialog. */
|
||||||
@Get('documents')
|
@Get('documents')
|
||||||
@RequirePermissions(Permission.MANAGE_SETTINGS)
|
@RequirePermissions(Permission.VIEW_INBOX)
|
||||||
async getDocuments(
|
async getDocuments(
|
||||||
@Query('search') search?: string,
|
@Query('search') search?: string,
|
||||||
@Query('page') page?: string,
|
@Query('page') page?: string,
|
||||||
@@ -108,13 +122,18 @@ export class PaperlessController {
|
|||||||
if (search) {
|
if (search) {
|
||||||
params.query = search; // Global search in Paperless
|
params.query = search; // Global search in Paperless
|
||||||
}
|
}
|
||||||
return this.paperlessService.getDocuments(params);
|
const ergebnis = await this.paperlessService.getDocuments(params);
|
||||||
|
return {
|
||||||
|
count: ergebnis.count,
|
||||||
|
results: (ergebnis.results ?? []).map(dokumentKurzinfo),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Titel verknüpfter Dokumente – bewusst ohne Prüfung pro Dokument. */
|
||||||
@Get('documents/:id')
|
@Get('documents/:id')
|
||||||
@RequirePermissions(Permission.VIEW_INBOX, Permission.PROCESS_MANUALLY)
|
@RequirePermissions(Permission.VIEW_INBOX)
|
||||||
async getDocument(@Param('id') id: string) {
|
async getDocument(@Param('id', ParseIntPipe) id: number) {
|
||||||
return this.paperlessService.getDocument(parseInt(id, 10));
|
return dokumentKurzinfo(await this.paperlessService.getDocument(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('tags')
|
@Get('tags')
|
||||||
@@ -226,9 +245,13 @@ export class PaperlessController {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vorschaubild – auch für Suchergebnisse außerhalb des Posteingangs,
|
||||||
|
* deshalb ohne Prüfung pro Dokument.
|
||||||
|
*/
|
||||||
|
@Get('documents/:id/preview')
|
||||||
@RequirePermissions(Permission.VIEW_INBOX)
|
@RequirePermissions(Permission.VIEW_INBOX)
|
||||||
@Get('inbox/preview/:id')
|
async getDocumentPreview(@Param('id') id: string, @Res() res: Response) {
|
||||||
async getInboxPreview(@Param('id') id: string, @Res() res: Response) {
|
|
||||||
try {
|
try {
|
||||||
const stream = await this.paperlessService.getDocumentPreviewStream(
|
const stream = await this.paperlessService.getDocumentPreviewStream(
|
||||||
parseInt(id, 10),
|
parseInt(id, 10),
|
||||||
@@ -252,9 +275,14 @@ export class PaperlessController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequirePermissions(Permission.VIEW_INBOX)
|
/**
|
||||||
@Get('inbox/pdf/:id')
|
* Original-PDF – für den Bearbeiten-Dialog und den Duplikatvergleich im
|
||||||
async getInboxPdf(@Param('id') id: string, @Res() res: Response) {
|
* Scanner (dort ein beliebiges vorhandenes Dokument), deshalb ohne Prüfung
|
||||||
|
* pro Dokument.
|
||||||
|
*/
|
||||||
|
@Get('documents/:id/pdf')
|
||||||
|
@RequirePermissions(Permission.VIEW_INBOX, Permission.VIEW_SCANNER)
|
||||||
|
async getDocumentPdf(@Param('id') id: string, @Res() res: Response) {
|
||||||
try {
|
try {
|
||||||
const stream = await this.paperlessService.getDocumentPdfStream(
|
const stream = await this.paperlessService.getDocumentPdfStream(
|
||||||
parseInt(id, 10),
|
parseInt(id, 10),
|
||||||
@@ -362,22 +390,22 @@ export class PaperlessController {
|
|||||||
* Mandant und Belegart vor. Liefert `erechnung: false`, wenn das Dokument
|
* Mandant und Belegart vor. Liefert `erechnung: false`, wenn das Dokument
|
||||||
* keine auswertbare E-Rechnung enthält.
|
* keine auswertbare E-Rechnung enthält.
|
||||||
*/
|
*/
|
||||||
@Get('inbox/:id/erechnung')
|
@Get('documents/:id/erechnung')
|
||||||
@RequirePermissions(Permission.VIEW_INBOX)
|
@RequirePermissions(Permission.VIEW_INBOX)
|
||||||
async getInboxErechnung(@Param('id') id: string, @Request() req: any) {
|
async getDocumentErechnung(
|
||||||
return this.erechnungService.analysiereDokument(
|
@Param('id', ParseIntPipe) id: number,
|
||||||
parseInt(id, 10),
|
@Request() req: BenutzerRequest,
|
||||||
req.user?.userId,
|
) {
|
||||||
);
|
await this.ladeBearbeitbaresDokument(id, req);
|
||||||
|
return this.erechnungService.analysiereDokument(id, req.user.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put('inbox/:id')
|
@Put('documents/:id')
|
||||||
@RequirePermissions(Permission.VIEW_INBOX)
|
@RequirePermissions(Permission.VIEW_INBOX)
|
||||||
async putInboxDocument(
|
async putDocument(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() body: any,
|
@Body() body: any,
|
||||||
@Request()
|
@Request() req: BenutzerRequest,
|
||||||
req: { user?: { permissions?: Permission[]; preferredUsername?: string } },
|
|
||||||
) {
|
) {
|
||||||
const documentId = parseInt(id, 10);
|
const documentId = parseInt(id, 10);
|
||||||
|
|
||||||
@@ -391,25 +419,7 @@ export class PaperlessController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
body.customFields = felder;
|
body.customFields = felder;
|
||||||
// Fetch from paperless
|
const oldDocument = await this.ladeBearbeitbaresDokument(documentId, req);
|
||||||
const oldDocument = await this.paperlessService.getDocument(documentId);
|
|
||||||
|
|
||||||
// Nur Dokumente aus dem eigenen Arbeitsbereich (Posteingang bzw. Manuell)
|
|
||||||
// – sonst ließen sich Mandant/Felder beliebiger Dokumente ändern.
|
|
||||||
if (
|
|
||||||
!darfDokumentBearbeiten(
|
|
||||||
oldDocument.tags as number[] | undefined,
|
|
||||||
req.user?.permissions ?? [],
|
|
||||||
this.paperlessService.getManuellTagId(),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.logger.warn(
|
|
||||||
`Dokument ${documentId}: Bearbeitung abgelehnt – nicht im Posteingang/Manuell-Bereich des Benutzers (${req.user?.preferredUsername ?? 'unbekannt'})`,
|
|
||||||
);
|
|
||||||
throw new ForbiddenException(
|
|
||||||
'Dieses Dokument liegt nicht in Ihrem Posteingang bzw. Ihrer Bearbeitungsliste',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
oldDocument.document_type = body.documentType ?? oldDocument.document_type;
|
oldDocument.document_type = body.documentType ?? oldDocument.document_type;
|
||||||
oldDocument.owner = body.mandant ?? oldDocument.owner;
|
oldDocument.owner = body.mandant ?? oldDocument.owner;
|
||||||
@@ -574,6 +584,33 @@ export class PaperlessController {
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lädt ein Dokument, das der Benutzer bearbeiten darf: Posteingang-Rolle nur
|
||||||
|
* mit Posteingang-Tag, Buchhaltung zusätzlich mit Manuell-Tag. Das Backend
|
||||||
|
* arbeitet mit dem Service-Token, Paperless prüft hier also nichts.
|
||||||
|
*/
|
||||||
|
private async ladeBearbeitbaresDokument(
|
||||||
|
documentId: number,
|
||||||
|
req: BenutzerRequest,
|
||||||
|
): Promise<any> {
|
||||||
|
const dokument = await this.paperlessService.getDocument(documentId);
|
||||||
|
if (
|
||||||
|
!darfDokumentBearbeiten(
|
||||||
|
dokument.tags as number[] | undefined,
|
||||||
|
req.user?.permissions ?? [],
|
||||||
|
this.paperlessService.getManuellTagId(),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
this.logger.warn(
|
||||||
|
`Dokument ${documentId}: Zugriff abgelehnt – nicht im Posteingang/Manuell-Bereich des Benutzers (${req.user?.preferredUsername ?? 'unbekannt'})`,
|
||||||
|
);
|
||||||
|
throw new ForbiddenException(
|
||||||
|
'Dieses Dokument liegt nicht in Ihrem Posteingang bzw. Ihrer Bearbeitungsliste',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return dokument;
|
||||||
|
}
|
||||||
|
|
||||||
@Get('tasks')
|
@Get('tasks')
|
||||||
@RequirePermissions(Permission.MANAGE_SETTINGS)
|
@RequirePermissions(Permission.MANAGE_SETTINGS)
|
||||||
async getAllTasks() {
|
async getAllTasks() {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export const paperlessApi = {
|
|||||||
checksumExists: (checksum: string) =>
|
checksumExists: (checksum: string) =>
|
||||||
api.post<{ exists: boolean }>('/api/paperless/checksum', { checksum }).then(r => r.data.exists),
|
api.post<{ exists: boolean }>('/api/paperless/checksum', { checksum }).then(r => r.data.exists),
|
||||||
getDocumentPdfBlob: (id: number) =>
|
getDocumentPdfBlob: (id: number) =>
|
||||||
api.get<Blob>(`/api/paperless/inbox/pdf/${id}`, { responseType: 'blob' }).then(r => r.data),
|
api.get<Blob>(`/api/paperless/documents/${id}/pdf`, { responseType: 'blob' }).then(r => r.data),
|
||||||
pruefeBelegnummer: (belegnummer: string) =>
|
pruefeBelegnummer: (belegnummer: string) =>
|
||||||
api.get<BelegnummerPruefung>('/api/paperless/belegnummer-pruefung', { params: { belegnummer } }).then(r => r.data),
|
api.get<BelegnummerPruefung>('/api/paperless/belegnummer-pruefung', { params: { belegnummer } }).then(r => r.data),
|
||||||
};
|
};
|
||||||
@@ -64,7 +64,7 @@ export const posteingangApi = {
|
|||||||
.then((r) => r.data),
|
.then((r) => r.data),
|
||||||
|
|
||||||
updateDocument: (id: number, data: any) =>
|
updateDocument: (id: number, data: any) =>
|
||||||
api.put(`/api/paperless/inbox/${id}`, data).then((r) => r.data),
|
api.put(`/api/paperless/documents/${id}`, data).then((r) => r.data),
|
||||||
|
|
||||||
getKontonummern: (correspondentId: number) =>
|
getKontonummern: (correspondentId: number) =>
|
||||||
api.get<Kontonummer[]>(`/api/kontonummern/FromCorrespondent/${correspondentId}`).then(r => r.data),
|
api.get<Kontonummer[]>(`/api/kontonummern/FromCorrespondent/${correspondentId}`).then(r => r.data),
|
||||||
@@ -73,5 +73,5 @@ export const posteingangApi = {
|
|||||||
api.post<Kontonummer>('/api/kontonummern', data).then(r => r.data),
|
api.post<Kontonummer>('/api/kontonummern', data).then(r => r.data),
|
||||||
|
|
||||||
getErechnung: (id: number) =>
|
getErechnung: (id: number) =>
|
||||||
api.get<ERechnungVorschlag>(`/api/paperless/inbox/${id}/erechnung`).then(r => r.data),
|
api.get<ERechnungVorschlag>(`/api/paperless/documents/${id}/erechnung`).then(r => r.data),
|
||||||
};
|
};
|
||||||
@@ -634,7 +634,7 @@ export default function DocumentEditModal({ documentId, document, open, onClose,
|
|||||||
icon={<EyeOutlined />}
|
icon={<EyeOutlined />}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
openAuthUrl(`${getEnv('VITE_API_URL')}/api/paperless/inbox/pdf/${currentId}`);
|
openAuthUrl(`${getEnv('VITE_API_URL')}/api/paperless/documents/${currentId}/pdf`);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -679,13 +679,13 @@ export default function DocumentEditModal({ documentId, document, open, onClose,
|
|||||||
icon={<ExportOutlined />}
|
icon={<ExportOutlined />}
|
||||||
block
|
block
|
||||||
style={{ marginBottom: 8 }}
|
style={{ marginBottom: 8 }}
|
||||||
onClick={() => openAuthUrl(`${getEnv('VITE_API_URL')}/api/paperless/inbox/pdf/${documentId}`)}
|
onClick={() => openAuthUrl(`${getEnv('VITE_API_URL')}/api/paperless/documents/${documentId}/pdf`)}
|
||||||
>
|
>
|
||||||
PDF in neuem Tab öffnen
|
PDF in neuem Tab öffnen
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<AuthIframe
|
<AuthIframe
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/pdf/${documentId}#toolbar=0`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${documentId}/pdf#toolbar=0`}
|
||||||
style={{ width: '100%', height: isMobile ? '50vh' : '100%' }}
|
style={{ width: '100%', height: isMobile ? '50vh' : '100%' }}
|
||||||
title="PDF Preview"
|
title="PDF Preview"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export default function DocumentSearchModal({ open, onCancel, onSelect }: Props)
|
|||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
avatar={
|
avatar={
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${doc.id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${doc.id}/preview`}
|
||||||
width={80}
|
width={80}
|
||||||
height={110}
|
height={110}
|
||||||
style={{ objectFit: 'cover', borderRadius: 4, border: '1px solid #f0f0f0' }}
|
style={{ objectFit: 'cover', borderRadius: 4, border: '1px solid #f0f0f0' }}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export default function ManuellBearbeitenPage() {
|
|||||||
|
|
||||||
const popoverContent = (id: number) => (
|
const popoverContent = (id: number) => (
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${id}/preview`}
|
||||||
width={400}
|
width={400}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -108,7 +108,7 @@ export default function ManuellBearbeitenPage() {
|
|||||||
render: (_: any, record: PosteingangDocument) => (
|
render: (_: any, record: PosteingangDocument) => (
|
||||||
<Popover content={popoverContent(record.id)} placement="right" trigger="hover">
|
<Popover content={popoverContent(record.id)} placement="right" trigger="hover">
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${record.id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${record.id}/preview`}
|
||||||
width={100}
|
width={100}
|
||||||
style={{ border: '1px solid #d9d9d9', objectFit: 'contain' }}
|
style={{ border: '1px solid #d9d9d9', objectFit: 'contain' }}
|
||||||
/>
|
/>
|
||||||
@@ -172,7 +172,7 @@ export default function ManuellBearbeitenPage() {
|
|||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${record.id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${record.id}/preview`}
|
||||||
width={72}
|
width={72}
|
||||||
style={{ border: '1px solid #d9d9d9', objectFit: 'contain', flexShrink: 0 }}
|
style={{ border: '1px solid #d9d9d9', objectFit: 'contain', flexShrink: 0 }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export default function PosteingangPage() {
|
|||||||
|
|
||||||
const popoverContent = (id: number) => (
|
const popoverContent = (id: number) => (
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${id}/preview`}
|
||||||
width={400}
|
width={400}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -80,7 +80,7 @@ export default function PosteingangPage() {
|
|||||||
render: (_: any, record: PosteingangDocument) => (
|
render: (_: any, record: PosteingangDocument) => (
|
||||||
<Popover content={popoverContent(record.id)} placement="right" trigger="hover">
|
<Popover content={popoverContent(record.id)} placement="right" trigger="hover">
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${record.id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${record.id}/preview`}
|
||||||
width={100}
|
width={100}
|
||||||
style={{ border: '1px solid #d9d9d9', objectFit: 'contain' }}
|
style={{ border: '1px solid #d9d9d9', objectFit: 'contain' }}
|
||||||
/>
|
/>
|
||||||
@@ -136,7 +136,7 @@ export default function PosteingangPage() {
|
|||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
<div style={{ display: 'flex', gap: 12 }}>
|
<div style={{ display: 'flex', gap: 12 }}>
|
||||||
<AuthImage
|
<AuthImage
|
||||||
src={`${getEnv('VITE_API_URL')}/api/paperless/inbox/preview/${record.id}`}
|
src={`${getEnv('VITE_API_URL')}/api/paperless/documents/${record.id}/preview`}
|
||||||
width={72}
|
width={72}
|
||||||
style={{ border: '1px solid #d9d9d9', objectFit: 'contain', flexShrink: 0 }}
|
style={{ border: '1px solid #d9d9d9', objectFit: 'contain', flexShrink: 0 }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in new issue
Block a user