test(auth): giris akisi sozlesme regresyon testi (E2E, gercek isleyici) - #7
test(auth): giris akisi sozlesme regresyon testi (E2E, gercek isleyici)
#7ersinkoc wants to merge 1 commit into
Conversation
Test-only degisiklik: uretim koduna dokunulmadi. round-7 E2E avindan kalicilastirilan giris akisi sozlesme testi. Cocuk sureclerde GERCEK auth/authenticate.php calisir (gercek oturum + CSRF + veritabani; web ortami yalnizca $_SERVER/$_POST ile simule edilir); isci script calisma aninda repo disinda uretilir, dosya tamamen kendi kendine yeter. Kapsanan sozlesme: - gecersiz CSRF -> 403 ABORT, hicbir DB yan etkisi yok - gecerli giris -> last_login_at + basarili deneme satiri + login audit - yanlis parola -> basarisiz satir + login_failed - ardan basarili giris -> e-postanin basarisiz satirlari silinir - max_login_attempts (ayarlardan okunur) sonrasi DOGRU parola bile reddedilir; rate-limit yolu YENI deneme satiri yazmaz - pasif hesap -> login_disabled_account + basarisiz satir users (parola hash'i dahil - isleyici giriste yeniden hashleyebilir) / login_attempts / audit_logs anlik goruntusu alinir ve sonda geri yuklenir; bolum 5 geri yuklemeyi kendini dogrular. Dogrulama: 9 OK / 0 FAIL; php -l temiz. Yerel MariaDB ister (docker run -d --name riskops-mariadb ... mariadb:10.11 + config/database.php); sunucu yoksa test acikca basarisiz olur.
There was a problem hiding this comment.
4 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tools/login_flow_test.php">
<violation number="1" location="tools/login_flow_test.php:107">
P2: The test ignores `config/database.php` and always connects with the hard-coded `riskops_local_dev` password. It therefore fails on the documented installation unless the local database happens to use these exact credentials; load the application database configuration instead.</violation>
<violation number="2" location="tools/login_flow_test.php:122">
P2: If the admin hash needs rehashing, running this test permanently changes `password_changed_at` despite the advertised full restoration. Snapshot and restore `password_changed_at` together with the password.</violation>
<violation number="3" location="tools/login_flow_test.php:131">
P1: When the application is used concurrently, this cleanup deletes unrelated audit and login-attempt records and overwrites concurrent user changes. Run against an isolated database or tag and restore only records created by this test.</violation>
<violation number="4" location="tools/login_flow_test.php:207">
P1: The section-1 valid-login check asserts `$successRows === 1`, but `$successRows` counts every successful `login_attempts` row ever written for `admin@riskops.local` (no `id` or `ip_address` filter). Any dev DB where the admin has logged in before — via the web UI, another test IP, or a prior run — already has successful rows, so this check always fails and the whole test reports false FAIL on a non-fresh database. Restrict the count to rows created by this run, e.g. `AND id > {$laMax}` (or `AND ip_address = '127.0.0.7'`), consistent with the snapshot/restore boundary.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| $pdo->exec("DELETE FROM users WHERE email LIKE 'login-flow-test.%@riskops.local'"); | ||
| $pdo->prepare('DELETE FROM login_attempts WHERE id > :m OR ip_address = :ip') | ||
| ->execute([':m' => $laMax, ':ip' => '127.0.0.7']); | ||
| $pdo->prepare('DELETE FROM audit_logs WHERE id > :m')->execute([':m' => $auMax]); |
There was a problem hiding this comment.
P1: When the application is used concurrently, this cleanup deletes unrelated audit and login-attempt records and overwrites concurrent user changes. Run against an isolated database or tag and restore only records created by this test.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/login_flow_test.php, line 131:
<comment>When the application is used concurrently, this cleanup deletes unrelated audit and login-attempt records and overwrites concurrent user changes. Run against an isolated database or tag and restore only records created by this test.</comment>
<file context>
@@ -0,0 +1,309 @@
+ $pdo->exec("DELETE FROM users WHERE email LIKE 'login-flow-test.%@riskops.local'");
+ $pdo->prepare('DELETE FROM login_attempts WHERE id > :m OR ip_address = :ip')
+ ->execute([':m' => $laMax, ':ip' => '127.0.0.7']);
+ $pdo->prepare('DELETE FROM audit_logs WHERE id > :m')->execute([':m' => $auMax]);
+ $upd = $pdo->prepare(
+ 'UPDATE users SET password = :p, status = :s, must_change_password = :mcp,
</file context>
| $code === 0 && last_login_of($pdo, $adminEmail) >= $t0 && $successRows === 1 | ||
| && in_array('login', audits_since($pdo, $auMax), true), |
There was a problem hiding this comment.
P1: The section-1 valid-login check asserts $successRows === 1, but $successRows counts every successful login_attempts row ever written for admin@riskops.local (no id or ip_address filter). Any dev DB where the admin has logged in before — via the web UI, another test IP, or a prior run — already has successful rows, so this check always fails and the whole test reports false FAIL on a non-fresh database. Restrict the count to rows created by this run, e.g. AND id > {$laMax} (or AND ip_address = '127.0.0.7'), consistent with the snapshot/restore boundary.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/login_flow_test.php, line 207:
<comment>The section-1 valid-login check asserts `$successRows === 1`, but `$successRows` counts every successful `login_attempts` row ever written for `admin@riskops.local` (no `id` or `ip_address` filter). Any dev DB where the admin has logged in before — via the web UI, another test IP, or a prior run — already has successful rows, so this check always fails and the whole test reports false FAIL on a non-fresh database. Restrict the count to rows created by this run, e.g. `AND id > {$laMax}` (or `AND ip_address = '127.0.0.7'`), consistent with the snapshot/restore boundary.</comment>
<file context>
@@ -0,0 +1,309 @@
+ "SELECT COUNT(*) FROM login_attempts WHERE success = 1 AND email = '{$adminEmail}'"
+ )->fetchColumn();
+ check('gecerli giris: last_login_at + basarili satir + login audit',
+ $code === 0 && last_login_of($pdo, $adminEmail) >= $t0 && $successRows === 1
+ && in_array('login', audits_since($pdo, $auMax), true),
+ 'll=' . last_login_of($pdo, $adminEmail) . ' ok_rows=' . $successRows);
</file context>
| $code === 0 && last_login_of($pdo, $adminEmail) >= $t0 && $successRows === 1 | |
| && in_array('login', audits_since($pdo, $auMax), true), | |
| $successRows = (int)$pdo->query( | |
| "SELECT COUNT(*) FROM login_attempts WHERE success = 1 AND email = '{$adminEmail}' AND id > {$laMax}" | |
| )->fetchColumn(); |
| /* --- Snapshot ---------------------------------------------------------- */ | ||
|
|
||
| $usersSnap = $pdo->query( | ||
| 'SELECT id, password, status, must_change_password, last_login_at FROM users ORDER BY id' |
There was a problem hiding this comment.
P2: If the admin hash needs rehashing, running this test permanently changes password_changed_at despite the advertised full restoration. Snapshot and restore password_changed_at together with the password.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/login_flow_test.php, line 122:
<comment>If the admin hash needs rehashing, running this test permanently changes `password_changed_at` despite the advertised full restoration. Snapshot and restore `password_changed_at` together with the password.</comment>
<file context>
@@ -0,0 +1,309 @@
+/* --- Snapshot ---------------------------------------------------------- */
+
+$usersSnap = $pdo->query(
+ 'SELECT id, password, status, must_change_password, last_login_at FROM users ORDER BY id'
+)->fetchAll();
+$laMax = (int)$pdo->query('SELECT COALESCE(MAX(id),0) FROM login_attempts')->fetchColumn();
</file context>
| $pdo = new PDO( | ||
| 'mysql:host=127.0.0.1;port=3306;dbname=riskops;charset=utf8mb4', | ||
| 'riskops_user', | ||
| 'riskops_local_dev', |
There was a problem hiding this comment.
P2: The test ignores config/database.php and always connects with the hard-coded riskops_local_dev password. It therefore fails on the documented installation unless the local database happens to use these exact credentials; load the application database configuration instead.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/login_flow_test.php, line 107:
<comment>The test ignores `config/database.php` and always connects with the hard-coded `riskops_local_dev` password. It therefore fails on the documented installation unless the local database happens to use these exact credentials; load the application database configuration instead.</comment>
<file context>
@@ -0,0 +1,309 @@
+ $pdo = new PDO(
+ 'mysql:host=127.0.0.1;port=3306;dbname=riskops;charset=utf8mb4',
+ 'riskops_user',
+ 'riskops_local_dev',
+ [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
</file context>
Amaç
Yalnızca test — üretim koduna dokunulmadı. Giriş akışının belgelenmiş sözleşmesine uçtan uca regresyon kapsamı: round-7 E2E avının (giriş yolunda defect bulunamadı) kalıcılaştırılmış hali.
Yöntem
Test, gerçek
auth/authenticate.phpişleyicisini çocuk süreçlerde çalıştırır:$_SERVER/$_POSTile simüle edilir (sabit test IP'si127.0.0.7— sayaç izolasyonu),csrf_require/auth_start/flashüretimdeki gibi çalışır;redirect()exit(0),app_abortSTDERR'daABORT <kod>+ exit(1),users(parola hash'i dahil — işleyici geçerli girişte hash'iPASSWORD_DEFAULT'a yeniden hesaplayabilir) /login_attempts/audit_logsanlık görüntüsü alınır, sonda geri yüklenir; bölüm 5 geri yüklemeyi kendini doğrular.Kapsanan sözleşme
users.last_login_atgüncellenir + başarılı deneme satırı +loginaudit.login_failedaudit.max_login_attempts(ayarlardan okunur, sabit kodlanmaz) başarısız denemeden sonra doğru parola bile reddedilir; rate-limit yolu yeni deneme satırı yazmaz.login_disabled_account+ başarısız satır.Doğrulama
php tools/login_flow_test.php→ 9 OK / 0 FAIL (geri yükleme kontrolleri dahil).php -ltemiz.docker run -d --name riskops-mariadb ... mariadb:10.11+config/database.php). Sunucu yoksa test açıkça başarısız olur — sessiz geçiş yok.Kapsam çiti
Bu PR yalnızca
tools/login_flow_test.phpdosyasını ekler. Dal doğrudanmainüzerindendir; açık diğer PR'lere bağımlılığı yoktur.Summary by cubic
Adds a login-flow contract regression test that runs the real
auth/authenticate.phpin child processes with real sessions, CSRF tokens, and database state. Test-only; no production code changes.max_login_attemptsfrom settings and verifies the rate-limit path writes no new attempt row.users(password hashes included, since the handler may rehash),login_attempts, andaudit_logs, restores them afterward, and validates the restore.php tools/login_flow_test.php: 9 OK / 0 FAIL and cleanphp -l.Written for commit 3d22ec5. Summary will update on new commits.