new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 16:09:42 +01:00
parent e9a9478aac
commit 8c66492b27
40 changed files with 2016 additions and 117 deletions

View File

@@ -0,0 +1,176 @@
import { Request, Response } from 'express';
import issueService from '../services/issue.service';
import { permissionService } from '../services/permission.service';
import logger from '../utils/logger';
const param = (req: Request, key: string): string => req.params[key] as string;
class IssueController {
async getIssues(req: Request, res: Response): Promise<void> {
try {
const userId = req.user!.id;
const groups: string[] = (req.user as any).groups || [];
const canViewAll = permissionService.hasPermission(groups, 'issues:view_all');
const issues = await issueService.getIssues(userId, canViewAll);
res.status(200).json({ success: true, data: issues });
} catch (error) {
logger.error('IssueController.getIssues error', { error });
res.status(500).json({ success: false, message: 'Issues konnten nicht geladen werden' });
}
}
async getIssue(req: Request, res: Response): Promise<void> {
const id = parseInt(param(req, 'id'), 10);
if (isNaN(id)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const issue = await issueService.getIssueById(id);
if (!issue) {
res.status(404).json({ success: false, message: 'Issue nicht gefunden' });
return;
}
const userId = req.user!.id;
const groups: string[] = (req.user as any).groups || [];
const canViewAll = permissionService.hasPermission(groups, 'issues:view_all');
if (!canViewAll && issue.erstellt_von !== userId) {
res.status(403).json({ success: false, message: 'Kein Zugriff' });
return;
}
res.status(200).json({ success: true, data: issue });
} catch (error) {
logger.error('IssueController.getIssue error', { error });
res.status(500).json({ success: false, message: 'Issue konnte nicht geladen werden' });
}
}
async createIssue(req: Request, res: Response): Promise<void> {
const { titel } = req.body;
if (!titel || typeof titel !== 'string' || titel.trim().length === 0) {
res.status(400).json({ success: false, message: 'Titel ist erforderlich' });
return;
}
try {
const issue = await issueService.createIssue(req.body, req.user!.id);
res.status(201).json({ success: true, data: issue });
} catch (error) {
logger.error('IssueController.createIssue error', { error });
res.status(500).json({ success: false, message: 'Issue konnte nicht erstellt werden' });
}
}
async updateIssue(req: Request, res: Response): Promise<void> {
const id = parseInt(param(req, 'id'), 10);
if (isNaN(id)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const groups: string[] = (req.user as any).groups || [];
const canManage = permissionService.hasPermission(groups, 'issues:manage');
if (!canManage) {
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
return;
}
const issue = await issueService.updateIssue(id, req.body);
if (!issue) {
res.status(404).json({ success: false, message: 'Issue nicht gefunden' });
return;
}
res.status(200).json({ success: true, data: issue });
} catch (error) {
logger.error('IssueController.updateIssue error', { error });
res.status(500).json({ success: false, message: 'Issue konnte nicht aktualisiert werden' });
}
}
async deleteIssue(req: Request, res: Response): Promise<void> {
const id = parseInt(param(req, 'id'), 10);
if (isNaN(id)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const issue = await issueService.getIssueById(id);
if (!issue) {
res.status(404).json({ success: false, message: 'Issue nicht gefunden' });
return;
}
const userId = req.user!.id;
const groups: string[] = (req.user as any).groups || [];
const canManage = permissionService.hasPermission(groups, 'issues:manage');
if (!canManage && issue.erstellt_von !== userId) {
res.status(403).json({ success: false, message: 'Keine Berechtigung' });
return;
}
await issueService.deleteIssue(id);
res.status(200).json({ success: true, message: 'Issue gelöscht' });
} catch (error) {
logger.error('IssueController.deleteIssue error', { error });
res.status(500).json({ success: false, message: 'Issue konnte nicht gelöscht werden' });
}
}
async getComments(req: Request, res: Response): Promise<void> {
const issueId = parseInt(param(req, 'id'), 10);
if (isNaN(issueId)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
try {
const issue = await issueService.getIssueById(issueId);
if (!issue) {
res.status(404).json({ success: false, message: 'Issue nicht gefunden' });
return;
}
const userId = req.user!.id;
const groups: string[] = (req.user as any).groups || [];
const canViewAll = permissionService.hasPermission(groups, 'issues:view_all');
if (!canViewAll && issue.erstellt_von !== userId) {
res.status(403).json({ success: false, message: 'Kein Zugriff' });
return;
}
const comments = await issueService.getComments(issueId);
res.status(200).json({ success: true, data: comments });
} catch (error) {
logger.error('IssueController.getComments error', { error });
res.status(500).json({ success: false, message: 'Kommentare konnten nicht geladen werden' });
}
}
async addComment(req: Request, res: Response): Promise<void> {
const issueId = parseInt(param(req, 'id'), 10);
if (isNaN(issueId)) {
res.status(400).json({ success: false, message: 'Ungültige ID' });
return;
}
const { inhalt } = req.body;
if (!inhalt || typeof inhalt !== 'string' || inhalt.trim().length === 0) {
res.status(400).json({ success: false, message: 'Kommentar darf nicht leer sein' });
return;
}
try {
const issue = await issueService.getIssueById(issueId);
if (!issue) {
res.status(404).json({ success: false, message: 'Issue nicht gefunden' });
return;
}
const userId = req.user!.id;
const groups: string[] = (req.user as any).groups || [];
const canViewAll = permissionService.hasPermission(groups, 'issues:view_all');
const canManage = permissionService.hasPermission(groups, 'issues:manage');
if (!canViewAll && !canManage && issue.erstellt_von !== userId) {
res.status(403).json({ success: false, message: 'Kein Zugriff' });
return;
}
const comment = await issueService.addComment(issueId, userId, inhalt.trim());
res.status(201).json({ success: true, data: comment });
} catch (error) {
logger.error('IssueController.addComment error', { error });
res.status(500).json({ success: false, message: 'Kommentar konnte nicht erstellt werden' });
}
}
}
export default new IssueController();