# SZCZEGÓŁOWA ANALIZA KODU - IPTV Panel
**Data analizy:** 23.12.2025

---

## 📊 STATYSTYKI PROJEKTU

### Rozmiar kodu
| Typ | Pliki | Linii kodu |
|-----|-------|------------|
| PHP (kontrolery) | 16 | ~3,800 |
| PHP (klasy/modele) | 12 | ~6,900 |
| PHP (pozostałe) | 5 | ~600 |
| Szablony Smarty | 35+ | ~6,400 |
| CSS | 1 | ~800 |
| JavaScript | 1 | ~200 |
| **SUMA** | **~70** | **~18,700** |

### Największe pliki (potencjalne do refaktoryzacji)
1. `AdminController.php` - 1,121 linii ⚠️
2. `PlaylistController.php` - 814 linii ⚠️
3. `Playlist.php` - 693 linii
4. `User.php` - 642 linii
5. `layout.tpl` - 665 linii
6. `dashboard.tpl` - 598 linii

---

## 🔴 PROBLEMY KRYTYCZNE (Security)

### S1. Brak Rate Limiting na API
**Lokalizacja:** `api/playlist.php`
**Problem:** Endpoint API nie ma żadnego throttlingu
**Ryzyko:** DoS, brute-force na MAC/CODE
**Rozwiązanie:**
```php
// Dodać na początku api/playlist.php
$rateLimiter = new RateLimiter();
if (!$rateLimiter->checkApiLimit($_SERVER['REMOTE_ADDR'], 100, 60)) {
    http_response_code(429);
    exit('Too Many Requests');
}
```

### S2. Słabe szyfrowanie API (XOR)
**Lokalizacja:** `api/playlist.php:79-93`
**Problem:** XOR jest trywialnie odwracalny
**Ryzyko:** Przechwycenie danych playlist
**Rozwiązanie:** AES-256-GCM lub podpisywanie JWT

### S3. Brak nagłówków bezpieczeństwa
**Lokalizacja:** `layout.tpl`, `index.php`
**Problem:** Brak CSP, X-Frame-Options, HSTS
**Rozwiązanie:**
```php
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');
header("Content-Security-Policy: default-src 'self'; ...");
```

### S4. Session Fixation potencjalny
**Lokalizacja:** `Auth.php:44`
**Problem:** Brak regeneracji session ID po logowaniu
**Rozwiązanie:** Dodać `session_regenerate_id(true)` po udanym logowaniu

### S5. Brak szyfrowania wrażliwych danych w DB
**Lokalizacja:** `playlists.config_json`
**Problem:** Hasła Xtream/Stalker w plain text
**Rozwiązanie:** Szyfrować AES przed zapisem, deszyfrować przy odczycie

### S6. Brak 2FA
**Problem:** Tylko hasło chroni konta admin/reseller
**Rozwiązanie:** TOTP (Google Authenticator)

---

## 🟠 PROBLEMY ŚREDNIE (Code Quality)

### Q1. AdminController za duży (1,121 linii)
**Problem:** God Object - robi za dużo
**Rozwiązanie:** Podzielić na:
- `SettingsController` - konfiguracja
- `MonitorController` - monitoring serwera
- `CronController` - zadania cron
- `BackupController` - backupy
- `ToolsController` - narzędzia

### Q2. Brak interfejsów/abstrakcji
**Problem:** Klasy są ściśle powiązane
**Rozwiązanie:**
```php
interface PlaylistRepositoryInterface {
    public function getById(int $id): ?array;
    public function create(array $data): array;
    // ...
}
```

### Q3. Powtórzony kod w kontrolerach
**Problem:** Podobna logika w UserController, DeviceController, PlaylistController
**Lokalizacje:**
- Walidacja CSRF
- Sprawdzanie uprawnień
- Obsługa błędów
**Rozwiązanie:** Trait lub middleware pattern

### Q4. Brak Dependency Injection
**Problem:** `new` wszędzie w kodzie
```php
// Obecne - źle
$this->logger = new Logger();
$userModel = new User();

// Powinno być
public function __construct(Logger $logger, User $userModel) {
    $this->logger = $logger;
    $this->userModel = $userModel;
}
```

### Q5. Magic strings/numbers
**Problem:** Hardcoded wartości
```php
// Źle
if ($role === 'reseller') { ... }
$limit = 100;

// Dobrze
if ($role === User::ROLE_RESELLER) { ... }
$limit = Config::get('default_playlist_limit');
```

### Q6. Brak typowania zwracanych wartości
**Problem:** Wiele metod nie ma return type
```php
// Obecne
public function getById($id) { ... }

// Powinno być
public function getById(int $id): ?array { ... }
```

### Q7. Niespójna obsługa błędów
**Problem:** Mieszanka return array z 'success' i exceptions
**Rozwiązanie:** Jeden spójny wzorzec (np. Result Pattern lub Exceptions)

---

## 🟡 PROBLEMY NISKIE (Improvements)

### I1. Brak cache'owania
**Problem:** Każde żądanie = query do DB
**Rozwiązanie:**
- Cache ustawień (już wczytane raz)
- Cache statystyk dashboardu (TTL 5 min)
- Cache list użytkowników/urządzeń

### I2. N+1 query problem
**Lokalizacja:** `dashboard.tpl` - statystyki resellerów
**Problem:** Wiele zapytań w pętli
**Rozwiązanie:** JOIN lub batch loading

### I3. Brak indeksów na niektórych kolumnach
**Problem:** Wolne zapytania przy dużej ilości danych
**Rozwiązanie:**
```sql
CREATE INDEX idx_playlists_type ON playlists(type);
CREATE INDEX idx_users_role ON users(role);
CREATE INDEX idx_users_parent_id ON users(parent_id);
CREATE INDEX idx_entity_notes_entity ON entity_notes(entity_type, entity_id);
```

### I4. Brak paginacji w niektórych miejscach
**Lokalizacja:** Dropdown wyboru urządzenia, listy resellerów
**Problem:** Przy 1000+ rekordów będzie wolno
**Rozwiązanie:** AJAX autocomplete lub virtual scrolling

### I5. Brak walidacji na poziomie modelu
**Problem:** Walidacja rozrzucona po kontrolerach
**Rozwiązanie:** Validator class lub walidacja w modelach

### I6. Brak transakcji DB
**Problem:** Operacje wielokrokowe mogą być częściowe
**Lokalizacja:** Klonowanie urządzenia z playlistami
**Rozwiązanie:**
```php
$db->beginTransaction();
try {
    // operacje
    $db->commit();
} catch (Exception $e) {
    $db->rollBack();
}
```

---

## 🔧 PROPOZYCJE REFAKTORYZACJI

### R1. Service Layer
Dodać warstwę serwisów między kontrolerami a modelami:
```
Controller → Service → Repository → Database
```

### R2. Event System
Dodać eventy dla ważnych akcji:
```php
$eventDispatcher->dispatch(new UserCreatedEvent($user));
$eventDispatcher->dispatch(new PlaylistUpdatedEvent($playlist));
```

### R3. Command/Query Separation (CQRS lite)
Rozdzielić operacje odczytu i zapisu:
```php
// Queries (read)
$query = new GetPlaylistsByDeviceQuery($deviceId);
$playlists = $queryBus->handle($query);

// Commands (write)
$command = new CreatePlaylistCommand($data);
$commandBus->handle($command);
```

### R4. Form Request Validation
Dedykowane klasy walidacji:
```php
class CreateUserRequest extends FormRequest {
    public function rules(): array {
        return [
            'username' => 'required|min:3|max:50|regex:/^[a-zA-Z0-9_-]+$/',
            'password' => 'required|min:6',
            'role' => 'in:user,reseller,admin',
        ];
    }
}
```

---

## 📋 BRAKUJĄCE FUNKCJONALNOŚCI

### F1. System wygasania
- [ ] Data wygaśnięcia urządzenia
- [ ] Data wygaśnięcia playlisty
- [ ] Data wygaśnięcia konta użytkownika
- [ ] Automatyczna dezaktywacja
- [ ] Powiadomienia przed wygaśnięciem
- [ ] Grace period

### F2. Powiadomienia
- [ ] Email przy logowaniu z nowego IP
- [ ] Email przy zmianie hasła
- [ ] Email przy wygasaniu
- [ ] Push notifications (browser)
- [ ] Telegram/Discord webhook

### F3. Import/Export
- [ ] Import playlist z CSV
- [ ] Import urządzeń z CSV
- [ ] Import użytkowników z CSV
- [ ] Export do M3U
- [ ] Export konfiguracji

### F4. API rozszerzone
- [ ] `/api/device/register` - rejestracja
- [ ] `/api/device/heartbeat` - ping
- [ ] `/api/epg` - program TV
- [ ] `/api/categories` - kategorie
- [ ] API documentation (Swagger)

### F5. Dashboard rozszerzony
- [ ] Wykresy (Chart.js)
- [ ] Real-time updates (WebSocket)
- [ ] Customizable widgets
- [ ] Mapa geograficzna (GeoIP)

### F6. Zarządzanie EPG
- [ ] Źródła EPG
- [ ] Mapowanie kanałów
- [ ] Cache EPG
- [ ] Preview EPG

### F7. Health Check playlist
- [ ] Testowanie URL
- [ ] Sprawdzanie dostępności
- [ ] Alerty o awariach
- [ ] Scheduled checks

### F8. System ticketów
- [ ] Tickety user → reseller
- [ ] Tickety reseller → admin
- [ ] Statusy, priorytety
- [ ] Historia

### F9. Backup rozszerzony
- [ ] Automatyczne backupy (CRON)
- [ ] Backup do chmury (S3, GCS)
- [ ] Retencja (usuwanie starych)
- [ ] Restore z GUI

### F10. Logowanie rozszerzone
- [ ] Log levels (debug, info, error)
- [ ] Log rotation
- [ ] External logging (Sentry)
- [ ] Request tracing

---

## 🎨 UI/UX IMPROVEMENTS

### U1. Responsywność
- [ ] Mobile-first refactor
- [ ] Bottom navigation na mobile
- [ ] Swipe gestures
- [ ] Touch-friendly buttons

### U2. Dark/Light Mode
- [ ] Przełącznik motywu
- [ ] System preference detection
- [ ] Per-user preference

### U3. Accessibility
- [ ] ARIA labels
- [ ] Keyboard navigation
- [ ] Focus indicators
- [ ] Screen reader support

### U4. UX Improvements
- [ ] Loading indicators
- [ ] Skeleton screens
- [ ] Infinite scroll
- [ ] Drag & drop
- [ ] Undo/Redo

### U5. Search & Filter
- [ ] Global search (Ctrl+K)
- [ ] Saved filters
- [ ] Recent searches
- [ ] Advanced filters

---

## 🗄️ DATABASE IMPROVEMENTS

### D1. Brakujące kolumny
```sql
-- Wygasanie
ALTER TABLE devices ADD COLUMN expires_at DATETIME NULL;
ALTER TABLE playlists ADD COLUMN expires_at DATETIME NULL;
ALTER TABLE users ADD COLUMN expires_at DATETIME NULL;

-- Statystyki
ALTER TABLE devices ADD COLUMN last_api_call DATETIME NULL;
ALTER TABLE devices ADD COLUMN api_calls_count INTEGER DEFAULT 0;

-- 2FA
ALTER TABLE users ADD COLUMN totp_secret VARCHAR(32) NULL;
ALTER TABLE users ADD COLUMN totp_enabled INTEGER DEFAULT 0;

-- Preferences
ALTER TABLE users ADD COLUMN preferences_json TEXT DEFAULT '{}';
```

### D2. Nowe tabele
```sql
-- Grupy/Pakiety playlist
CREATE TABLE playlist_groups (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100),
    description TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Szablony playlist
CREATE TABLE playlist_templates (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100),
    type VARCHAR(20),
    config_json TEXT,
    created_by INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Historia zmian cen/płatności
CREATE TABLE billing_history (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    amount DECIMAL(10,2),
    currency VARCHAR(3),
    description TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Tickety support
CREATE TABLE tickets (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    assigned_to INTEGER,
    subject VARCHAR(200),
    status VARCHAR(20) DEFAULT 'open',
    priority VARCHAR(20) DEFAULT 'normal',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE ticket_messages (
    id INTEGER PRIMARY KEY,
    ticket_id INTEGER,
    user_id INTEGER,
    message TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
```

### D3. Indeksy do dodania
```sql
CREATE INDEX idx_devices_expires ON devices(expires_at);
CREATE INDEX idx_playlists_expires ON playlists(expires_at);
CREATE INDEX idx_users_expires ON users(expires_at);
CREATE INDEX idx_users_role_active ON users(role, is_active);
CREATE INDEX idx_sessions_expires ON sessions(expires_at);
CREATE INDEX idx_audit_log_entity ON audit_log(entity_type, entity_id);
CREATE INDEX idx_api_logs_mac ON api_logs(mac);
```

---

## 📦 ZALEŻNOŚCI DO DODANIA

### Composer packages
```json
{
    "require": {
        "monolog/monolog": "^3.0",
        "phpmailer/phpmailer": "^6.8",
        "firebase/php-jwt": "^6.0",
        "pragmarx/google2fa": "^8.0",
        "guzzlehttp/guzzle": "^7.0",
        "intervention/image": "^2.7"
    },
    "require-dev": {
        "phpunit/phpunit": "^10.0",
        "phpstan/phpstan": "^1.0",
        "squizlabs/php_codesniffer": "^3.0"
    }
}
```

---

## 📁 STRUKTURA KATALOGÓW - PROPOZYCJA

```
playlist-panel/
├── api/
│   ├── v1/
│   │   ├── playlist.php
│   │   ├── device.php
│   │   ├── epg.php
│   │   └── status.php
│   └── v2/  (przyszłość - REST)
├── app/
│   ├── Controllers/
│   ├── Models/
│   ├── Services/
│   ├── Repositories/
│   ├── Events/
│   ├── Listeners/
│   ├── Validators/
│   └── Middleware/
├── config/
│   ├── app.php
│   ├── database.php
│   ├── mail.php
│   └── routes.php
├── database/
│   ├── migrations/
│   └── seeds/
├── public/
│   ├── index.php
│   ├── assets/
│   └── uploads/
├── resources/
│   ├── views/
│   ├── lang/
│   └── js/
├── storage/
│   ├── cache/
│   ├── logs/
│   └── backups/
├── tests/
│   ├── Unit/
│   └── Feature/
└── vendor/
```

---

## ✅ CO JEST DOBRZE ZROBIONE

1. **Prepared statements** - wszystkie zapytania używają parametrów (254 wystąpień)
2. **CSRF Protection** - poprawnie zaimplementowane
3. **Password hashing** - bcrypt z kosztem 12
4. **Session management** - tokeny w DB, expire time
5. **Audit logging** - pełne śledzenie zmian
6. **Role-based access** - 3-poziomowa hierarchia
7. **Input validation** - większość danych walidowana
8. **Error handling** - try/catch w krytycznych miejscach (36 wystąpień)
9. **Clean URLs** - routing przez front controller
10. **Template separation** - Smarty templates

---

## 🎯 PRIORYTETY WDROŻENIA

### Faza 1 - Bezpieczeństwo (1-2 tygodnie)
1. Rate limiting API
2. Security headers
3. Session regeneration
4. Szyfrowanie config playlist

### Faza 2 - Stabilność (2-3 tygodnie)
1. Transakcje DB
2. Lepsze indeksy
3. Cache podstawowy
4. Obsługa błędów

### Faza 3 - Funkcjonalności (3-4 tygodnie)
1. System wygasania
2. Powiadomienia email
3. Import/Export
4. Health check playlist

### Faza 4 - UI/UX (2-3 tygodnie)
1. Dark/Light mode
2. Mobile improvements
3. Dashboard wykresy
4. Global search

### Faza 5 - Rozszerzenia (ongoing)
1. 2FA
2. API v2 REST
3. Tickety support
4. Integracje zewnętrzne

---

## 📈 METRYKI JAKOŚCI

| Metryka | Obecna | Cel |
|---------|--------|-----|
| Pokrycie testami | 0% | 60%+ |
| PHPStan level | N/A | 6+ |
| Cyclomatic complexity | Wysoka | <10 per method |
| Code duplication | ~15% | <5% |
| Security headers | 1/7 | 7/7 |
| OWASP compliance | 60% | 90%+ |

---

*Raport wygenerowany na podstawie analizy kodu źródłowego*
