feat(module-grants): Proxmox, Handelsware und DKV mit Freigabestufe Verwalten

- Proxmox-Schreibwege und Handelsware-Einstellungen auf @ModuleManage umgestellt
- DKV-Fleet: ganze Klasse Verwalten-Stufe, Benutzen allein bleibt ohne Zugriff
- Metadaten-Test belegt umgestellte und bewusst Administratoren vorbehaltene Handler
- Webseiten (Proxmox, Handelsware, Widget) folgen canManage, DKV-Zugriffsseite erklärt die Stufe

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-02 13:31:08 +02:00
parent a222711ad9
commit c2ebc8daa0
23 changed files with 403 additions and 138 deletions
+12 -12
View File
@@ -9,10 +9,8 @@ import {
Put,
Req,
} from '@nestjs/common';
import { Role } from '@prisma/client';
import { Roles } from '../auth/decorators/roles.decorator';
import type { AuthenticatedRequest } from '../auth/types/auth-user';
import { UseModule } from '../module-registry/module.guard';
import { ModuleManage, UseModule } from '../module-registry/module.guard';
import {
CreateProxmoxServerDto,
TestProxmoxServerDto,
@@ -26,9 +24,11 @@ import { ProxmoxService } from './proxmox.service';
* `domaincheck.controller.ts`) — Aktivierung UND Freigabe. `tenantId` kommt
* ausschliesslich aus `req.tenantId` (gesetzt vom `TenantGuard`), nie aus
* Body oder Query. Lesen (`GET servers`) steht jedem Benutzer mit
* Modulzugriff offen; Schreiben (`POST servers`, `POST servers/test`,
* `POST servers/:id/poll`, `POST servers/:id/test`) zusaetzlich
* `@Roles(ADMIN, SUPER_ADMIN)` (T-DHH-05). `servers/test` (statisch, zwei
* Modulzugriff offen; Schreiben (`POST servers`, `PUT`/`DELETE servers/:id`,
* `POST servers/test`, `POST servers/:id/poll`, `POST servers/:id/test`)
* zusaetzlich `@ModuleManage('proxmox')` — Administratoren und Benutzer mit
* der Freigabestufe Verwalten (261002-icv, vorher `@Roles(ADMIN,
* SUPER_ADMIN)`; T-DHH-05). `servers/test` (statisch, zwei
* Segmente) und `servers/:id/test` (drei Segmente) ueberschneiden sich
* nicht — beide POST, aber unterschiedliche Segmentzahl, deshalb keine
* Reihenfolge-Abhaengigkeit (anders als `GET :id` vs. statische Routen).
@@ -55,7 +55,7 @@ export class ProxmoxController {
}
@Post('servers')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async create(@Req() req: AuthenticatedRequest, @Body() dto: CreateProxmoxServerDto) {
const tenantId = this.requireTenantId(req);
const created = await this.proxmoxService.createServer(tenantId, dto);
@@ -65,7 +65,7 @@ export class ProxmoxController {
}
@Put('servers/:id')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async update(
@Req() req: AuthenticatedRequest,
@Param('id') id: string,
@@ -78,7 +78,7 @@ export class ProxmoxController {
}
@Delete('servers/:id')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async remove(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
const tenantId = this.requireTenantId(req);
const deleted = await this.proxmoxService.deleteServer(tenantId, id);
@@ -87,7 +87,7 @@ export class ProxmoxController {
}
@Post('servers/:id/poll')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async poll(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
return this.proxmoxService.pollServer(this.requireTenantId(req), id);
}
@@ -101,7 +101,7 @@ export class ProxmoxController {
* OHNE den Zwischenlagerstand zu ueberschreiben.
*/
@Post('servers/:id/test')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async test(
@Req() req: AuthenticatedRequest,
@Param('id') id: string,
@@ -115,7 +115,7 @@ export class ProxmoxController {
* noch keinen gespeicherten Server, `dto` ist deshalb die einzige Quelle.
*/
@Post('servers/test')
@Roles(Role.ADMIN, Role.SUPER_ADMIN)
@ModuleManage('proxmox')
async testDraft(@Req() req: AuthenticatedRequest, @Body() dto: TestProxmoxServerDto) {
this.requireTenantId(req);
return this.proxmoxService.testDraftConnection(dto);