diff --git a/module/knowledgecenter_update/Ajax/Ajax.php b/module/knowledgecenter_update/Ajax/Ajax.php index 788e6d7..251d79a 100644 --- a/module/knowledgecenter_update/Ajax/Ajax.php +++ b/module/knowledgecenter_update/Ajax/Ajax.php @@ -33,26 +33,56 @@ function ajax_has_wiki_edit(): bool || get_permission_state('r-wiki-br', $mid, $uid) == 1; } -// Betriebsrat darf einen Post nur bearbeiten, wenn er in einer freigegebenen Kategorie liegt. -// Gibt false zurück wenn Bearbeitung verboten, true wenn erlaubt. +// Prüft ob eine Kategorie (oder ein Vorfahre) betriebsrat_editable=1 hat. +function ajax_is_category_editable_for_br(int $categoryId): bool +{ + $visited = []; + $queue = [$categoryId]; + while (!empty($queue)) { + $current = array_shift($queue); + if (isset($visited[$current])) { + continue; + } + $visited[$current] = true; + $res = mysqli_query($GLOBALS['mysql_con'], + "SELECT betriebsrat_editable FROM knowledgecenter_categories_update WHERE id = $current LIMIT 1"); + $row = mysqli_fetch_assoc($res); + if ($row && (int)$row['betriebsrat_editable'] === 1) { + return true; + } + $pRes = mysqli_query($GLOBALS['mysql_con'], + "SELECT parent_category_id FROM knowledgecenter_category_links WHERE child_category_id = $current"); + while ($pRow = mysqli_fetch_assoc($pRes)) { + $pid = (int)$pRow['parent_category_id']; + if (!isset($visited[$pid])) { + $queue[] = $pid; + } + } + } + return false; +} + +// Betriebsrat darf einen Post nur bearbeiten, wenn er in einer freigegebenen +// Kategorie (oder Unterkategorie einer freigegebenen Kategorie) liegt. function ajax_can_edit_post(int $postId): bool { $mid = $GLOBALS['main_contact']['master_mandant_id'] ?? 0; $uid = $GLOBALS['main_contact']['id'] ?? 0; if (get_permission_state('r-wiki', $mid, $uid) == 1) { - return true; // Redakteur darf immer + return true; } if (get_permission_state('r-wiki-br', $mid, $uid) != 1) { - return false; // Kein Wiki-Recht + return false; } - // Betriebsrat: Post muss in betriebsrat_editable Kategorie liegen + // Betriebsrat: prüfe alle dem Post zugeordneten Kategorien inkl. Vorfahren $res = mysqli_query($GLOBALS['mysql_con'], - "SELECT COUNT(*) AS cnt - FROM knowledgecenter_category_post kcp - JOIN knowledgecenter_categories_update kcu ON kcu.id = kcp.category_id - WHERE kcp.post_id = $postId AND kcu.betriebsrat_editable = 1"); - $row = mysqli_fetch_assoc($res); - return $row && (int)$row['cnt'] > 0; + "SELECT category_id FROM knowledgecenter_category_post WHERE post_id = $postId"); + while ($row = mysqli_fetch_assoc($res)) { + if (ajax_is_category_editable_for_br((int)$row['category_id'])) { + return true; + } + } + return false; } // AJAX-Handler: Falls per POST eine Aktion übergeben wurde, diese verarbeiten und das Skript beenden. @@ -719,6 +749,22 @@ function update_post_version() echo json_encode(['error' => 'Ungültige Beitrags-ID']); exit; } + + if (!ajax_has_wiki_edit()) { + echo json_encode(['error' => 'Keine Berechtigung']); + exit; + } + // Betriebsrat darf bestehende Posts nur bearbeiten wenn der Post in einer freigegebenen Kategorie liegt. + // Neue Drafts haben noch keine Kategorien → Prüfung überspringen (Zugang wurde schon bei create_post_draft gesichert). + if ($postId > 0) { + $catCountRes = mysqli_query($GLOBALS['mysql_con'], + "SELECT COUNT(*) AS cnt FROM knowledgecenter_category_post WHERE post_id = $postId"); + $catCountRow = mysqli_fetch_assoc($catCountRes); + if ((int)$catCountRow['cnt'] > 0 && !ajax_can_edit_post($postId)) { + echo json_encode(['error' => 'Keine Berechtigung für diesen Beitrag']); + exit; + } + } $keepModifiedAt = isset($_POST['keep_modified_at']) && (int) $_POST['keep_modified_at'] === 1; $backgroundColor = normalize_hex_color($_POST['background_color'] ?? '#FFFFFF', '#FFFFFF'); @@ -1062,6 +1108,10 @@ function delete_post_gallery_dir($postId) function create_post_draft() { + if (!ajax_has_wiki_edit()) { + echo json_encode(['error' => 'Keine Berechtigung']); + exit; + } $insertPostQuery = "INSERT INTO knowledgecenter_posts (created_at) VALUES (NOW())"; if (!mysqli_query($GLOBALS['mysql_con'], $insertPostQuery)) { echo json_encode(['error' => 'Fehler beim Erstellen des Entwurfs: ' . mysqli_error($GLOBALS['mysql_con'])]); @@ -1276,6 +1326,27 @@ function update_post_categories() exit; } + $mid = $GLOBALS['main_contact']['master_mandant_id'] ?? 0; + $uid = $GLOBALS['main_contact']['id'] ?? 0; + $isRedakteur = get_permission_state('r-wiki', $mid, $uid) == 1; + $isBetriebsrat = get_permission_state('r-wiki-br', $mid, $uid) == 1; + + if (!$isRedakteur && !$isBetriebsrat) { + echo json_encode(['error' => 'Keine Berechtigung']); + exit; + } + + // Betriebsrat darf nur Kategorien zuweisen, die für ihn freigegeben sind (inkl. Vererbung) + if (!$isRedakteur && $isBetriebsrat) { + foreach ($categories as $catId) { + $catId = (int)$catId; + if ($catId > 0 && !ajax_is_category_editable_for_br($catId)) { + echo json_encode(['error' => "Kategorie $catId ist nicht für den Betriebsrat freigegeben"]); + exit; + } + } + } + // Bestehende Einträge für diesen Beitrag löschen $deleteQuery = "DELETE FROM knowledgecenter_category_post WHERE post_id = $postId"; if (!mysqli_query($GLOBALS['mysql_con'], $deleteQuery)) { diff --git a/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php b/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php index 376691a..37b00e4 100644 --- a/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php +++ b/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php @@ -74,14 +74,36 @@ if (!$verifyQ || mysqli_num_rows($verifyQ) === 0) { respond_error('Beitrag existiert nicht.', 404); } -// Betriebsrat darf Bilder nur in freigegebene Kategorien hochladen +// Betriebsrat darf Bilder nur für Posts in freigegebenen Kategorien hochladen (inkl. Vererbung) if (!$hasRwiki && $hasRwikiBr) { + $brAllowed = false; $brRes = mysqli_query($GLOBALS['mysql_con'], - "SELECT COUNT(*) AS cnt FROM knowledgecenter_category_post kcp - JOIN knowledgecenter_categories_update kcu ON kcu.id = kcp.category_id - WHERE kcp.post_id = $postId AND kcu.betriebsrat_editable = 1"); - $brRow = mysqli_fetch_assoc($brRes); - if (!$brRow || (int)$brRow['cnt'] === 0) { + "SELECT category_id FROM knowledgecenter_category_post WHERE post_id = $postId"); + while ($brRow = mysqli_fetch_assoc($brRes)) { + $catId = (int)$brRow['category_id']; + // Baum nach oben absuchen + $visited = []; + $queue = [$catId]; + while (!empty($queue)) { + $current = array_shift($queue); + if (isset($visited[$current])) continue; + $visited[$current] = true; + $chkRes = mysqli_query($GLOBALS['mysql_con'], + "SELECT betriebsrat_editable FROM knowledgecenter_categories_update WHERE id = $current LIMIT 1"); + $chkRow = mysqli_fetch_assoc($chkRes); + if ($chkRow && (int)$chkRow['betriebsrat_editable'] === 1) { + $brAllowed = true; + break 2; + } + $pRes = mysqli_query($GLOBALS['mysql_con'], + "SELECT parent_category_id FROM knowledgecenter_category_links WHERE child_category_id = $current"); + while ($pRow = mysqli_fetch_assoc($pRes)) { + $pid = (int)$pRow['parent_category_id']; + if (!isset($visited[$pid])) $queue[] = $pid; + } + } + } + if (!$brAllowed) { respond_error('Keine Berechtigung für diesen Beitrag.', 403); } } diff --git a/module/knowledgecenter_update/Controllers/knowledgecenter.inc.php b/module/knowledgecenter_update/Controllers/knowledgecenter.inc.php index e603e75..b6ba0f5 100644 --- a/module/knowledgecenter_update/Controllers/knowledgecenter.inc.php +++ b/module/knowledgecenter_update/Controllers/knowledgecenter.inc.php @@ -867,6 +867,36 @@ function require_wiki_edit_permission(): void } } +// Prüft ob eine Kategorie (oder irgendein Vorfahre über knowledgecenter_category_links) +// betriebsrat_editable=1 hat. Läuft den Baum nach oben durch. +function is_category_betriebsrat_editable(int $categoryId): bool +{ + $visited = []; + $queue = [$categoryId]; + while (!empty($queue)) { + $current = array_shift($queue); + if (isset($visited[$current])) { + continue; + } + $visited[$current] = true; + $res = mysqli_query($GLOBALS['mysql_con'], + "SELECT betriebsrat_editable FROM knowledgecenter_categories_update WHERE id = $current LIMIT 1"); + $row = mysqli_fetch_assoc($res); + if ($row && (int)$row['betriebsrat_editable'] === 1) { + return true; + } + $pRes = mysqli_query($GLOBALS['mysql_con'], + "SELECT parent_category_id FROM knowledgecenter_category_links WHERE child_category_id = $current"); + while ($pRow = mysqli_fetch_assoc($pRes)) { + $pid = (int)$pRow['parent_category_id']; + if (!isset($visited[$pid])) { + $queue[] = $pid; + } + } + } + return false; +} + // Switch-Case für die verschiedenen Aktionen $action = $_GET["action"] ?? "List"; switch ($action) {