fix(security): Posteingangs-Maske nur für Dokumente im eigenen Arbeitsbereich
PUT paperless/inbox/:id prüft jetzt pro Dokument: Posteingang-Rolle nur für Dokumente mit Tag 1 (Posteingang), Buchhaltung nur für Dokumente mit MANUELL_BEARBEITEN_TAG, Admins immer. Bisher ließen sich Mandant (Owner), Felder und Titel beliebiger Paperless-Dokumente ändern, weil das Backend mit dem Service-Token arbeitet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3f98dfd98f
commit
cedd7c78f4
4 files changed
+97
-4
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import { Permission } from '../auth/permissions.enum';
|
||||
import {
|
||||
POSTEINGANG_TAG_ID,
|
||||
darfDokumentBearbeiten,
|
||||
} from './dokument-zugriff.util';
|
||||
|
||||
const MANUELL = 6;
|
||||
|
||||
describe('darfDokumentBearbeiten', () => {
|
||||
it('Posteingang-Rolle: nur Dokumente mit Posteingang-Tag', () => {
|
||||
const rechte = [Permission.VIEW_INBOX];
|
||||
expect(
|
||||
darfDokumentBearbeiten([POSTEINGANG_TAG_ID, 9], rechte, MANUELL),
|
||||
).toBe(true);
|
||||
expect(darfDokumentBearbeiten([9], rechte, MANUELL)).toBe(false);
|
||||
expect(darfDokumentBearbeiten([MANUELL], rechte, MANUELL)).toBe(false);
|
||||
});
|
||||
|
||||
it('Buchhaltung: Dokumente mit Manuell-Tag', () => {
|
||||
const rechte = [Permission.PROCESS_MANUALLY];
|
||||
expect(darfDokumentBearbeiten([MANUELL], rechte, MANUELL)).toBe(true);
|
||||
expect(darfDokumentBearbeiten([POSTEINGANG_TAG_ID], rechte, MANUELL)).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('Admins dürfen alles', () => {
|
||||
expect(darfDokumentBearbeiten([], [Permission.MANAGE_ALL], MANUELL)).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('andere Rollen und fehlende Tags: nein', () => {
|
||||
expect(
|
||||
darfDokumentBearbeiten(
|
||||
[POSTEINGANG_TAG_ID],
|
||||
[Permission.VIEW_FREIGABE],
|
||||
MANUELL,
|
||||
),
|
||||
).toBe(false);
|
||||
expect(
|
||||
darfDokumentBearbeiten(undefined, [Permission.VIEW_INBOX], MANUELL),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Permission } from '../auth/permissions.enum';
|
||||
|
||||
/** Paperless-Tag, der ein Dokument als „im Posteingang“ kennzeichnet. */
|
||||
export const POSTEINGANG_TAG_ID = 1;
|
||||
|
||||
/**
|
||||
* Darf der Benutzer dieses Paperless-Dokument über die Posteingangs-Maske
|
||||
* bearbeiten? Der Backend-Service-Token umgeht die Paperless-Rechte, deshalb
|
||||
* wird hier pro Dokument geprüft: Posteingang-Rolle nur für Dokumente mit
|
||||
* Posteingang-Tag, Buchhaltung nur für Dokumente mit Manuell-Tag.
|
||||
*/
|
||||
export function darfDokumentBearbeiten(
|
||||
tags: number[] | undefined,
|
||||
permissions: Permission[],
|
||||
manuellTagId: number,
|
||||
): boolean {
|
||||
if (permissions.includes(Permission.MANAGE_ALL)) return true;
|
||||
const vorhanden = new Set((tags ?? []).map(Number));
|
||||
return (
|
||||
(vorhanden.has(POSTEINGANG_TAG_ID) &&
|
||||
permissions.includes(Permission.VIEW_INBOX)) ||
|
||||
(vorhanden.has(manuellTagId) &&
|
||||
permissions.includes(Permission.PROCESS_MANUALLY))
|
||||
);
|
||||
}
|
||||
@@ -17,11 +17,13 @@ import {
|
||||
Res,
|
||||
Query,
|
||||
Request,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common';
|
||||
import type { Response } from 'express';
|
||||
import { AllowApiKey, RequirePermissions } from '../auth/permissions.decorator';
|
||||
import { Permission } from '../auth/permissions.enum';
|
||||
import { entferneGeschuetzteStatusfelder } from './status-felder.util';
|
||||
import { darfDokumentBearbeiten } from './dokument-zugriff.util';
|
||||
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
@@ -392,6 +394,23 @@ export class PaperlessController {
|
||||
// Fetch from paperless
|
||||
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.owner = body.mandant ?? oldDocument.owner;
|
||||
oldDocument.correspondent = body.correspondent ?? oldDocument.correspondent;
|
||||
|
||||
@@ -215,11 +215,15 @@ export class PaperlessService {
|
||||
return response.data.results;
|
||||
}
|
||||
|
||||
async getManuellDocuments(): Promise<any[]> {
|
||||
const errorTag = this.configService.get<number>(
|
||||
'MANUELL_BEARBEITEN_TAG',
|
||||
6,
|
||||
/** Tag der Liste „Manuell bearbeiten“ (Env-Werte kommen als String). */
|
||||
getManuellTagId(): number {
|
||||
return Number(
|
||||
this.configService.get<number | string>('MANUELL_BEARBEITEN_TAG', 6),
|
||||
);
|
||||
}
|
||||
|
||||
async getManuellDocuments(): Promise<any[]> {
|
||||
const errorTag = this.getManuellTagId();
|
||||
const response = await this.client.get('/documents/', {
|
||||
params: {
|
||||
page: 1,
|
||||
|
||||
Reference in new issue
Block a user