feat(wiki): Kategorienvererbung für betriebsrat_editable, Ajax-Absicherung
- is_category_betriebsrat_editable(): läuft den Kategoriebaum nach oben durch (via knowledgecenter_category_links), sodass Unterkategorien einer freigegebenen Kategorie automatisch ebenfalls als editierbar gelten - ajax_is_category_editable_for_br(): gleiche Logik für den Ajax-Kontext - ajax_can_edit_post(): nutzt jetzt Vererbung statt direkter Kategorienprüfung - create_post_draft(): ajax_has_wiki_edit()-Check hinzugefügt - update_post_version(): Permission-Check mit Sonderfall neue Drafts (noch keine Kategorien → Prüfung auf has_wiki_edit begrenzt) - update_post_categories(): Betriebsrat darf nur freigegebene Kategorien (inkl. Vererbung) zuweisen - upload_inline_image.php: Bild-Upload prüft ebenfalls den Kategoriebaum Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user