rights system

This commit is contained in:
Matthias Hochmeister
2026-03-23 10:07:53 +01:00
parent f976f36cbc
commit 2bb22850f4
35 changed files with 1565 additions and 282 deletions

View File

@@ -2,7 +2,8 @@ import { Request, Response } from 'express';
import incidentService from '../services/incident.service';
import logger from '../utils/logger';
import { AppError } from '../middleware/error.middleware';
import { AppRole, hasPermission, resolveRequestRole } from '../middleware/rbac.middleware';
import { AppRole } from '../middleware/rbac.middleware';
import { permissionService } from '../services/permission.service';
import {
CreateEinsatzSchema,
UpdateEinsatzSchema,
@@ -88,9 +89,11 @@ class IncidentController {
throw new AppError('Einsatz nicht gefunden', 404);
}
// Role-based redaction: self-contained role resolution (no middleware dependency)
const role = resolveRequestRole(req);
const canReadBerichtText = hasPermission(role, 'incidents:read_bericht_text');
// Role-based redaction: check einsaetze:view_reports permission
const groups: string[] = req.user?.groups ?? [];
const canReadBerichtText =
groups.includes('dashboard_admin') ||
permissionService.hasPermission(groups, 'einsaetze:view_reports');
const responseData = {
...incident,

View File

@@ -0,0 +1,116 @@
import { Request, Response } from 'express';
import { permissionService } from '../services/permission.service';
import logger from '../utils/logger';
class PermissionController {
/**
* GET /api/permissions/me
* Returns the current user's effective permissions.
*/
async getMyPermissions(req: Request, res: Response): Promise<void> {
try {
const groups: string[] = req.user?.groups ?? [];
const isAdmin = groups.includes('dashboard_admin');
let permissions: string[];
if (isAdmin) {
// Admin gets all permissions
const matrix = await permissionService.getMatrix();
permissions = matrix.permissions.map(p => p.id);
} else {
permissions = permissionService.getEffectivePermissions(groups);
}
res.json({
success: true,
data: {
permissions,
maintenance: permissionService.getMaintenanceFlags(),
isAdmin,
},
});
} catch (error) {
logger.error('Failed to get user permissions', { error });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Berechtigungen' });
}
}
/**
* GET /api/admin/permissions/matrix
* Returns the full permission matrix for the admin UI.
*/
async getMatrix(_req: Request, res: Response): Promise<void> {
try {
const matrix = await permissionService.getMatrix();
res.json({ success: true, data: matrix });
} catch (error) {
logger.error('Failed to get permission matrix', { error });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Berechtigungsmatrix' });
}
}
/**
* PUT /api/admin/permissions/group/:groupName
* Sets all permissions for a given Authentik group.
*/
async setGroupPermissions(req: Request, res: Response): Promise<void> {
try {
const groupName = req.params.groupName as string;
const { permissions } = req.body;
if (!Array.isArray(permissions)) {
res.status(400).json({ success: false, message: 'permissions must be an array' });
return;
}
await permissionService.setGroupPermissions(
groupName,
permissions,
req.user!.id
);
res.json({ success: true, message: 'Berechtigungen aktualisiert' });
} catch (error) {
logger.error('Failed to set group permissions', { error });
res.status(500).json({ success: false, message: 'Fehler beim Speichern der Berechtigungen' });
}
}
/**
* GET /api/admin/permissions/groups
* Returns all known Authentik groups from the permission table.
*/
async getGroups(_req: Request, res: Response): Promise<void> {
try {
const groups = await permissionService.getKnownGroups();
res.json({ success: true, data: groups });
} catch (error) {
logger.error('Failed to get groups', { error });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Gruppen' });
}
}
/**
* PUT /api/admin/permissions/maintenance/:featureGroupId
* Toggles maintenance mode for a feature group.
*/
async setMaintenanceFlag(req: Request, res: Response): Promise<void> {
try {
const featureGroupId = req.params.featureGroupId as string;
const { active } = req.body;
if (typeof active !== 'boolean') {
res.status(400).json({ success: false, message: 'active must be a boolean' });
return;
}
await permissionService.setMaintenanceFlag(featureGroupId, active);
res.json({ success: true, message: 'Wartungsmodus aktualisiert' });
} catch (error) {
logger.error('Failed to set maintenance flag', { error });
res.status(500).json({ success: false, message: 'Fehler beim Setzen des Wartungsmodus' });
}
}
}
export default new PermissionController();