Beide Module wurden aus einem anderen Kundenprojekt kopiert und bereinigt: Knowledgecenter: - Bild-Cache (1.985 Dateien) geleert, Ordnerstruktur mit .gitkeep behalten - Files-Gallery-Lizenzschlüssel entfernt (config.php) - Kundenspezifische Kategorien gelöscht: Teil I/II/III QM-Struktur, nummerierte QM-Kapitel, Gremien (Präsidium/Finanzausschuss/Landesausschuss), Sitzungsservice-Serie, Protokoll-Abteilungen, Testeinträge - 56 generische Kategorien bleiben (Downloads, Onboarding, Personalthemen …) Tasks: - Alle Betriebsdaten gelöscht (114 Tasks, 914 Submissions, 579 Assignments) - Task-Definitionen und Verlinkungen geleert - Kategoriestruktur bleibt (Allgemein, IT, Personal, Buchhaltung …) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
253 lines
8.4 KiB
PHP
253 lines
8.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
class TaskCertAuthContext
|
|
{
|
|
private int $contactId;
|
|
private int $masterMandantId;
|
|
private int $currentMandantId;
|
|
|
|
public function __construct(int $contactId, int $masterMandantId, int $currentMandantId)
|
|
{
|
|
$this->contactId = $contactId;
|
|
$this->masterMandantId = $masterMandantId;
|
|
$this->currentMandantId = $currentMandantId;
|
|
}
|
|
|
|
public static function fromGlobals(): self
|
|
{
|
|
$mainContact = self::asArray($GLOBALS['main_contact'] ?? ($_SESSION['main_contact'] ?? []));
|
|
|
|
$contactId = self::firstPositiveInt([
|
|
$mainContact['id'] ?? null,
|
|
$mainContact['main_contact_id'] ?? null,
|
|
$GLOBALS['main_contact_id'] ?? null,
|
|
$_SESSION['main_contact_id'] ?? null,
|
|
$GLOBALS['contact_id'] ?? null,
|
|
$_SESSION['contact_id'] ?? null,
|
|
$_SESSION['id'] ?? null,
|
|
]);
|
|
|
|
$masterMandantId = self::firstPositiveInt([
|
|
$mainContact['master_mandant_id'] ?? null,
|
|
$mainContact['main_mandant_id'] ?? null,
|
|
$mainContact['mandant_id'] ?? null,
|
|
$GLOBALS['master_mandant_id'] ?? null,
|
|
$_SESSION['master_mandant_id'] ?? null,
|
|
$GLOBALS['main_mandant_id'] ?? null,
|
|
$_SESSION['main_mandant_id'] ?? null,
|
|
self::extractMandantId($GLOBALS['mandant'] ?? null),
|
|
self::extractMandantId($_SESSION['mandant'] ?? null),
|
|
]);
|
|
|
|
$currentMandantId = self::firstPositiveInt([
|
|
$mainContact['current_mandant_id'] ?? null,
|
|
$mainContact['main_mandant_id'] ?? null,
|
|
$GLOBALS['current_mandant_id'] ?? null,
|
|
$_SESSION['current_mandant_id'] ?? null,
|
|
self::extractMandantId($GLOBALS['current_mandant'] ?? null),
|
|
self::extractMandantId($_SESSION['current_mandant'] ?? null),
|
|
self::extractMandantId($GLOBALS['mandant'] ?? null),
|
|
self::extractMandantId($_SESSION['mandant'] ?? null),
|
|
]);
|
|
|
|
if ($currentMandantId <= 0) {
|
|
$currentMandantId = $masterMandantId;
|
|
}
|
|
|
|
if ($masterMandantId <= 0) {
|
|
$masterMandantId = $currentMandantId;
|
|
}
|
|
|
|
return new self($contactId, $masterMandantId, $currentMandantId);
|
|
}
|
|
|
|
public function contactId(): int
|
|
{
|
|
return $this->contactId;
|
|
}
|
|
|
|
public function masterMandantId(): int
|
|
{
|
|
return $this->masterMandantId;
|
|
}
|
|
|
|
public function currentMandantId(): int
|
|
{
|
|
return $this->currentMandantId;
|
|
}
|
|
|
|
public function isLoggedIn(): bool
|
|
{
|
|
return $this->contactId > 0;
|
|
}
|
|
|
|
public function hasPermission(string $permissionKey): bool
|
|
{
|
|
if (!$this->isLoggedIn()) {
|
|
TaskCertLogger::warning('Permission denied: no contact id in auth context', [
|
|
'permission' => $permissionKey,
|
|
'contact_id' => $this->contactId,
|
|
'master_mandant_id' => $this->masterMandantId,
|
|
'current_mandant_id' => $this->currentMandantId,
|
|
'request_uri' => (string) ($_SERVER['REQUEST_URI'] ?? ''),
|
|
]);
|
|
return false;
|
|
}
|
|
|
|
$mandantIds = [];
|
|
if ($this->currentMandantId > 0) {
|
|
$mandantIds[] = $this->currentMandantId;
|
|
}
|
|
|
|
if ($this->masterMandantId > 0 && !in_array($this->masterMandantId, $mandantIds, true)) {
|
|
$mandantIds[] = $this->masterMandantId;
|
|
}
|
|
|
|
if ($mandantIds === []) {
|
|
$mandantIds[] = 0;
|
|
}
|
|
|
|
$usedFallback = !function_exists('get_permission_state');
|
|
$checkedStates = [];
|
|
|
|
foreach ($mandantIds as $mandantId) {
|
|
try {
|
|
$state = $usedFallback
|
|
? $this->getPermissionStateFallback($permissionKey, $mandantId)
|
|
: (int) get_permission_state($permissionKey, $mandantId, $this->contactId);
|
|
$checkedStates[] = [
|
|
'mandant_id' => $mandantId,
|
|
'state' => $state,
|
|
];
|
|
|
|
if ($state === 1) {
|
|
if ($usedFallback) {
|
|
TaskCertLogger::info('Permission granted via SQL fallback', [
|
|
'permission' => $permissionKey,
|
|
'contact_id' => $this->contactId,
|
|
'mandant_id' => $mandantId,
|
|
]);
|
|
}
|
|
return true;
|
|
}
|
|
} catch (Throwable $throwable) {
|
|
TaskCertLogger::error('Permission check failed', [
|
|
'permission' => $permissionKey,
|
|
'contact_id' => $this->contactId,
|
|
'mandant_id' => $mandantId,
|
|
'fallback_used' => $usedFallback ? 1 : 0,
|
|
'exception' => $throwable,
|
|
]);
|
|
}
|
|
}
|
|
|
|
TaskCertLogger::warning('Permission denied after check', [
|
|
'permission' => $permissionKey,
|
|
'contact_id' => $this->contactId,
|
|
'master_mandant_id' => $this->masterMandantId,
|
|
'current_mandant_id' => $this->currentMandantId,
|
|
'checked_mandant_ids' => $mandantIds,
|
|
'checked_states' => $checkedStates,
|
|
'fallback_used' => $usedFallback ? 1 : 0,
|
|
'request_uri' => (string) ($_SERVER['REQUEST_URI'] ?? ''),
|
|
]);
|
|
|
|
return false;
|
|
}
|
|
|
|
private static function asArray($value): array
|
|
{
|
|
if (!is_array($value)) {
|
|
return [];
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
private static function firstPositiveInt(array $values): int
|
|
{
|
|
foreach ($values as $value) {
|
|
$intValue = (int) $value;
|
|
if ($intValue > 0) {
|
|
return $intValue;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
private static function extractMandantId($value): int
|
|
{
|
|
if (!is_array($value)) {
|
|
return 0;
|
|
}
|
|
|
|
return self::firstPositiveInt([
|
|
$value['id'] ?? null,
|
|
$value['main_mandant_id'] ?? null,
|
|
$value['mandant_id'] ?? null,
|
|
]);
|
|
}
|
|
|
|
private function getPermissionStateFallback(string $permissionKey, int $mandantId): int
|
|
{
|
|
$conn = $GLOBALS['mysql_con'] ?? null;
|
|
if (!($conn instanceof mysqli)) {
|
|
throw new RuntimeException('Kein mysqli-Handle für Permission-Fallback verfügbar.');
|
|
}
|
|
|
|
$defaultState = 0;
|
|
$permissionId = 0;
|
|
|
|
$stmtPermission = $conn->prepare(
|
|
'SELECT id, default_active FROM main_permission WHERE code = ? LIMIT 1'
|
|
);
|
|
if (!($stmtPermission instanceof mysqli_stmt)) {
|
|
throw new RuntimeException('Statement für main_permission konnte nicht erstellt werden.');
|
|
}
|
|
|
|
$stmtPermission->bind_param('s', $permissionKey);
|
|
$stmtPermission->execute();
|
|
$resultPermission = $stmtPermission->get_result();
|
|
if ($resultPermission instanceof mysqli_result) {
|
|
$permission = $resultPermission->fetch_assoc();
|
|
if (is_array($permission)) {
|
|
$permissionId = (int) ($permission['id'] ?? 0);
|
|
$defaultState = (int) ($permission['default_active'] ?? 0) === 1 ? 1 : 0;
|
|
}
|
|
$resultPermission->free();
|
|
}
|
|
$stmtPermission->close();
|
|
|
|
if ($permissionId <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
$state = $defaultState;
|
|
$stmtContact = $conn->prepare(
|
|
'SELECT active FROM main_contact_permission
|
|
WHERE main_contact_id = ? AND main_mandant_id = ? AND main_permission_id = ?
|
|
LIMIT 1'
|
|
);
|
|
if (!($stmtContact instanceof mysqli_stmt)) {
|
|
throw new RuntimeException('Statement für main_contact_permission konnte nicht erstellt werden.');
|
|
}
|
|
|
|
$contactId = $this->contactId;
|
|
$stmtContact->bind_param('iii', $contactId, $mandantId, $permissionId);
|
|
$stmtContact->execute();
|
|
$resultContact = $stmtContact->get_result();
|
|
if ($resultContact instanceof mysqli_result) {
|
|
$contactPermission = $resultContact->fetch_assoc();
|
|
if (is_array($contactPermission)) {
|
|
$state = (int) ($contactPermission['active'] ?? 0) === 1 ? 1 : 0;
|
|
}
|
|
$resultContact->free();
|
|
}
|
|
$stmtContact->close();
|
|
|
|
return $state;
|
|
}
|
|
}
|