Zwei vorbestehende, bislang rote Pruefungen behoben.
1) PHP lief in UTC, MySQL in der System-Zeitzone (hier CEST, +2h). Ueberall,
wo ein in PHP berechneter Zeitstempel gegen MySQL NOW() verglichen wird,
liefen die Uhren dadurch gegeneinander:
- Hinweise mit kurzer Restlaufzeit galten sofort als abgelaufen
(notices: valid_from = NOW() aus MySQL, valid_until aus PHP date()).
- Auth-Token (Passwort-Reset, E-Mail-Verifikation) liefen bis zu 2h zu
frueh ab (expires_at aus PHP date(), Pruefung gegen NOW()).
bootstrap.php pinnt die PHP-Zeitzone jetzt deterministisch aus
APP_TIMEZONE (Standard Europe/Berlin), app_db_pdo() setzt die DB-Session
per numerischem Offset auf dieselbe Zeit. Damit stimmen beide Uhren
ueberein. Behebt check-m8-tenant-isolation (11/1 -> 12/0).
2) check-m3-settings-flow stammte aus M3 und lieferte nicht die spaeter
hinzugekommenen Pflichtfelder (pdf_row_height_px,
payment_reminder_interval_days). Dadurch schlug bereits das Update fehl und
alle Folge-Assertions kippten. Der Test sendet jetzt den vollstaendigen
Feldsatz wie das Einstellungsformular und prueft die beiden Felder mit.
Die Update-Funktion selbst war korrekt (7/6 -> 15/0).
Voller Regressionslauf gruen: http-smoke 33/0, role-matrix 55/0,
tenant-isolation 12/0, m3-auth 9/0, password-email 14/0, settings 15/0,
tenant-resolution 12/0, billing 10/0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
123 lines
4.8 KiB
PHP
123 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require __DIR__ . '/dev-db.php';
|
|
require __DIR__ . '/../app/saas-auth.php';
|
|
|
|
function settings_check_assert(string $label, bool $condition, array &$failures, int &$passes): void
|
|
{
|
|
if ($condition) {
|
|
$passes++;
|
|
echo "PASS {$label}\n";
|
|
return;
|
|
}
|
|
|
|
$failures[] = $label;
|
|
echo "FAIL {$label}\n";
|
|
}
|
|
|
|
function settings_check_cleanup(PDO $pdo, string $slug, string $emailNorm): void
|
|
{
|
|
$stmt = $pdo->prepare('SELECT id FROM tenants WHERE slug = ?');
|
|
$stmt->execute([$slug]);
|
|
$tenantId = $stmt->fetchColumn();
|
|
|
|
if ($tenantId !== false) {
|
|
$tenantId = (int)$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([$emailNorm]);
|
|
}
|
|
|
|
$pdo = dev_pdo();
|
|
dev_apply_schema($pdo);
|
|
|
|
$slug = 'm3-settings-flow-check';
|
|
$email = 'm3-settings-flow-check@test.local';
|
|
$emailNorm = saas_email_norm($email);
|
|
$password = 'M3-settings-flow-123';
|
|
$failures = [];
|
|
$passes = 0;
|
|
|
|
settings_check_cleanup($pdo, $slug, $emailNorm);
|
|
|
|
$registration = saas_register_tenant_owner($pdo, [
|
|
'tenant_name' => 'M3 Settings Flow Check',
|
|
'tenant_slug' => $slug,
|
|
'display_name' => 'M3 Settings Check',
|
|
'email' => $email,
|
|
'password' => $password,
|
|
'password_confirm' => $password,
|
|
]);
|
|
|
|
settings_check_assert('registration succeeds', $registration['ok'] === true, $failures, $passes);
|
|
|
|
if ($registration['ok']) {
|
|
$identity = $registration['identity'];
|
|
$tenantId = (int)$identity['tenant_id'];
|
|
settings_check_assert('owner can manage settings', saas_can_manage_tenant_settings($identity), $failures, $passes);
|
|
settings_check_assert(
|
|
'member cannot manage settings',
|
|
!saas_can_manage_tenant_settings(['role' => 'member']),
|
|
$failures,
|
|
$passes
|
|
);
|
|
|
|
$settings = saas_fetch_tenant_settings($pdo, $tenantId);
|
|
settings_check_assert('settings can be fetched', $settings !== null, $failures, $passes);
|
|
if ($settings !== null) {
|
|
settings_check_assert('default mark price is 20 cents', $settings['mark_price_cents'] === 20, $failures, $passes);
|
|
}
|
|
|
|
// Vollstaendiger Feldsatz wie ihn das Einstellungsformular sendet - die
|
|
// Update-Funktion erwartet auch die spaeter hinzugekommenen Pflichtfelder
|
|
// (pdf_row_height_px, payment_reminder_interval_days).
|
|
$update = saas_update_tenant_settings($pdo, $tenantId, [
|
|
'tenant_name' => 'M3 Settings Flow Updated',
|
|
'timezone' => 'Europe/Berlin',
|
|
'locale' => 'de-DE',
|
|
'currency_code' => 'EUR',
|
|
'mark_price' => '0,35',
|
|
'sheet_window_days' => '90',
|
|
'negative_warning' => '12,50',
|
|
'paypal_url_template' => 'https://paypal.example/m3/',
|
|
'self_entry_enabled' => '1',
|
|
'paypal_enabled' => '1',
|
|
'pdf_split_mode' => 'alphabetical',
|
|
'pdf_row_height_px' => '18',
|
|
'payment_reminder_interval_days' => '14',
|
|
]);
|
|
|
|
settings_check_assert('settings update succeeds', $update['ok'] === true, $failures, $passes);
|
|
|
|
$updated = saas_fetch_tenant_settings($pdo, $tenantId);
|
|
settings_check_assert('updated settings can be fetched', $updated !== null, $failures, $passes);
|
|
if ($updated !== null) {
|
|
settings_check_assert('tenant name is updated', $updated['name'] === 'M3 Settings Flow Updated', $failures, $passes);
|
|
settings_check_assert('mark price is updated', $updated['mark_price_cents'] === 35, $failures, $passes);
|
|
settings_check_assert('sheet window is updated', $updated['sheet_window_days'] === 90, $failures, $passes);
|
|
settings_check_assert('negative warning is stored negative', $updated['negative_warning_cents'] === -1250, $failures, $passes);
|
|
settings_check_assert('paypal is enabled', $updated['paypal_enabled'] === 1, $failures, $passes);
|
|
settings_check_assert('self entry is enabled', $updated['self_entry_enabled'] === 1, $failures, $passes);
|
|
settings_check_assert('pdf row height is updated', (int)$updated['pdf_row_height_px'] === 18, $failures, $passes);
|
|
settings_check_assert('reminder interval is updated', (int)$updated['payment_reminder_interval_days'] === 14, $failures, $passes);
|
|
}
|
|
}
|
|
|
|
settings_check_cleanup($pdo, $slug, $emailNorm);
|
|
|
|
if ($failures !== []) {
|
|
echo "\nM3 settings flow check failed with " . count($failures) . " failure(s):\n";
|
|
foreach ($failures as $failure) {
|
|
echo "- {$failure}\n";
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
echo "\nM3 settings flow check passed with {$passes} assertions.\n";
|