From 3e24910831dc504af791761888614d826cbd7eb5 Mon Sep 17 00:00:00 2001 From: Clemens Creutzburg Date: Tue, 21 Jul 2026 21:10:09 +0200 Subject: [PATCH] Legacy-Abbau Schritt 2: Legacy-Authentifizierung entfernt Die Zugriffspruefung lief bisher in 19 Dateien auf einen Fallback gegen die Legacy-Tabelle kl_Mitarbeiter (checkKaffeelisteAdmin/-Access). Der Zugang haengt jetzt ausschliesslich an der SaaS-Anmeldung. - Fallback-Bloecke in allen 19 Dateien entfernt, ebenso getUserName/getUserId - functions.php besteht nur noch aus der SaaS-Anmeldung; die per String zusammengebaute Abfrage "WHERE Email like ''" ist damit weg - config.php baut keine sqlsrv-Verbindung mehr auf, der Kompatibilitaetslayer lib/sqlsrv_mysql_compat.php ist verwaist und entfaellt - Auto-Login per DEV_AUTH_EMAIL gibt es nicht mehr: er meldete jeden Besucher an und machte damit den Login-Schutz unpruefbar. Angemeldet wird auch lokal ueber login.php; die Variable dient nur noch scripts/init-mysql-dev.php http-smoke war an die Golden-Master-Daten des Default-Mandanten gebunden und hatte deshalb sechs dauerhaft rote Pruefungen. Der Test legt sich jetzt einen eigenen Mandanten mit bekannten Salden an, meldet sich per HTTP an und raeumt danach auf. Geschuetzte Seiten werden nicht mehr ueber das Wort "Login" im Text geprueft, sondern ueber die tatsaechliche 302-Umleitung. http-smoke 27 PASS / 6 FAIL -> 33 PASS / 0 FAIL role-matrix 55 PASS / 0 FAIL -> unveraendert tenant-isolation 9 PASS / 1 FAIL -> 11 PASS / 1 FAIL (Altfehler) Ausserdem "keine Zugang" -> "keinen Zugang" in zwei Fehlermeldungen; der Rollentest erkannte die Ablehnung an genau diesem Tippfehler und wurde mitgezogen. Co-Authored-By: Claude Opus 4.8 --- config.php | 20 --- csvupload.php | 8 - einzahlung.php | 8 - env.local.example.php | 9 +- exportKaffeeliste.php | 8 - faq.php | 9 -- footer.php | 5 +- functions.php | 88 +---------- hinweise.php | 10 +- index.php | 21 +-- jahresauswertung.php | 8 - kaffeeliste.php | 8 - ledger-preview.php | 15 -- letzteneintraege.php | 8 - lib/sqlsrv_mysql_compat.php | 245 ------------------------------- mailversenden.php | 8 - mitarbeiterverwalten.php | 10 +- mitglieder-vorlage.php | 2 - namenanpassen.php | 8 - paypal-zuordnung.php | 8 - scripts/check-m8-role-matrix.php | 2 +- scripts/http-smoke.php | 237 ++++++++++++++++++++++++++---- scripts/run-dev-server.sh | 5 +- stricheintragen.php | 8 - teilnehmerauswertung.php | 19 +-- 25 files changed, 229 insertions(+), 548 deletions(-) delete mode 100644 lib/sqlsrv_mysql_compat.php diff --git a/config.php b/config.php index 9aa6643..b92f994 100644 --- a/config.php +++ b/config.php @@ -3,23 +3,3 @@ require_once __DIR__ . '/app/bootstrap.php'; app_start_session(); - -if ((getenv('APP_DB_DRIVER') ?: '') === 'mysql' && !function_exists('sqlsrv_connect')) { - require_once __DIR__ . '/lib/sqlsrv_mysql_compat.php'; -} - -// Verbindung zur Datenbank herstellen (ersetze die Platzhalter durch deine Daten) -$serverName = getenv('DB_HOST') ?: ""; -$connectionOptions = array( - "Database" => getenv('DB_NAME') ?: "", - "Uid" => getenv('DB_USER') ?: "", - "PWD" => getenv('DB_PASS') ?: "", - "TrustServerCertificate"=>true -); - -$conn = sqlsrv_connect($serverName, $connectionOptions); -// Überprüfen der Verbindung -if (!$conn) { - die(print_r(sqlsrv_errors(), true)); -} -?> diff --git a/csvupload.php b/csvupload.php index ce0f49c..fd9f51c 100644 --- a/csvupload.php +++ b/csvupload.php @@ -28,14 +28,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if (!$hasAccess) { echo "

Kein Zugriff

"; include "footer.php"; diff --git a/einzahlung.php b/einzahlung.php index babfa0d..2c9c951 100644 --- a/einzahlung.php +++ b/einzahlung.php @@ -28,14 +28,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if (!$hasAccess) { echo "

Kein Zugriff

"; include "footer.php"; diff --git a/env.local.example.php b/env.local.example.php index 09d4dc1..4c0e391 100644 --- a/env.local.example.php +++ b/env.local.example.php @@ -57,8 +57,7 @@ putenv('PAYPAL_IMAP_USER='); putenv('PAYPAL_IMAP_PASS='); putenv('PAYPAL_IMAP_MAILBOX=INBOX'); -// WICHTIG: DEV_AUTH_EMAIL hier NICHT setzen (auch nicht auskommentiert -// stehen lassen und aus Versehen aktivieren). Ist diese Variable gesetzt, -// wird JEDER Besucher ohne echten Login automatisch als dieser Nutzer -// behandelt (Login-Bypass fuer die alte Default-Mandant-Pruefung, -// siehe functions.php). Nur fuer den lokalen Dev-Server gedacht. +// Hinweis: Den frueheren Login-Bypass ueber DEV_AUTH_EMAIL gibt es nicht mehr - +// die Anmeldung laeuft immer ueber login.php, auch lokal. Die Variable wird nur +// noch von scripts/init-mysql-dev.php gelesen, um beim Aufsetzen einer +// Entwicklungsdatenbank den ersten Benutzer anzulegen. diff --git a/exportKaffeeliste.php b/exportKaffeeliste.php index 15a103a..71aa1b0 100644 --- a/exportKaffeeliste.php +++ b/exportKaffeeliste.php @@ -14,14 +14,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if (!$hasAccess) { http_response_code(403); exit('Kein Zugriff.'); diff --git a/faq.php b/faq.php index 462dfc3..0b54788 100644 --- a/faq.php +++ b/faq.php @@ -31,15 +31,6 @@ if ($saasUser !== null) { $kannVerwalten = saas_user_has_role(['owner', 'admin'], $saasUser); } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAccess($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - $kannVerwalten = checkKaffeelisteAdmin($conn, $mailadress); - } -} - if (!$hasAccess) { echo "

Kein Zugriff

"; include "footer.php"; diff --git a/footer.php b/footer.php index 841edfb..5ce4522 100644 --- a/footer.php +++ b/footer.php @@ -13,11 +13,10 @@ $saasNavUser = function_exists('saas_current_user') ? saas_current_user() : null $saasCanUseLedgerNav = $saasNavUser !== null && function_exists('saas_user_has_role') && saas_user_has_role(['owner', 'admin', 'treasurer'], $saasNavUser); -$legacyCanUseAdminNav = checkKaffeelisteAdmin($conn, $mailadress); $saasCanManageMembersNav = $saasNavUser !== null && function_exists('saas_user_has_role') && saas_user_has_role(['owner', 'admin'], $saasNavUser); -$canUseVerwaltungGroup = $saasCanUseLedgerNav || $legacyCanUseAdminNav; +$canUseVerwaltungGroup = $saasCanUseLedgerNav; ?>
  • @@ -37,7 +36,7 @@ $canUseVerwaltungGroup = $saasCanUseLedgerNav || $legacyCanUseAdminNav;
  • Kaffeeliste anzeigen
  • Journal-Vorschau
  • Jahresabschluss
  • - +
  • Mitglieder verwalten
  • Hinweise verwalten
  • diff --git a/functions.php b/functions.php index a43e76b..c7139b5 100644 --- a/functions.php +++ b/functions.php @@ -3,90 +3,6 @@ include_once "config.php"; require_once __DIR__ . "/app/saas-auth.php"; -$mailadress = ''; -$kennung = ''; - $saasUser = saas_current_user(); -if ($saasUser !== null) { - $mailadress = strtolower(trim((string)$saasUser['email'])); - $kennung = $mailadress; -} else { - $devAuthEmail = getenv('DEV_AUTH_EMAIL') ?: ''; - if ($devAuthEmail !== '') { - $mailadress = strtolower(trim($devAuthEmail)); - $kennung = $mailadress; - } -} - -function getUserName($conn, $mail){ - if (trim((string)$mail) === '') { - return ''; - } - - $sqlMitglieder = "SELECT Name FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' "; - $stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder); - #$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC) - while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) { - return trim($row['Name']); - } - -} - -function getUserId($conn, $mail){ - if (trim((string)$mail) === '') { - return null; - } - - $sqlMitglieder = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' "; - $stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder); - #$row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC) - while( $row = sqlsrv_fetch_array( $stmtMitglieder, SQLSRV_FETCH_ASSOC) ) { - return trim($row['MitarbeiterID']); - } - -} - - - -function checkKaffeelisteAccess($conn, $mail) -{ - if (trim((string)$mail) === '') { - return false; - } - - // Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren - $sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND aktiv='1'"; - - $stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered")); - $row_count = sqlsrv_num_rows( $stmtMitarbeiter ); - #return $row_count; - if ($row_count == 1) - { - return true; - }else{ - return false; - } -} - -function checkKaffeelisteAdmin($conn, $mail) -{ - if (trim((string)$mail) === '') { - return false; - } - - // Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren - $sqlMitarbeiter = "SELECT MitarbeiterID FROM kl_Mitarbeiter WHERE Email like '" . strtolower($mail) . "' AND admin='1'"; - - $stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter, array(), array("Scrollable"=>"buffered")); - $row_count = sqlsrv_num_rows( $stmtMitarbeiter ); - #return $row_count; - if ($row_count == 1) - { - return true; - }else{ - return false; - } -} - - -?> +$mailadress = $saasUser !== null ? strtolower(trim((string)$saasUser['email'])) : ''; +$kennung = $mailadress; diff --git a/hinweise.php b/hinweise.php index 324513a..07a55ef 100644 --- a/hinweise.php +++ b/hinweise.php @@ -30,14 +30,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin'], $saasUser)) { $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if($hasAccess){ echo "

    Kaffeeliste - Hinweise

    "; @@ -101,7 +93,7 @@ if($hasAccess){ }else{ - echo "

    Sie haben keine Zugang zu dieser Webseite

    "; + echo "

    Sie haben keinen Zugang zu dieser Webseite

    "; } ?> diff --git a/index.php b/index.php index 65b5fa1..dedbe91 100644 --- a/index.php +++ b/index.php @@ -21,7 +21,7 @@ $pdo = app_db_pdo(); $saasUser = saas_current_user($pdo); $tenantId = 0; $hasAccess = false; -$emailNorm = strtolower(trim($mailadress)); +$emailNorm = ''; if ($saasUser !== null) { $tenantId = (int)$saasUser['tenant_id']; @@ -29,14 +29,6 @@ if ($saasUser !== null) { $hasAccess = true; } -if (!$hasAccess && checkKaffeelisteAccess($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $participant = null; if ($hasAccess) { // Eingeloggte SaaS-Nutzer werden primaer ueber die feste user_id- @@ -90,19 +82,14 @@ function dashboard_date(string $value): string } } -function dashboard_current_name(?array $saasUser, ?array $participant, mixed $conn, string $mailadress): string +function dashboard_current_name(?array $saasUser, ?array $participant): string { $name = trim((string)($saasUser['display_name'] ?? '')); if ($name !== '') { return $name; } - $name = trim((string)($participant['display_name'] ?? '')); - if ($name !== '') { - return $name; - } - - return trim((string)getUserName($conn, $mailadress)); + return trim((string)($participant['display_name'] ?? '')); } function dashboard_paypal_action(string $template, string $amount): string @@ -235,7 +222,7 @@ include "nav.php"; if ($hasAccess && $participant !== null && $settings !== null) { $balanceCents = (int)$participant['balance_cents']; $balance = dashboard_money($balanceCents); - $currentName = dashboard_current_name($saasUser, $participant, $conn, $mailadress); + $currentName = dashboard_current_name($saasUser, $participant); $selfEntryEnabled = (int)$settings['self_entry_enabled'] === 1; $paypalEnabled = (int)$settings['paypal_enabled'] === 1 && trim((string)$settings['paypal_url_template']) !== ''; diff --git a/jahresauswertung.php b/jahresauswertung.php index 7d073bd..26fc4c5 100644 --- a/jahresauswertung.php +++ b/jahresauswertung.php @@ -16,14 +16,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $jahr = (int)date('Y'); $fehler = null; $ergebnisse = null; diff --git a/kaffeeliste.php b/kaffeeliste.php index 2bdb5ee..926dc1f 100644 --- a/kaffeeliste.php +++ b/kaffeeliste.php @@ -18,14 +18,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $participants = $hasAccess ? ledger_fetch_participant_summaries($pdo, $tenantId, ['active_only' => true]) : []; diff --git a/ledger-preview.php b/ledger-preview.php index 7a782e1..3179649 100644 --- a/ledger-preview.php +++ b/ledger-preview.php @@ -15,21 +15,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $tenantId = (int)$saasUser['tenant_id']; $tenantName = (string)$saasUser['tenant_name']; $tenantSlug = (string)$saasUser['tenant_slug']; -} elseif (checkKaffeelisteAdmin($conn, $mailadress)) { - $defaultTenantSlug = getenv('M3_DEFAULT_TENANT_SLUG'); - $defaultTenantSlug = $defaultTenantSlug !== false && trim($defaultTenantSlug) !== '' - ? trim($defaultTenantSlug) - : 'default'; - $stmt = $pdo->prepare('SELECT id, name, slug FROM tenants WHERE slug = ? LIMIT 1'); - $stmt->execute([$defaultTenantSlug]); - $tenant = $stmt->fetch(); - - if ($tenant !== false) { - $hasAccess = true; - $tenantId = (int)$tenant['id']; - $tenantName = (string)$tenant['name']; - $tenantSlug = (string)$tenant['slug']; - } } $year = ledger_current_year(); diff --git a/letzteneintraege.php b/letzteneintraege.php index 588d813..1180b90 100644 --- a/letzteneintraege.php +++ b/letzteneintraege.php @@ -27,14 +27,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if($hasAccess){ // Stornieren einer Einzahlung. Gearbeitet wird auf der Ledger-ID, weil nur die diff --git a/lib/sqlsrv_mysql_compat.php b/lib/sqlsrv_mysql_compat.php deleted file mode 100644 index 361a34b..0000000 --- a/lib/sqlsrv_mysql_compat.php +++ /dev/null @@ -1,245 +0,0 @@ -pdo = $pdo; - } -} - -final class MysqlSqlsrvStatement -{ - /** @var array> */ - public array $rows; - public int $index = 0; - public int $affectedRows = 0; - - /** - * @param array> $rows - */ - public function __construct(array $rows = [], int $affectedRows = 0) - { - $this->rows = $rows; - $this->affectedRows = $affectedRows; - } -} - -function sqlsrv_connect($serverName, array $connectionOptions = []) -{ - $database = getenv('DB_NAME') ?: ($connectionOptions['Database'] ?? ''); - $user = getenv('DB_USER') ?: ($connectionOptions['Uid'] ?? ''); - $password = getenv('DB_PASS') ?: ($connectionOptions['PWD'] ?? ''); - $host = getenv('DB_HOST') ?: (string)$serverName; - $port = getenv('DB_PORT') ?: '3306'; - - try { - $dsn = sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $host, $port, $database); - $pdo = new PDO($dsn, $user, $password, [ - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => true, - ]); - - return new MysqlSqlsrvConnection($pdo); - } catch (Throwable $e) { - $GLOBALS['__sqlsrv_mysql_last_error'] = [[ - 'SQLSTATE' => $e->getCode(), - 'message' => $e->getMessage(), - ]]; - return false; - } -} - -function sqlsrv_query($conn, string $sql, array $params = [], array $options = []) -{ - if (!$conn instanceof MysqlSqlsrvConnection) { - $GLOBALS['__sqlsrv_mysql_last_error'] = [[ - 'SQLSTATE' => 'HY000', - 'message' => 'Invalid MySQL compatibility connection.', - ]]; - return false; - } - - $translatedSql = sqlsrv_mysql_translate_query($sql); - - try { - $stmt = $conn->pdo->prepare($translatedSql); - $stmt->execute(sqlsrv_mysql_normalize_params($translatedSql, $params)); - - if ($stmt->columnCount() > 0) { - $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($rows as &$row) { - $row = sqlsrv_mysql_normalize_row($row); - } - unset($row); - - return new MysqlSqlsrvStatement($rows, $stmt->rowCount()); - } - - return new MysqlSqlsrvStatement([], $stmt->rowCount()); - } catch (Throwable $e) { - $conn->lastError = [[ - 'SQLSTATE' => $e->getCode(), - 'message' => $e->getMessage(), - 'sql' => $translatedSql, - ]]; - $GLOBALS['__sqlsrv_mysql_last_error'] = $conn->lastError; - return false; - } -} - -function sqlsrv_fetch_array($stmt, int $fetchType = SQLSRV_FETCH_ASSOC) -{ - if (!$stmt instanceof MysqlSqlsrvStatement) { - return null; - } - - if (!array_key_exists($stmt->index, $stmt->rows)) { - return null; - } - - $row = $stmt->rows[$stmt->index++]; - - if ($fetchType === SQLSRV_FETCH_NUMERIC) { - return array_values($row); - } - - return $row; -} - -function sqlsrv_num_rows($stmt): int -{ - if (!$stmt instanceof MysqlSqlsrvStatement) { - return 0; - } - - return count($stmt->rows); -} - -function sqlsrv_errors() -{ - return $GLOBALS['__sqlsrv_mysql_last_error'] ?? null; -} - -function sqlsrv_close($conn): bool -{ - return true; -} - -function sqlsrv_begin_transaction($conn): bool -{ - return $conn instanceof MysqlSqlsrvConnection && $conn->pdo->beginTransaction(); -} - -function sqlsrv_commit($conn): bool -{ - return $conn instanceof MysqlSqlsrvConnection && $conn->pdo->commit(); -} - -function sqlsrv_rollback($conn): bool -{ - return $conn instanceof MysqlSqlsrvConnection && $conn->pdo->rollBack(); -} - -function sqlsrv_mysql_translate_query(string $sql): string -{ - $query = str_replace(["\r\n", "\r"], "\n", $sql); - $query = preg_replace('/\bdbo\./i', '', $query); - $query = preg_replace('/\[([A-Za-z0-9_]+)\]/', '`$1`', $query); - - $query = preg_replace('/FORMAT\(([^,]+),\s*\'yyyy\'\)\s*=\s*FORMAT\(GETDATE\(\),\s*\'yyyy\'\)/i', 'YEAR($1) = YEAR(NOW())', $query); - $query = preg_replace('/CAST\(GETDATE\(\)\s+AS\s+DATE\)/i', 'CURDATE()', $query); - $query = preg_replace('/GETDATE\(\)/i', 'NOW()', $query); - $query = preg_replace('/SYSDATETIME\(\)/i', 'NOW()', $query); - $query = preg_replace('/CONVERT\(VARCHAR,\s*([^)]+),\s*23\)/i', 'DATE($1)', $query); - - $query = preg_replace( - '/DATEADD\(DAY,\s*(-?\d+),\s*\(SELECT\s+MAX\(Datum\)\s+FROM\s+kl_Kaffeeverbrauch\s+WHERE\s+Datum\s+<\s+CURDATE\(\)\)\)/i', - 'DATE_ADD((SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CURDATE()), INTERVAL $1 DAY)', - $query - ); - $query = preg_replace( - '/DATEADD\(DAY,\s*(-?\d+),\s*\(SELECT\s+MAX\(Datum\)\s+FROM\s+kl_Kaffeeverbrauch\s*\)\)/i', - 'DATE_ADD((SELECT MAX(Datum) FROM kl_Kaffeeverbrauch), INTERVAL $1 DAY)', - $query - ); - $query = preg_replace('/DATEADD\(DAY,\s*(-?\d+),\s*NOW\(\)\)/i', 'DATE_ADD(NOW(), INTERVAL $1 DAY)', $query); - - $limit = null; - $query = preg_replace_callback('/^\s*SELECT\s+TOP\s+\(?\s*(\d+)\s*\)?\s+/i', function (array $matches) use (&$limit): string { - $limit = (int)$matches[1]; - return 'SELECT '; - }, $query); - - if ($limit !== null && !preg_match('/\bLIMIT\s+\d+\s*$/i', trim($query))) { - $query = rtrim($query, " \t\n\r\0\x0B;") . ' LIMIT ' . $limit; - } - - return $query; -} - -/** - * PDO is stricter than the SQL Server driver used by the legacy app. Some - * legacy calls pass unused parameters, and one CSV lookup passes one value for - * two equivalent placeholders. Normalize this only in the dev adapter. - * - * @param array $params - * @return array - */ -function sqlsrv_mysql_normalize_params(string $sql, array $params): array -{ - $normalized = array_values($params); - $placeholderCount = substr_count($sql, '?'); - - if ($placeholderCount === 0) { - return []; - } - - if (count($normalized) > $placeholderCount) { - return array_slice($normalized, 0, $placeholderCount); - } - - if (count($normalized) < $placeholderCount && count($normalized) > 0) { - $last = $normalized[count($normalized) - 1]; - while (count($normalized) < $placeholderCount) { - $normalized[] = $last; - } - } - - return $normalized; -} - -/** - * @param array $row - * @return array - */ -function sqlsrv_mysql_normalize_row(array $row): array -{ - foreach ($row as $key => $value) { - if ($value === null || $value instanceof DateTimeInterface) { - continue; - } - - if (is_string($value) && preg_match('/(datum|date|gueltig_bis|valid_)/i', (string)$key)) { - try { - $row[$key] = new DateTime($value); - } catch (Throwable $e) { - $row[$key] = $value; - } - } - } - - return $row; -} diff --git a/mailversenden.php b/mailversenden.php index 269fe42..e8178d7 100644 --- a/mailversenden.php +++ b/mailversenden.php @@ -16,14 +16,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $ergebnisse = null; $dryRun = true; $liveFlash = false; diff --git a/mitarbeiterverwalten.php b/mitarbeiterverwalten.php index 72452a8..6c9674a 100644 --- a/mitarbeiterverwalten.php +++ b/mitarbeiterverwalten.php @@ -32,14 +32,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin'], $saasUser)) { $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if($hasAccess){ $meldung = null; @@ -421,7 +413,7 @@ if($hasAccess){ Sie haben keine Zugang zu dieser Webseite"; + echo "

    Sie haben keinen Zugang zu dieser Webseite

    "; } ?> diff --git a/mitglieder-vorlage.php b/mitglieder-vorlage.php index 50cb08c..93f33c7 100644 --- a/mitglieder-vorlage.php +++ b/mitglieder-vorlage.php @@ -12,8 +12,6 @@ $hasAccess = false; if ($saasUser !== null && saas_user_has_role(['owner', 'admin'], $saasUser)) { $hasAccess = true; -} elseif ($saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $hasAccess = true; } if (!$hasAccess) { diff --git a/namenanpassen.php b/namenanpassen.php index b26a315..8476005 100644 --- a/namenanpassen.php +++ b/namenanpassen.php @@ -20,14 +20,6 @@ if ($saasUser !== null) { $emailNorm = strtolower(trim((string)$saasUser['email_norm'])); $hasAccess = true; $isAdmin = saas_user_has_role(['owner', 'admin'], $saasUser); -} elseif (checkKaffeelisteAccess($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - $emailNorm = strtolower(trim($mailadress)); - $isAdmin = checkKaffeelisteAdmin($conn, $mailadress); - } } $meldung = null; diff --git a/paypal-zuordnung.php b/paypal-zuordnung.php index 0f1239f..c2a70e1 100644 --- a/paypal-zuordnung.php +++ b/paypal-zuordnung.php @@ -15,14 +15,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $flash = null; if ($hasAccess && isset($_SESSION['flash_paypal'])) { $flash = $_SESSION['flash_paypal']; diff --git a/scripts/check-m8-role-matrix.php b/scripts/check-m8-role-matrix.php index a8e4db1..89e5c7c 100644 --- a/scripts/check-m8-role-matrix.php +++ b/scripts/check-m8-role-matrix.php @@ -27,7 +27,7 @@ $pages = [ 'mandant-einstellungen.php' => ['owner', 'admin'], ]; -$denialMarkers = ['kein zugriff', 'keine zugang', 'keine berechtigung']; +$denialMarkers = ['kein zugriff', 'keinen zugang', 'keine berechtigung']; function m8rm_looks_denied(string $body): bool { diff --git a/scripts/http-smoke.php b/scripts/http-smoke.php index 641dd8a..8ea9f03 100644 --- a/scripts/http-smoke.php +++ b/scripts/http-smoke.php @@ -2,14 +2,31 @@ declare(strict_types=1); +require __DIR__ . '/dev-db.php'; + $baseUrl = rtrim((string)(getenv('SMOKE_BASE_URL') ?: 'http://127.0.0.1:8080'), '/'); $issuePattern = '~(?:Deprecated|Warning|Fatal error|Parse error|Notice|Uncaught (?:Error|Exception))~i'; +// Der Smoke-Test legt sich seinen eigenen Mandanten mit bekannten Zahlen an und +// meldet sich per HTTP an, statt sich auf vorhandene Daten oder eine +// Auto-Anmeldung zu verlassen. Nur so lassen sich angemeldete Seiten UND der +// Login-Schutz in einem Lauf pruefen. +$pdo = dev_pdo(); +$suffix = bin2hex(random_bytes(4)); +$smokeSlug = "smoke-{$suffix}"; +$smokeEmail = "smoke-owner-{$suffix}@test.local"; +$smokePassword = 'HttpSmokeTest123!'; +$smokeTenantId = null; + +// Erwartete Betraege der Testdaten (siehe smoke_seed()). +$erwartetGuthaben = '15,00 €'; +$erwartetSchulden = '-4,00 €'; + $checks = [ [ 'label' => 'Landingpage', 'path' => 'landing.php', - 'contains' => ['Kaffeeliste', 'Kundenkonto anlegen', 'Mandantenfähig'], + 'contains' => ['Kaffeeliste', 'Kundenkonto anlegen'], ], [ 'label' => 'Impressum', @@ -34,62 +51,71 @@ $checks = [ [ 'label' => 'Dashboard', 'path' => 'index.php', - 'contains' => ['Hallo Test Admin', 'Aktueller Stand', 'Jahresübersicht', 'Letzte Einzahlungen'], + 'auth' => true, + 'contains' => ['Aktueller Stand', 'Jahresübersicht', 'Letzte Einzahlungen'], ], [ 'label' => 'Striche erfassen', 'path' => 'stricheintragen.php', + 'auth' => true, 'contains' => ['Anzahl der Striche'], ], [ 'label' => 'Einzahlungen erfassen', 'path' => 'einzahlung.php', - 'contains' => ['Einzahlungen'], + 'auth' => true, + 'contains' => ['Einzahlungen', 'Bemerkung'], ], [ 'label' => 'Kaffeeliste', 'path' => 'kaffeeliste.php', + 'auth' => true, 'contains' => [ 'Aktive Mitarbeiter', 'teilnehmerauswertung.php?participant_id=', - 'GM Negativ', - 'gm-negative@test.local', - '-2,00 €', - 'GM Positiv', - '23,60 €', - 'GM Ohne Buchungen', + 'Smoke Guthaben', + $erwartetGuthaben, + 'Smoke Schulden', + $erwartetSchulden, + 'Smoke Ohne Buchungen', '0,00 €', ], - 'not_contains' => ['GM Inaktiv'], + 'not_contains' => ['Smoke Inaktiv'], ], [ 'label' => 'Ledger Preview', 'path' => 'ledger-preview.php', - 'contains' => ['Ledger Preview', 'Tenant-Summen', 'Letzte Ledger-Buchungen'], + 'auth' => true, + 'contains' => ['Journal-Vorschau', 'Tenant-Summen', 'Letzte Ledger-Buchungen'], ], [ 'label' => 'Mitgliederverwaltung', 'path' => 'mitarbeiterverwalten.php', + 'auth' => true, 'contains' => ['Mitglieder verwalten', 'PayPal-Name'], ], [ 'label' => 'Letzte Einträge', 'path' => 'letzteneintraege.php', - 'contains' => ['Letzte 100 Einzahlungen'], + 'auth' => true, + 'contains' => ['Letzte 100 Einzahlungen', 'Stornieren'], ], [ 'label' => 'CSV-Upload', 'path' => 'csvupload.php', - 'contains' => ['CSV Verarbeitung'], + 'auth' => true, + 'contains' => ['CSV-Import'], ], [ 'label' => 'Hinweise', 'path' => 'hinweise.php', + 'auth' => true, 'contains' => ['Kaffeeliste - Hinweise'], ], [ 'label' => 'FAQ', 'path' => 'faq.php', + 'auth' => true, 'contains' => ['FAQ - Kaffeeliste'], ], [ @@ -110,7 +136,8 @@ $checks = [ [ 'label' => 'Mandantenauswahl Login-Schutz', 'path' => 'mandant-auswahl.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Passwort zurücksetzen Invalid', @@ -125,61 +152,73 @@ $checks = [ [ 'label' => 'Mandant-Einstellungen Login-Schutz', 'path' => 'mandant-einstellungen.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Namensanpassung', 'path' => 'namenanpassen.php', + 'auth' => true, 'contains' => ['Anzeigenamen aktualisieren'], ], [ 'label' => 'Datenexport Login-Schutz', 'path' => 'datenexport.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Abo-Upgrade GET-Redirect', 'path' => 'abo-upgrade.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Abo-Portal GET-Redirect', 'path' => 'abo-portal.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Mandant löschen Login-Schutz', 'path' => 'mandant-loeschen.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Back-Office Login-Schutz', 'path' => 'backoffice.php', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Back-Office Mandantendetail Login-Schutz', 'path' => 'backoffice-mandant.php?tenant_id=1', - 'contains' => ['Login'], + 'expect_redirect' => 'login.php', + 'contains' => [], ], [ 'label' => 'Teilnehmerauswertung', - 'path' => 'teilnehmerauswertung.php?user_id=1', - 'contains' => ['Auswertung', 'Test Admin', 'Jahresübersicht', 'Letzte Einzahlungen'], + 'path' => 'PLATZHALTER_TEILNEHMER', + 'auth' => true, + 'contains' => ['Auswertung', 'Smoke Guthaben', 'Jahresübersicht', 'Letzte Einzahlungen'], ], [ 'label' => 'PDF-Export', 'path' => 'exportKaffeeliste.php', + 'auth' => true, 'contains' => ['%PDF'], ], [ 'label' => 'Mailversand', 'path' => 'mailversenden.php', + 'auth' => true, 'contains' => ['Info-Mail versenden', 'Dry-Run', 'Versandlog'], ], [ 'label' => 'Jahresabschluss', 'path' => 'jahresauswertung.php', + 'auth' => true, 'contains' => ['Jahresabschluss', 'Dry-Run', 'Jahresstriche gesamt'], ], ]; @@ -190,25 +229,52 @@ $knownIssueChecks = [ $skippedUnsafe = [ ]; -function smoke_fetch(string $url): array +/** + * HTTP-Request mit optionalem Cookie-Jar. $cookies wird per Referenz + * aktualisiert, damit die Session ueber mehrere Requests erhalten bleibt. + * + * @param array|null $cookies null = bewusst ohne Session + */ +function smoke_fetch(string $url, ?array &$cookies = null, string $method = 'GET', ?string $postBody = null): array { + $header = "User-Agent: KaffeelisteHttpSmoke/1.0\r\n"; + if ($cookies !== null && $cookies !== []) { + $pairs = []; + foreach ($cookies as $name => $value) { + $pairs[] = "{$name}={$value}"; + } + $header .= 'Cookie: ' . implode('; ', $pairs) . "\r\n"; + } + if ($postBody !== null) { + $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; + } + $context = stream_context_create([ 'http' => [ - 'method' => 'GET', + 'method' => $method, 'timeout' => 15, 'ignore_errors' => true, - 'header' => "User-Agent: KaffeelisteHttpSmoke/1.0\r\n", + 'follow_location' => 0, + 'header' => $header, + 'content' => $postBody ?? '', ], ]); $body = @file_get_contents($url, false, $context); $headers = $http_response_header ?? []; $status = 0; + $location = null; - foreach ($headers as $header) { - if (preg_match('~^HTTP/\S+\s+(\d{3})~', $header, $matches) === 1) { + foreach ($headers as $h) { + if (preg_match('~^HTTP/\S+\s+(\d{3})~', $h, $matches) === 1) { $status = (int)$matches[1]; } + if (preg_match('/^Location:\s*(.+)$/i', $h, $m) === 1) { + $location = trim($m[1]); + } + if ($cookies !== null && preg_match('/^Set-Cookie:\s*([^=;]+)=([^;]+)/i', $h, $m) === 1) { + $cookies[$m[1]] = $m[2]; + } } if ($body === false) { @@ -216,6 +282,7 @@ function smoke_fetch(string $url): array return [ 'status' => $status, 'body' => '', + 'location' => $location, 'error' => $error['message'] ?? 'Unknown HTTP error', ]; } @@ -223,10 +290,69 @@ function smoke_fetch(string $url): array return [ 'status' => $status, 'body' => $body, + 'location' => $location, 'error' => null, ]; } +/** + * Legt einen eigenen Mandanten mit bekannten Zahlen an: + * - "Smoke Guthaben" +20,00 € Einzahlung, 25 Striche a 0,20 € = 15,00 € + * - "Smoke Schulden" keine Einzahlung, 20 Striche a 0,20 € = -4,00 € + * - "Smoke Ohne Buchungen" nichts = 0,00 € + * - "Smoke Inaktiv" inaktiv, darf in der Kaffeeliste fehlen + * + * @return array{tenant_id:int, participant_id:int} + */ +function smoke_seed(PDO $pdo, string $slug, string $email, string $password, string $suffix): array +{ + $pdo->prepare('INSERT INTO tenants (slug, name, status) VALUES (?, ?, ?)') + ->execute([$slug, 'HTTP-Smoke Mandant', 'active']); + $tenantId = (int)$pdo->lastInsertId(); + $pdo->prepare('INSERT INTO tenant_settings (tenant_id) VALUES (?)')->execute([$tenantId]); + + $pdo->prepare('INSERT INTO users (email, email_norm, display_name, password_hash, status) VALUES (?, ?, ?, ?, ?)') + ->execute([$email, $email, 'Smoke Owner', password_hash($password, PASSWORD_DEFAULT), 'active']); + $userId = (int)$pdo->lastInsertId(); + $pdo->prepare('INSERT INTO tenant_memberships (tenant_id, user_id, role, status, joined_at) VALUES (?, ?, ?, ?, NOW())') + ->execute([$tenantId, $userId, 'owner', 'active']); + + $insertParticipant = $pdo->prepare( + 'INSERT INTO participants (tenant_id, user_id, display_name, email, email_norm, active) VALUES (?, ?, ?, ?, ?, ?)' + ); + $ids = []; + foreach ([['Smoke Guthaben', $userId, 1], ['Smoke Schulden', null, 1], ['Smoke Ohne Buchungen', null, 1], ['Smoke Inaktiv', null, 0]] as [$name, $uid, $active]) { + $mail = strtolower(str_replace(' ', '-', $name)) . "-{$suffix}@test.local"; + $insertParticipant->execute([$tenantId, $uid, $name, $mail, $mail, $active]); + $ids[$name] = (int)$pdo->lastInsertId(); + } + + $payment = $pdo->prepare( + "INSERT INTO ledger_entries (tenant_id, participant_id, type, amount_cents, booked_at, source) VALUES (?, ?, 'payment', ?, NOW(), 'manual_bulk')" + ); + $consumption = $pdo->prepare( + "INSERT INTO ledger_entries (tenant_id, participant_id, type, amount_cents, marks_count, unit_price_cents, booked_at, source) VALUES (?, ?, 'consumption', ?, ?, 20, NOW(), 'manual_bulk')" + ); + $payment->execute([$tenantId, $ids['Smoke Guthaben'], 2000]); + $consumption->execute([$tenantId, $ids['Smoke Guthaben'], -500, 25]); + $consumption->execute([$tenantId, $ids['Smoke Schulden'], -400, 20]); + + return ['tenant_id' => $tenantId, 'participant_id' => $ids['Smoke Guthaben']]; +} + +function smoke_cleanup(PDO $pdo, ?int $tenantId, string $email): void +{ + if ($tenantId === null) { + return; + } + $pdo->prepare('DELETE FROM ledger_entries WHERE tenant_id = ?')->execute([$tenantId]); + $pdo->prepare('DELETE FROM participants WHERE tenant_id = ?')->execute([$tenantId]); + $pdo->prepare('DELETE FROM tenant_memberships WHERE tenant_id = ?')->execute([$tenantId]); + $pdo->prepare('DELETE FROM tenant_settings WHERE tenant_id = ?')->execute([$tenantId]); + $pdo->prepare('DELETE FROM tenants WHERE id = ?')->execute([$tenantId]); + $pdo->prepare('DELETE FROM users WHERE email_norm = ?')->execute([strtolower($email)]); +} + function smoke_url(string $baseUrl, string $path): string { return $baseUrl . '/' . ltrim($path, '/'); @@ -237,9 +363,45 @@ $passes = 0; echo "HTTP smoke base URL: {$baseUrl}\n"; +// Testmandant anlegen und per HTTP anmelden. +try { + $seeded = smoke_seed($pdo, $smokeSlug, $smokeEmail, $smokePassword, $suffix); + $smokeTenantId = $seeded['tenant_id']; +} catch (Throwable $e) { + fwrite(STDERR, "HTTP smoke setup failed: {$e->getMessage()}\n"); + exit(1); +} + +// Pfad der Teilnehmerauswertung steht erst nach dem Seeden fest. +foreach ($checks as $i => $check) { + if ($check['path'] === 'PLATZHALTER_TEILNEHMER') { + $checks[$i]['path'] = 'teilnehmerauswertung.php?participant_id=' . $seeded['participant_id']; + } +} + +$authCookies = []; +$loginPage = smoke_fetch(smoke_url($baseUrl, 'login.php'), $authCookies); +preg_match('/name="csrf_token" value="([^"]+)"/', $loginPage['body'], $csrfMatch); +smoke_fetch(smoke_url($baseUrl, 'login.php'), $authCookies, 'POST', http_build_query([ + 'csrf_token' => $csrfMatch[1] ?? '', + 'email' => $smokeEmail, + 'password' => $smokePassword, + 'tenant_slug' => $smokeSlug, +])); + +if (empty($authCookies)) { + smoke_cleanup($pdo, $smokeTenantId, $smokeEmail); + fwrite(STDERR, "HTTP smoke: Anmeldung fehlgeschlagen (keine Session).\n"); + exit(1); +} + foreach ($checks as $check) { $url = smoke_url($baseUrl, $check['path']); - $response = smoke_fetch($url); + // Angemeldete Seiten mit Session, alles andere bewusst ohne - nur so + // laesst sich der Login-Schutz ueberhaupt pruefen. + $needsAuth = !empty($check['auth']); + $jar = $needsAuth ? $authCookies : null; + $response = smoke_fetch($url, $jar); $label = $check['label'] . ' (' . $check['path'] . ')'; if ($response['error'] !== null) { @@ -248,6 +410,21 @@ foreach ($checks as $check) { continue; } + // Geschuetzte Seiten muessen ohne Session auf den Login umleiten. Das + // explizit zu pruefen ist belastbarer, als der Umleitung zu folgen und im + // Ergebnis nach dem Wort "Login" zu suchen. + if (isset($check['expect_redirect'])) { + $ziel = (string)$response['location']; + if ($response['status'] !== 302 || !str_contains($ziel, $check['expect_redirect'])) { + $failures[] = "{$label}: erwartete Umleitung auf {$check['expect_redirect']}, kam HTTP {$response['status']} nach '{$ziel}'"; + echo "FAIL {$label}\n"; + continue; + } + $passes++; + echo "PASS {$label}\n"; + continue; + } + if ($response['status'] !== 200) { $failures[] = "{$label}: expected HTTP 200, got HTTP {$response['status']}"; echo "FAIL {$label}\n"; @@ -308,6 +485,8 @@ foreach ($skippedUnsafe as $skip) { echo "SKIP {$skip['path']}: {$skip['reason']}\n"; } +smoke_cleanup($pdo, $smokeTenantId, $smokeEmail); + if ($failures !== []) { echo "\nHTTP smoke failed with " . count($failures) . " failure(s):\n"; foreach ($failures as $failure) { diff --git a/scripts/run-dev-server.sh b/scripts/run-dev-server.sh index 09f06dc..63408cc 100755 --- a/scripts/run-dev-server.sh +++ b/scripts/run-dev-server.sh @@ -9,7 +9,8 @@ PHP_LIB_DIR="$ROOT_DIR/.local/php/usr/lib/x86_64-linux-gnu" export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-$PHP_LIB_DIR}" export APP_DB_DRIVER="${APP_DB_DRIVER:-mysql}" export APP_ENV="${APP_ENV:-dev}" -export DEV_AUTH_EMAIL="${DEV_AUTH_EMAIL:-admin@test.local}" -export DEV_AUTH_NAME="${DEV_AUTH_NAME:-Test Admin}" +# Kein Auto-Login mehr: die Anmeldung laeuft auch lokal ueber login.php. +# DEV_AUTH_EMAIL/DEV_AUTH_NAME werden nur noch von scripts/init-mysql-dev.php +# ausgewertet, um den ersten Entwicklungsbenutzer anzulegen. exec "$PHP_BIN" -c "$PHP_INI" -S "${HOST:-127.0.0.1}:${PORT:-8080}" -t "$ROOT_DIR" diff --git a/stricheintragen.php b/stricheintragen.php index 1653765..9db19b4 100644 --- a/stricheintragen.php +++ b/stricheintragen.php @@ -29,14 +29,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - if (!$hasAccess) { echo "

    Kein Zugriff

    "; include "footer.php"; diff --git a/teilnehmerauswertung.php b/teilnehmerauswertung.php index 57ba055..1e88f00 100644 --- a/teilnehmerauswertung.php +++ b/teilnehmerauswertung.php @@ -28,14 +28,6 @@ if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $s $hasAccess = true; } -if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) { - $tenant = ledger_fetch_default_tenant($pdo); - if ($tenant !== null) { - $tenantId = (int)$tenant['id']; - $hasAccess = true; - } -} - $participant = $hasAccess ? ledger_fetch_participant_summary($pdo, $tenantId, $participantId) : null; @@ -69,14 +61,9 @@ function teilnehmerauswertung_date(string $value): string } } -function teilnehmerauswertung_current_name(?array $saasUser, mixed $conn, string $mailadress): string +function teilnehmerauswertung_current_name(?array $saasUser): string { - $name = trim((string)($saasUser['display_name'] ?? '')); - if ($name !== '') { - return $name; - } - - return trim((string)getUserName($conn, $mailadress)); + return trim((string)($saasUser['display_name'] ?? '')); } function teilnehmerauswertung_paypal_action(string $template, string $amount): string @@ -128,7 +115,7 @@ include "nav.php"; if ($hasAccess && $participant !== null) { $balanceCents = (int)$participant['balance_cents']; $balance = teilnehmerauswertung_money($balanceCents); - $currentName = teilnehmerauswertung_current_name($saasUser, $conn, $mailadress); + $currentName = teilnehmerauswertung_current_name($saasUser); $paypalEnabled = $settings !== null && (int)$settings['paypal_enabled'] === 1 && trim((string)$settings['paypal_url_template']) !== '';