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;
|
|| get_permission_state('r-wiki-br', $mid, $uid) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Betriebsrat darf einen Post nur bearbeiten, wenn er in einer freigegebenen Kategorie liegt.
|
// Prüft ob eine Kategorie (oder ein Vorfahre) betriebsrat_editable=1 hat.
|
||||||
// Gibt false zurück wenn Bearbeitung verboten, true wenn erlaubt.
|
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
|
function ajax_can_edit_post(int $postId): bool
|
||||||
{
|
{
|
||||||
$mid = $GLOBALS['main_contact']['master_mandant_id'] ?? 0;
|
$mid = $GLOBALS['main_contact']['master_mandant_id'] ?? 0;
|
||||||
$uid = $GLOBALS['main_contact']['id'] ?? 0;
|
$uid = $GLOBALS['main_contact']['id'] ?? 0;
|
||||||
if (get_permission_state('r-wiki', $mid, $uid) == 1) {
|
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) {
|
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'],
|
$res = mysqli_query($GLOBALS['mysql_con'],
|
||||||
"SELECT COUNT(*) AS cnt
|
"SELECT category_id FROM knowledgecenter_category_post WHERE post_id = $postId");
|
||||||
FROM knowledgecenter_category_post kcp
|
while ($row = mysqli_fetch_assoc($res)) {
|
||||||
JOIN knowledgecenter_categories_update kcu ON kcu.id = kcp.category_id
|
if (ajax_is_category_editable_for_br((int)$row['category_id'])) {
|
||||||
WHERE kcp.post_id = $postId AND kcu.betriebsrat_editable = 1");
|
return true;
|
||||||
$row = mysqli_fetch_assoc($res);
|
}
|
||||||
return $row && (int)$row['cnt'] > 0;
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AJAX-Handler: Falls per POST eine Aktion übergeben wurde, diese verarbeiten und das Skript beenden.
|
// 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']);
|
echo json_encode(['error' => 'Ungültige Beitrags-ID']);
|
||||||
exit;
|
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;
|
$keepModifiedAt = isset($_POST['keep_modified_at']) && (int) $_POST['keep_modified_at'] === 1;
|
||||||
|
|
||||||
$backgroundColor = normalize_hex_color($_POST['background_color'] ?? '#FFFFFF', '#FFFFFF');
|
$backgroundColor = normalize_hex_color($_POST['background_color'] ?? '#FFFFFF', '#FFFFFF');
|
||||||
@@ -1062,6 +1108,10 @@ function delete_post_gallery_dir($postId)
|
|||||||
|
|
||||||
function create_post_draft()
|
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())";
|
$insertPostQuery = "INSERT INTO knowledgecenter_posts (created_at) VALUES (NOW())";
|
||||||
if (!mysqli_query($GLOBALS['mysql_con'], $insertPostQuery)) {
|
if (!mysqli_query($GLOBALS['mysql_con'], $insertPostQuery)) {
|
||||||
echo json_encode(['error' => 'Fehler beim Erstellen des Entwurfs: ' . mysqli_error($GLOBALS['mysql_con'])]);
|
echo json_encode(['error' => 'Fehler beim Erstellen des Entwurfs: ' . mysqli_error($GLOBALS['mysql_con'])]);
|
||||||
@@ -1276,6 +1326,27 @@ function update_post_categories()
|
|||||||
exit;
|
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
|
// Bestehende Einträge für diesen Beitrag löschen
|
||||||
$deleteQuery = "DELETE FROM knowledgecenter_category_post WHERE post_id = $postId";
|
$deleteQuery = "DELETE FROM knowledgecenter_category_post WHERE post_id = $postId";
|
||||||
if (!mysqli_query($GLOBALS['mysql_con'], $deleteQuery)) {
|
if (!mysqli_query($GLOBALS['mysql_con'], $deleteQuery)) {
|
||||||
|
|||||||
@@ -74,14 +74,36 @@ if (!$verifyQ || mysqli_num_rows($verifyQ) === 0) {
|
|||||||
respond_error('Beitrag existiert nicht.', 404);
|
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) {
|
if (!$hasRwiki && $hasRwikiBr) {
|
||||||
|
$brAllowed = false;
|
||||||
$brRes = mysqli_query($GLOBALS['mysql_con'],
|
$brRes = mysqli_query($GLOBALS['mysql_con'],
|
||||||
"SELECT COUNT(*) AS cnt FROM knowledgecenter_category_post kcp
|
"SELECT category_id FROM knowledgecenter_category_post WHERE post_id = $postId");
|
||||||
JOIN knowledgecenter_categories_update kcu ON kcu.id = kcp.category_id
|
while ($brRow = mysqli_fetch_assoc($brRes)) {
|
||||||
WHERE kcp.post_id = $postId AND kcu.betriebsrat_editable = 1");
|
$catId = (int)$brRow['category_id'];
|
||||||
$brRow = mysqli_fetch_assoc($brRes);
|
// Baum nach oben absuchen
|
||||||
if (!$brRow || (int)$brRow['cnt'] === 0) {
|
$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);
|
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
|
// Switch-Case für die verschiedenen Aktionen
|
||||||
$action = $_GET["action"] ?? "List";
|
$action = $_GET["action"] ?? "List";
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
|
|||||||
Reference in New Issue
Block a user