169 lines
7.1 KiB
Markdown
169 lines
7.1 KiB
Markdown
---
|
|
plan_id: 20260712-1647-zapamietywanie-logowania
|
|
title: Zapamiętywanie logowania przez 30 dni
|
|
storage: plan-first
|
|
legacy_phase: null
|
|
created: 2026-07-12T16:47:19+02:00
|
|
status: planned
|
|
type: execute
|
|
autonomous: true
|
|
delegation: auto
|
|
files_modified:
|
|
- app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php
|
|
- app/Models/RememberTokenModel.php
|
|
- app/Controllers/Auth.php
|
|
- app/Filters/AuthFilter.php
|
|
- app/Views/auth/login.php
|
|
- tests/unit/RememberTokenModelTest.php
|
|
quality_radar: ok
|
|
---
|
|
|
|
<objective>
|
|
## Cel
|
|
Umożliwić użytkownikowi zaznaczenie opcji „Zapamiętaj mnie” podczas logowania i utrzymać dostęp przez 30 dni niezależnie na wielu komputerach.
|
|
|
|
## Powód
|
|
Obecna sesja wygasa po 2 godzinach i nie przeżywa zamknięcia przeglądarki. Osobny token dla każdego urządzenia zachowuje równoległe logowania bez współdzielenia jednego identyfikatora sesji.
|
|
|
|
## Wynik
|
|
Checkbox w formularzu, trwałe tokeny przechowywane w bazie wyłącznie jako skróty, automatyczne odtworzenie sesji oraz unieważnienie tokenu bieżącego urządzenia przy wylogowaniu.
|
|
</objective>
|
|
|
|
<context>
|
|
## Dokumenty projektu
|
|
@.paul/PROJECT.md
|
|
@.paul/STATE.md
|
|
@.paul/config.md
|
|
@.paul/codebase/impact_map.md
|
|
@.paul/codebase/quality_risks.md
|
|
|
|
## Pliki źródłowe
|
|
@app/Controllers/Auth.php
|
|
@app/Filters/AuthFilter.php
|
|
@app/Views/auth/login.php
|
|
@app/Config/Routes.php
|
|
@app/Config/Cookie.php
|
|
@app/Config/Session.php
|
|
</context>
|
|
|
|
<clarifications>
|
|
- „Wiele komputerów jednocześnie” oznacza osobny aktywny token na każdym urządzeniu; kolejne logowanie nie usuwa wcześniejszych tokenów.
|
|
- Wylogowanie usuwa token tylko z bieżącego urządzenia. Globalne „wyloguj wszędzie” jest poza zakresem.
|
|
</clarifications>
|
|
|
|
<impact_scan>
|
|
## Quality Radar
|
|
|
|
**Status:** ok
|
|
**Narzędzia:** codebase-memory-mcp 0.6.1; jscpd i ast-grep wyłączone polityką projektu.
|
|
|
|
## Dotknięte obszary
|
|
- Logowanie: `Auth::login`, `Auth::logout`, `app/Views/auth/login.php`.
|
|
- Ochrona tras: `AuthFilter::before` odtwarza zwykłą sesję po poprawnym tokenie.
|
|
- Dane: nowa tabela tokenów z wieloma rekordami; konto nadal pochodzi z `.env`.
|
|
- Wdrożenie: nowa migracja wymaga ręcznego uruchomienia na hostido.
|
|
|
|
## Ryzyka duplikacji / wartości hardcoded
|
|
- Czas 30 dni ma jedno źródło prawdy w `RememberTokenModel`.
|
|
- Token cookie nie może być zapisany jawnie w bazie; tabela przechowuje selektor i hash walidatora.
|
|
- Nie wydłużać globalnie `Session::$expiration`, bo nie zapewnia niezależnych urządzeń.
|
|
|
|
## Jawne odroczenia
|
|
- Panel urządzeń i „wyloguj wszędzie” — dodać dopiero na żądanie.
|
|
- Harmonogram czyszczenia — przy tej skali wygasłe tokeny wystarczy usuwać podczas użycia mechanizmu.
|
|
</impact_scan>
|
|
|
|
<acceptance_criteria>
|
|
|
|
## AC-1: Logowanie bez zapamiętania
|
|
```gherkin
|
|
Given użytkownik nie zaznaczył „Zapamiętaj mnie”
|
|
When poda poprawny email i hasło
|
|
Then otrzymuje wyłącznie obecną sesję bez trwałego cookie logowania
|
|
```
|
|
|
|
## AC-2: Logowanie zapamiętane przez 30 dni
|
|
```gherkin
|
|
Given użytkownik zaznaczył „Zapamiętaj mnie”
|
|
When poda poprawny email i hasło
|
|
Then aplikacja zapisuje bezpieczny token i cookie ważne 30 dni
|
|
And po utracie zwykłej sesji poprawny token odtwarza sesję i wpuszcza na chronioną trasę
|
|
```
|
|
|
|
## AC-3: Wiele urządzeń
|
|
```gherkin
|
|
Given użytkownik zaznaczył opcję na dwóch urządzeniach
|
|
When oba urządzenia otwierają chronioną trasę bez zwykłej sesji
|
|
Then oba niezależne tokeny pozostają poprawne
|
|
And wylogowanie na jednym urządzeniu nie unieważnia drugiego
|
|
```
|
|
|
|
## AC-4: Odrzucenie nieważnego tokenu
|
|
```gherkin
|
|
Given cookie jest zmienione, wygasłe lub nie ma odpowiadającego rekordu
|
|
When użytkownik otwiera chronioną trasę
|
|
Then cookie i wadliwy rekord są usuwane w możliwym zakresie
|
|
And użytkownik trafia na `/login`
|
|
```
|
|
|
|
</acceptance_criteria>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Dodać bezpieczne tokeny per urządzenie</name>
|
|
<files>app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php, app/Models/RememberTokenModel.php</files>
|
|
<action>Utworzyć tabelę z unikalnym selektorem, hashem walidatora, `expires_at` i timestampami. W modelu umieścić stałą 30 dni oraz operacje wystawienia tokenu przez `random_bytes`, weryfikacji przez `hash_equals`, usunięcia bieżącego tokenu i wygasłych rekordów. Każde logowanie dopisuje rekord.</action>
|
|
<verify>php -l app/Database/Migrations/2026-07-12-160001_CreateRememberTokens.php; php -l app/Models/RememberTokenModel.php</verify>
|
|
<done>AC-2, AC-3 i AC-4 mają trwały mechanizm danych bez jawnych sekretów w bazie.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Podłączyć checkbox, odtworzenie sesji i wylogowanie</name>
|
|
<files>app/Controllers/Auth.php, app/Filters/AuthFilter.php, app/Views/auth/login.php</files>
|
|
<action>Dodać checkbox `remember`. Po poprawnym logowaniu tworzyć cookie tylko po zaznaczeniu. W filtrze zachować obecną ścieżkę sesji, a przy jej braku zweryfikować cookie i ustawić `logged_in`/`user_email`. Cookie: HttpOnly, SameSite=Lax, 30 dni, Secure w produkcji. `logout()` usuwa token bieżącego cookie, cookie i sesję.</action>
|
|
<verify>php -l app/Controllers/Auth.php; php -l app/Filters/AuthFilter.php; php -l app/Views/auth/login.php</verify>
|
|
<done>AC-1..AC-4 są obsłużone w przepływie HTTP.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Sprawdzić bezpieczeństwo i równoległe urządzenia</name>
|
|
<files>tests/unit/RememberTokenModelTest.php</files>
|
|
<action>Dodać jeden mały test obejmujący dwa jednocześnie poprawne tokeny, odrzucenie zmienionego walidatora oraz unieważnienie jednego bez wpływu na drugi. Wykonać UAT w dwóch profilach przeglądarki.</action>
|
|
<verify>vendor/bin/phpunit tests/unit/RememberTokenModelTest.php; ręcznie: dwa profile przeglądarki zgodnie z AC-1..AC-4</verify>
|
|
<done>AC-1..AC-4 mają automatyczną kontrolę tokenów i potwierdzenie przepływu przeglądarkowego.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<boundaries>
|
|
## Nie zmieniać
|
|
- Hasło i email nadal pochodzą z `.env`; nie tworzyć systemu wielu kont.
|
|
- Nie zmieniać czasu zwykłej sesji ani chronionych tras.
|
|
- Nie dotykać modułów finansów, inwestycji i paragonów.
|
|
|
|
## Ograniczenia zakresu
|
|
- Bez nowej zależności, panelu urządzeń, resetu hasła i „wyloguj wszędzie”.
|
|
- Bez surowego tokenu lub hasła w bazie i logach.
|
|
</boundaries>
|
|
|
|
<verification>
|
|
- [ ] `php -l` przechodzi dla zmienionych plików PHP.
|
|
- [ ] `vendor/bin/phpunit tests/unit/RememberTokenModelTest.php` przechodzi w środowisku z `vendor/`.
|
|
- [ ] UAT potwierdza zwykłe logowanie, 30-dniowe cookie, dwa profile, wylogowanie jednego profilu i odrzucenie zmienionego cookie.
|
|
- [ ] Cookie ma HttpOnly, SameSite=Lax, właściwy termin i Secure na produkcji.
|
|
- [ ] Migracja jest zastosowana ręcznie na zdalnej bazie przed wdrożeniem kodu.
|
|
- [ ] Ryzyka Quality Radar są obsłużone lub jawnie odroczone.
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- [ ] Wszystkie AC przechodzą.
|
|
- [ ] Weryfikacja jest kompletna.
|
|
- [ ] Dwa urządzenia pozostają zalogowane niezależnie przez maksymalnie 30 dni.
|
|
- [ ] Baza nie zawiera surowych tokenów.
|
|
</success_criteria>
|
|
|
|
<output>
|
|
SUMMARY.md path: `.paul/plans/20260712-1647-zapamietywanie-logowania/SUMMARY.md`
|
|
</output>
|