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; } }