# Strategia Bezpiecznego Wdrożenia Fazy 2 > **Data:** 2026-01-31 > **Status:** KRYTYCZNE - wymaga starannego planowania > **Ryzyko:** Wysokie - 125+ zmian musi być atomowych --- ## Problem ### Obecne nazwy endpointów (bez prefiksu) ```python # app.py @app.route('/') def index(): ... # url_for('index') @app.route('/login') def login(): ... # url_for('login') @app.route('/dashboard') def dashboard(): ... # url_for('dashboard') ``` ### Docelowe nazwy endpointów (z prefiksem blueprintu) ```python # blueprints/public/routes.py @bp.route('/') def index(): ... # url_for('public.index') # blueprints/auth/routes.py @bp.route('/login') def login(): ... # url_for('auth.login') ``` ### Skala zmian | Lokalizacja | url_for('index') | url_for('login') | url_for('dashboard') | url_for('register') | |-------------|------------------|------------------|----------------------|---------------------| | app.py | 18 | 10 | 43 | 0 | | szablony | 27 | 11 | 6 | 10 | | **RAZEM** | **45** | **21** | **49** | **10** | **Łącznie: ~125 miejsc do zmiany ATOMICZNIE** --- ## Strategie wdrożenia ### ❌ Opcja A: Stopniowe wdrażanie (NIEMOŻLIWE) Nie można wdrożyć blueprintu bez zmiany wszystkich url_for. Każda częściowa zmiana = awaria. ### ⚠️ Opcja B: Aliasy / Redirecty (RYZYKOWNE) ```python # Po rejestracji blueprintu, dodać alias w app.py: @app.route('/_redirect_index') def _old_index(): return redirect(url_for('public.index')) # Ale url_for('index') wciąż nie zadziała! ``` **Problem:** Flask nie wspiera natywnie aliasów endpointów. ### ⚠️ Opcja C: Endpoint override (CZĘŚCIOWO) ```python # W blueprincie - nadpisać nazwę endpointu @bp.route('/', endpoint='index') # Bez prefiksu! def index_view(): ... ``` **Problem:** - `url_for('index')` zadziała ✅ - `url_for('public.index')` NIE zadziała ❌ - `utils/decorators.py` wymaga `url_for('public.index')` ❌ ### ✅ Opcja D: Big Bang z testami (REKOMENDOWANA) 1. Przygotować WSZYSTKIE zmiany lokalnie 2. Uruchomić PEŁNE testy lokalne 3. Wdrożyć jednym commitem 4. Mieć gotowy rollback --- ## Plan wdrożenia Fazy 2 (bezpieczny) ### Etap 1: Przygotowanie (lokalnie) ```bash # 1. Stworzyć nowy branch git checkout -b feature/phase2-auth-public # 2. Stworzyć blueprinty mkdir -p blueprints/auth blueprints/public ``` ### Etap 2: Implementacja blueprintów #### blueprints/auth/routes.py - Przenieść: login, logout, register, verify-2fa, forgot-password, reset-password, verify-email, resend-verification - Użyć: `from utils.helpers import validate_email, validate_password, sanitize_input` #### blueprints/public/routes.py - Przenieść: index, company_detail, search, events, new_members, connections_map, release_notes - Użyć: `from utils.helpers import sanitize_input` ### Etap 3: Masowa zmiana url_for ```bash # Zmiana w szablonach find templates/ -name "*.html" -exec sed -i '' \ -e "s/url_for('index')/url_for('public.index')/g" \ -e "s/url_for('login')/url_for('auth.login')/g" \ -e "s/url_for('logout')/url_for('auth.logout')/g" \ -e "s/url_for('register')/url_for('auth.register')/g" \ -e "s/url_for('dashboard')/url_for('account.dashboard')/g" \ {} \; # Zmiana w app.py sed -i '' \ -e "s/url_for('index')/url_for('public.index')/g" \ -e "s/url_for('login')/url_for('auth.login')/g" \ ... \ app.py ``` ### Etap 4: Testy lokalne (KRYTYCZNE!) ```bash # 1. Uruchomić aplikację python3 app.py # 2. Testy manualne - WSZYSTKIE muszą przejść! □ Strona główna ładuje się □ Menu nawigacji działa □ Link "Zaloguj" działa □ Formularz logowania działa □ Logowanie przekierowuje na dashboard □ Dashboard ładuje się □ Wylogowanie działa □ Rejestracja działa □ Reset hasła działa □ Wyszukiwarka działa □ Profil firmy działa □ Wszystkie istniejące blueprinty działają (reports, contacts, etc.) ``` ### Etap 5: Wdrożenie ```bash # 1. Commit git add . git commit -m "refactor(phase2): Extract auth + public blueprints BREAKING CHANGE: All url_for() calls updated to use blueprint prefixes: - url_for('index') -> url_for('public.index') - url_for('login') -> url_for('auth.login') - url_for('register') -> url_for('auth.register') - url_for('dashboard') -> url_for('account.dashboard') ~125 files changed atomically." # 2. Push git push origin feature/phase2-auth-public git checkout master git merge feature/phase2-auth-public git push origin master && git push inpi master # 3. Deploy ssh maciejpi@57.128.200.27 "cd /var/www/nordabiznes && sudo systemctl restart nordabiznes" # 4. Weryfikacja (natychmiast!) curl -sI https://nordabiznes.pl/ | head -3 curl -sI https://nordabiznes.pl/login | head -3 curl -sI https://nordabiznes.pl/dashboard | head -3 ``` ### Etap 6: Rollback (jeśli potrzebny) ```bash # Natychmiastowy rollback git revert HEAD git push origin master && git push inpi master ssh maciejpi@57.128.200.27 "cd /var/www/nordabiznes && sudo systemctl restart nordabiznes" ``` --- ## Checklist przed wdrożeniem ### Przygotowanie - [ ] Nowy branch utworzony - [ ] Blueprinty auth i public stworzone - [ ] Wszystkie routes przeniesione - [ ] Wszystkie url_for zmienione w app.py - [ ] Wszystkie url_for zmienione w szablonach - [ ] utils/decorators.py sprawdzony ### Testy lokalne - [ ] Aplikacja uruchamia się bez błędów - [ ] Strona główna działa - [ ] Logowanie działa - [ ] Dashboard działa - [ ] Wylogowanie działa - [ ] Rejestracja działa - [ ] Menu nawigacji działa - [ ] Istniejące blueprinty działają ### Przed wdrożeniem - [ ] Backup bazy danych (opcjonalnie) - [ ] Czas wdrożenia: niska aktywność użytkowników - [ ] Osoba monitorująca: dostępna ### Po wdrożeniu - [ ] Health check OK - [ ] Strona główna OK - [ ] Logowanie OK - [ ] Brak błędów w logach --- ## Alternatywa: Endpoint override (bezpieczniejsza?) Zamiast zmieniać 125 miejsc, można użyć endpoint override: ```python # blueprints/public/__init__.py bp = Blueprint('public', __name__) # blueprints/public/routes.py @bp.route('/', endpoint='index') # Endpoint = 'index' (bez prefiksu!) def index(): ... ``` **Zalety:** - `url_for('index')` dalej działa ✅ - Nie trzeba zmieniać szablonów ✅ - Mniej ryzykowne ✅ **Wady:** - `utils/decorators.py` używa `url_for('public.index')` - trzeba zmienić ❌ - Niespójna konwencja nazewnictwa ❌ - Trudniejsze debugowanie ❌ ### Decyzja **REKOMENDACJA:** Użyć endpoint override dla pierwszego wdrożenia, potem stopniowo migrować na pełne nazwy. ```python # Faza 2a: Endpoint override (bezpieczne) @bp.route('/', endpoint='index') @bp.route('/login', endpoint='login') # Faza 2b: Stopniowa zmiana szablonów (później) # url_for('index') -> url_for('public.index') ``` --- ## ✅ REKOMENDOWANA STRATEGIA: Dual Endpoints (Alias Bridge) ### Dowód koncepcji (przetestowane!) ```python # Flask pozwala zarejestrować ten sam URL pod dwoma nazwami: app.register_blueprint(auth_bp) # Rejestruje /login -> auth.login # Dodanie aliasu dla kompatybilności wstecznej: app.add_url_rule('/login', 'login', app.view_functions['auth.login']) # Wynik: # /login -> auth.login (nowy) # /login -> login (stary alias) # Oba url_for działają: # url_for('login') = /login ✓ # url_for('auth.login') = /login ✓ ``` ### Plan wdrożenia (3 podfazy) #### Faza 2a: Blueprinty + Aliasy (BEZPIECZNE) ```python # blueprints/__init__.py def register_blueprints(app): from blueprints.auth import bp as auth_bp from blueprints.public import bp as public_bp app.register_blueprint(auth_bp) app.register_blueprint(public_bp) # ALIASY dla kompatybilności wstecznej # Szablony dalej używają url_for('login'), url_for('index'), etc. _create_endpoint_aliases(app, { # stara_nazwa: nowa_nazwa 'index': 'public.index', 'login': 'auth.login', 'logout': 'auth.logout', 'register': 'auth.register', 'dashboard': 'public.dashboard', # lub account.dashboard 'search': 'public.search', 'company_detail': 'public.company_detail', 'company_detail_by_slug': 'public.company_detail_by_slug', # ... wszystkie inne }) def _create_endpoint_aliases(app, aliases): """Tworzy aliasy dla starych nazw endpointów.""" for old_name, new_name in aliases.items(): if new_name in app.view_functions: # Znajdź URL dla nowego endpointu for rule in app.url_map.iter_rules(): if rule.endpoint == new_name: app.add_url_rule( rule.rule, old_name, app.view_functions[new_name], methods=rule.methods ) break ``` **Efekt Fazy 2a:** - ✅ Blueprinty działają - ✅ `url_for('login')` działa (alias) - ✅ `url_for('auth.login')` działa (nowy) - ✅ Szablony NIE wymagają zmian - ✅ Zero ryzyka awarii #### Faza 2b: Stopniowa migracja szablonów ```bash # Można zmieniać po jednym szablonie # Każda zmiana = osobny commit # Przykład: sed -i '' "s/url_for('login')/url_for('auth.login')/g" templates/base.html git commit -m "refactor: Migrate url_for in base.html" ``` **Efekt Fazy 2b:** - ✅ Szablony używają nowych nazw - ✅ Aliasy dalej działają (dla nieprzemigrowanych) - ✅ Można robić stopniowo #### Faza 2c: Usunięcie aliasów (cleanup) ```python # Po pełnej migracji szablonów: # Usunąć _create_endpoint_aliases() ``` **Efekt Fazy 2c:** - ✅ Czysty kod - ✅ Tylko nowe nazwy endpointów - ✅ Pełna migracja zakończona --- ## Podsumowanie strategii | Faza | Opis | Ryzyko | Szablony | |------|------|--------|----------| | **2a** | Blueprinty + aliasy | 🟢 Niskie | Bez zmian | | **2b** | Migracja szablonów | 🟢 Niskie | Stopniowo | | **2c** | Usunięcie aliasów | 🟢 Niskie | Po migracji | ### Porównanie z Big Bang | Aspekt | Big Bang | Alias Bridge | |--------|----------|--------------| | Zmiany na raz | ~125 | ~20 (tylko blueprinty) | | Ryzyko awarii | 🔴 Wysokie | 🟢 Niskie | | Rollback | Trudny | Łatwy | | Testowanie | Wszystko naraz | Etapami | | Czas wdrożenia | 1 dzień | 3-5 dni (bezpiecznie) | --- ## Checklist Fazy 2a ### Przygotowanie - [ ] Stworzyć `blueprints/auth/__init__.py` - [ ] Stworzyć `blueprints/auth/routes.py` - [ ] Stworzyć `blueprints/public/__init__.py` - [ ] Stworzyć `blueprints/public/routes.py` - [ ] Przenieść routes z app.py do blueprintów - [ ] Dodać funkcję `_create_endpoint_aliases()` - [ ] Zaktualizować `blueprints/__init__.py` ### Testy lokalne - [ ] Aplikacja uruchamia się - [ ] `url_for('index')` działa - [ ] `url_for('public.index')` działa - [ ] Logowanie działa - [ ] Strona główna działa - [ ] Istniejące blueprinty działają ### Wdrożenie - [ ] Commit + push - [ ] Deploy na produkcję - [ ] Weryfikacja health check - [ ] Weryfikacja logowania --- **Ostatnia aktualizacja:** 2026-01-31 **Status:** REKOMENDOWANA STRATEGIA - Alias Bridge