fix(auth): PM_Buchhaltung umfasst den Posteingang

Der Posteingang ist eine abgespeckte Buchhaltung. Bisher bekam
PM_Buchhaltung nur PROCESS_MANUALLY; die Seite „Manuell bearbeiten“
nutzt für Vorschau, PDF, E-Rechnung und Speichern aber Routen mit
VIEW_INBOX – reine Buchhaltungsnutzer konnten dort nichts speichern.

PM_Buchhaltung bekommt jetzt zusätzlich VIEW_INBOX (Backend und Frontend).
permissions.enum.spec.ts vergleicht künftig nicht nur die Gruppennamen,
sondern auch die Berechtigungen pro Gruppe zwischen beiden Kopien.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bjoernpoettkerandClaude Opus 5.5 committed 2026-11-04 10:46:43 +01:00
1 parent cedd7c78f4
commit 04fca933ee
3 files changed
+49 -4

No files matched your search

@@ -16,9 +16,15 @@ describe('mapGroupsToPermissions', () => {
);
});
it('mappt PM_Buchhaltung auf PROCESS_MANUALLY', () => {
expect(mapGroupsToPermissions(['PM_Buchhaltung'])).toEqual([
Permission.PROCESS_MANUALLY,
it('PM_Buchhaltung enthält den Posteingang (abgespeckte Buchhaltung)', () => {
expect(mapGroupsToPermissions(['PM_Buchhaltung']).sort()).toEqual(
[Permission.PROCESS_MANUALLY, Permission.VIEW_INBOX].sort(),
);
});
it('PM_Posteingang bekommt nur den Posteingang', () => {
expect(mapGroupsToPermissions(['PM_Posteingang'])).toEqual([
Permission.VIEW_INBOX,
]);
});
@@ -52,4 +58,37 @@ describe('mapGroupsToPermissions', () => {
const frontend = groupNames(readFileSync(frontendFile, 'utf8'));
expect(backend).toEqual(frontend);
});
// Gleiche Gruppennamen reichen nicht – jede Gruppe muss auch dieselben
// Berechtigungen bekommen (z.B. PM_Buchhaltung inkl. VIEW_INBOX).
it('vergibt pro Gruppe dieselben Berechtigungen wie das Frontend', () => {
const frontendFile = join(
__dirname,
'../../../paperless-frontend/src/auth/permissions.ts',
);
if (!existsSync(frontendFile)) return;
const mapping = (source: string) => {
const ergebnis: Record<string, string[]> = {};
const treffer = [...source.matchAll(/groups\.includes\('([^']+)'\)/g)];
treffer.forEach((m, i) => {
const ende = treffer[i + 1]?.index ?? source.length;
const block = source.slice(m.index, ende);
ergebnis[m[1]] = [
...new Set(
[...block.matchAll(/permissions\.add\(Permission\.(\w+)\)/g)].map(
(p) => p[1],
),
),
].sort();
});
return ergebnis;
};
const backend = mapping(
readFileSync(join(__dirname, 'permissions.enum.ts'), 'utf8'),
);
expect(backend['PM_Buchhaltung']).toContain('VIEW_INBOX');
expect(mapping(readFileSync(frontendFile, 'utf8'))).toEqual(backend);
});
});
@@ -34,8 +34,11 @@ export function mapGroupsToPermissions(
// Gruppe wurde in Authentik von 'PM_Belege' zu 'PM_Buchhaltung' umbenannt.
// Muss identisch zu paperless-frontend/src/auth/permissions.ts bleiben.
if (groups.includes('PM_Buchhaltung'))
// Der Posteingang ist eine abgespeckte Buchhaltung – PM_Buchhaltung umfasst ihn.
if (groups.includes('PM_Buchhaltung')) {
permissions.add(Permission.PROCESS_MANUALLY);
permissions.add(Permission.VIEW_INBOX);
}
if (groups.includes('PM_Maileingang')) permissions.add(Permission.VIEW_MAIL);
if (groups.includes('PM_Posteingang')) permissions.add(Permission.VIEW_INBOX);
if (groups.includes('PM_Scanner')) permissions.add(Permission.VIEW_SCANNER);
@@ -31,8 +31,11 @@ export function mapGroupsToPermissions(groups: string[] | undefined | null): Per
return Array.from(permissions);
}
// Der Posteingang ist eine abgespeckte Buchhaltung – PM_Buchhaltung umfasst ihn.
// Muss identisch zu paperless-backend/src/auth/permissions.enum.ts bleiben.
if (groups.includes('PM_Buchhaltung')) {
permissions.add(Permission.PROCESS_MANUALLY);
permissions.add(Permission.VIEW_INBOX);
}
if (groups.includes('PM_Maileingang')) {
permissions.add(Permission.VIEW_MAIL);