Files
cmsPRO/.paul/phases/02-shared-email-security/02-01-PLAN.md
Jacek Pyziak 3325eaf44c refactor: centralny autoloader, Shared\Email i Shared\Security
- Utworzono autoload/autoloader.php (hybrydowy PSR-4 + legacy)
- Zmigrowano 7 entry pointów do centralnego autoloadera
- Dodano PSR-4 mapowanie w composer.json (Domain, Shared, Admin, Frontend)
- Utworzono Shared\Email\Email (PHPMailer, migracja z Helpers)
- Utworzono Shared\Security\CsrfToken (random_bytes + hash_equals)
- Wrappery w Helpers delegują do nowych klas
- Zaktualizowano docs/PROJECT_STRUCTURE.md
- Inicjalizacja PAUL (.paul/) z roadmapą 19 faz refaktoryzacji

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 17:28:01 +02:00

183 lines
6.7 KiB
Markdown

---
phase: 02-shared-email-security
plan: 01
type: execute
wave: 1
depends_on: ["01-01"]
files_modified:
- autoload/Shared/Email/Email.php
- autoload/Shared/Security/CsrfToken.php
- autoload/Shared/Helpers/Helpers.php
autonomous: true
delegation: off
---
<objective>
## Goal
Utworzyć Shared\Email\Email i Shared\Security\CsrfToken wzorując się na shopPRO. Przenieść logikę z Helpers::send_email() i Helpers::get_token()/is_token_valid() do dedykowanych klas. Zachować wrappery w Helpers dla kompatybilności.
## Purpose
Email i Security to brakujące moduły Shared potrzebne przed refaktoryzacją Admin i Frontend kontrolerów. CsrfToken z kryptograficznie bezpiecznym tokenem zastąpi słaby sha1(mt_rand()).
## Output
- autoload/Shared/Email/Email.php — klasa email z PHPMailer
- autoload/Shared/Security/CsrfToken.php — CSRF z random_bytes + hash_equals
- Wrappery w Helpers.php delegujące do nowych klas
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
## Prior Work
@.paul/phases/01-infrastructure/01-01-SUMMARY.md — autoloader gotowy, PSR-4 działa
## Source Files
@autoload/Shared/Helpers/Helpers.php — zawiera send_email(), get_token(), is_token_valid()
## Reference
shopPRO autoload/Shared/Email/Email.php — docelowa implementacja
shopPRO autoload/Shared/Security/CsrfToken.php — docelowa implementacja
</context>
<acceptance_criteria>
## AC-1: Email class
```gherkin
Given plik autoload/Shared/Email/Email.php istnieje
When załaduję klasę Shared\Email\Email
Then klasa ma metody: send(), email_check(), load_by_name()
And send() używa PHPMailer do wysyłki maili
```
## AC-2: CsrfToken class
```gherkin
Given plik autoload/Shared/Security/CsrfToken.php istnieje
When załaduję klasę Shared\Security\CsrfToken
Then klasa ma statyczne metody: getToken(), validate(), regenerate()
And getToken() używa bin2hex(random_bytes(32))
And validate() używa hash_equals() (timing-safe)
```
## AC-3: Wrappery w Helpers
```gherkin
Given Helpers::send_email() i Helpers::get_token() nadal istnieją
When wywołam je z istniejącego kodu
Then delegują do nowych klas (Shared\Email\Email i Shared\Security\CsrfToken)
And istniejący kod działa bez zmian
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Utworzenie Shared\Email\Email</name>
<files>autoload/Shared/Email/Email.php</files>
<action>
Utworzyć klasę Email wzorowaną na shopPRO:
- namespace Shared\Email
- Właściwość $table = 'pp_newsletter_templates'
- Właściwość $text (treść maila), $headers, $newsletter_headers, $newsletter_footers
- Metoda load_by_name(string $name) — ładuje szablon z DB
- Metoda email_check($email) — walidacja filter_var
- Metoda send(string $email, string $subject, bool $newsletter_headers = false, string $file = null)
- Używa PHPMailer (require_once z libraries/)
- Regex do naprawy relatywnych URL w obrazkach/linkach
- Obsługa załączników
- Return $mail->Send()
WAŻNE: Sprawdzić w Helpers.php jak wygląda obecna implementacja send_email()
i przenieść tę logikę do nowej klasy, dostosowując do wzorca shopPRO.
PHP < 8.0 — brak named args, union types, match.
</action>
<verify>Sprawdzić że plik istnieje, ma namespace Shared\Email, klasę Email z metodami send(), email_check()</verify>
<done>AC-1 satisfied: Email class z PHPMailer</done>
</task>
<task type="auto">
<name>Task 2: Utworzenie Shared\Security\CsrfToken</name>
<files>autoload/Shared/Security/CsrfToken.php</files>
<action>
Utworzyć klasę CsrfToken wzorowaną na shopPRO:
- namespace Shared\Security
- const SESSION_KEY = 'csrf_token'
- static getToken(): string
- Jeśli brak tokenu w sesji → generuje bin2hex(random_bytes(32))
- Zapisuje w $_SESSION[self::SESSION_KEY]
- Zwraca token
- static validate(string $token): bool
- Porównuje z $_SESSION[self::SESSION_KEY] używając hash_equals()
- Return true/false (NIE usuwać tokenu po walidacji — to robi regenerate())
- static regenerate(): void
- Wymusza nowy token: unset($_SESSION[self::SESSION_KEY])
PHP < 8.0 — brak named args, union types, match.
</action>
<verify>Sprawdzić że plik istnieje, ma namespace Shared\Security, klasę CsrfToken z metodami getToken(), validate(), regenerate()</verify>
<done>AC-2 satisfied: CsrfToken z random_bytes + hash_equals</done>
</task>
<task type="auto">
<name>Task 3: Wrappery w Helpers.php</name>
<files>autoload/Shared/Helpers/Helpers.php</files>
<action>
W klasie Helpers:
1. Metoda send_email() — zamienić ciało na delegację:
$email = new \Shared\Email\Email();
$email->text = $text;
return $email->send($to, $subject, false, $file);
2. Metoda get_token() — zamienić ciało na delegację:
return \Shared\Security\CsrfToken::getToken();
3. Metoda is_token_valid() — zamienić ciało na delegację:
return \Shared\Security\CsrfToken::validate($token);
Zachować sygnatury metod identyczne — żaden calling code się nie zmienia.
NIE usuwać metod — to wrappery dla kompatybilności wstecznej.
NIE zmieniać żadnych innych metod w Helpers.
</action>
<verify>Sprawdzić że Helpers::send_email(), get_token(), is_token_valid() delegują do nowych klas</verify>
<done>AC-3 satisfied: Wrappery delegują, istniejący kod działa bez zmian</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- autoload/Domain/* (nie ruszać repositories)
- autoload/Shared/Cache/* (nie ruszać)
- autoload/Shared/Html/* (nie ruszać)
- autoload/Shared/Image/* (nie ruszać)
- autoload/Shared/Tpl/* (nie ruszać)
- config.php, libraries/* (nie ruszać)
## SCOPE LIMITS
- Tylko Email i Security — nie refaktoryzować innych metod Helpers
- Nie zmieniać callerów (admin/, front/) — oni nadal używają Helpers::
- Nie dodawać nowych zależności poza tym co już jest w libraries/
</boundaries>
<verification>
Before declaring plan complete:
- [ ] autoload/Shared/Email/Email.php istnieje z namespace Shared\Email
- [ ] autoload/Shared/Security/CsrfToken.php istnieje z namespace Shared\Security
- [ ] Helpers::send_email() deleguje do Email class
- [ ] Helpers::get_token() deleguje do CsrfToken::getToken()
- [ ] Helpers::is_token_valid() deleguje do CsrfToken::validate()
- [ ] Żadne inne metody w Helpers nie zostały zmienione
- All acceptance criteria met
</verification>
<success_criteria>
- Email i CsrfToken klasy utworzone z poprawnymi namespace'ami
- Wrappery w Helpers zachowują kompatybilność wsteczną
- Zero regresji — istniejący kod używający Helpers:: działa bez zmian
</success_criteria>
<output>
After completion, create `.paul/phases/02-shared-email-security/02-01-SUMMARY.md`
</output>