237 lines
12 KiB
Markdown
237 lines
12 KiB
Markdown
# Test odbiorczy po wdrozeniu
|
|
|
|
Lista do wykonania **w podanej kolejnosci** po uruchomieniu instancji u klienta.
|
|
Kazdy punkt ma oczekiwany wynik: jesli sie nie zgadza, nie przechodz dalej, bo
|
|
kolejne punkty na nim polegaja.
|
|
|
|
Czas wykonania calosci: okolo 90 minut, plus czekanie na przypomnienia i na
|
|
podsumowanie (do dwoch godzin, mozna w tle).
|
|
|
|
**Wszystkie punkty wykonuje sie przy WLACZONYM trybie bezpiecznym wysylki**, poza
|
|
sekcja I, ktora ten tryb celowo wylacza na koniec. Dzieki temu zadna wiadomosc
|
|
z testow nie trafi do prawdziwych ludzi.
|
|
|
|
---
|
|
|
|
## A. Przed uruchomieniem
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| A1 | `cp .env.production.example .env.production` i uzupelnic | plik istnieje, `chmod 600` |
|
|
| A2 | `./scripts/check-config.sh --skip-db` | `Konfiguracja w porzadku`, kod wyjscia 0 |
|
|
| A3 | Sprawdzic DNS domeny: `dig +short webinary.klient.pl` | adres IP serwera |
|
|
| A4 | Sprawdzic certyfikat SSL na reverse proxy klienta | waznosc powyzej 14 dni |
|
|
| A5 | Porty otwarte na firewallu: 80, 443 | dostepne z internetu |
|
|
| A6 | Przy `VIDEO_PROVIDER=LIVEKIT`: dodatkowo 7880, 7881 TCP oraz **zakres UDP** (domyslnie 50000-50100) | dostepne z internetu |
|
|
|
|
**A6 jest najczestszym przeoczeniem.** Bez otwartego zakresu UDP uczestnicy wchodza
|
|
do pokoju i widza liste obecnych, ale **sie nie slysza**. Objaw wyglada jak awaria
|
|
aplikacji, a jest regula firewalla.
|
|
|
|
---
|
|
|
|
## B. Uruchomienie
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| B1 | `docker compose -f docker-compose.prod.yml --env-file .env.production up -d` | wszystkie kontenery `Started` |
|
|
| B2 | `docker compose -f docker-compose.prod.yml ps` | postgres i minio `healthy`, backend `healthy` (do 90 s) |
|
|
| B3 | `docker compose logs backend \| grep "KONFIGURACJA INSTANCJI" -A 20` | wypis stanu, `Brak ostrzezen konfiguracyjnych` |
|
|
| B4 | `curl -s https://webinary.klient.pl/api/health` | `{"status":"UP",...}` |
|
|
| B5 | `./scripts/check-config.sh` (juz bez `--skip-db`) | kod wyjscia 0 |
|
|
|
|
Jesli B3 pokazuje ostrzezenia, przeczytaj je: kazde nazywa skutek, nie ustawienie.
|
|
Ostrzezenie o wylaczonym trybie bezpiecznym na tym etapie oznacza, ze **testy
|
|
ponizej wysla prawdziwe wiadomosci**.
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| B6 | `docker compose logs backend \| grep -i "haslo administratora"` | jednorazowe haslo (gdy `ADMIN_PASSWORD` bylo puste) |
|
|
| B7 | Zalogowac sie na `/logowanie` i **od razu zmienic haslo** | wejscie do `/panel`, haslo zmienione |
|
|
|
|
---
|
|
|
|
## C. Konfiguracja przez panel
|
|
|
|
Poczta i bramka SMS **nie sa** w `.env`: ustawia sie je w panelu, bo zmiana nie
|
|
moze wymagac dostepu do serwera.
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| C1 | Ustawienia -> E-mail: host, port, login, haslo, nazwa nadawcy | zapisane |
|
|
| C2 | **Sprawdzic, ze `MAIL_SAFE_MODE` jest wlaczony i ma adres zastepczy** | wlaczony, adres wlasny |
|
|
| C3 | Ustawienia -> E-mail -> Test wysylki | wiadomosc dociera na adres zastepczy |
|
|
| C4 | Ustawienia -> Aplikacja: nazwa marki, adres publiczny, strefa czasowa | zapisane |
|
|
| C5 | Ustawienia -> Grafika: logo i ikona | widoczne w panelu i na stronie glownej |
|
|
| C6 | Ustawienia -> Zgody: tresc regulaminu i zgod marketingowych | zapisane, `CONSENT_VERSION` ustawiona |
|
|
| C7 | Przy uzyciu SMS: Ustawienia -> SMS, klucz bramki, tryb bezpieczny **wlaczony** | test SMS dociera na numer zastepczy |
|
|
|
|
---
|
|
|
|
## D. Sciezka webinarowa
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| D1 | Panel -> Webinary -> nowy: tytul, termin **w przyszlosci**, limit miejsc | zapisany jako DRAFT |
|
|
| D2 | Dodac tresc strony w edytorze, wgrac obrazek | obrazek widoczny w podgladzie |
|
|
| D3 | Opublikowac webinar | status PUBLISHED |
|
|
| D4 | Otworzyc `/w/{slug}` w oknie prywatnym | strona z trescia i formularzem zapisu |
|
|
| D5 | Zapisac sie z wlasnego adresu, zaznaczyc zgody | ekran potwierdzenia |
|
|
| D6 | Sprawdzic skrzynke | mail potwierdzajacy z **dzialajacym** linkiem i zalacznikiem `invite.ics` |
|
|
| D7 | Otworzyc `invite.ics` w kalendarzu | wydarzenie z poprawna data i strefa |
|
|
| D8 | Kliknac link z maila | strona wlasnego zapisu, widoczny przycisk rezygnacji |
|
|
| D9 | Panel -> lista zapisanych | wpis widoczny, zgody z wersja i data |
|
|
| D10 | Eksport CSV listy zapisanych | plik otwiera sie w Excelu, polskie znaki poprawne |
|
|
| D11 | Dodac regule przypomnienia na **za 5 minut** i odczekac | przypomnienie dociera (na adres zastepczy) |
|
|
| D12 | Wejsc na `/spotkanie/{token}` z linku | przedpokoj z tytulem i imieniem do potwierdzenia |
|
|
| D13 | Wejsc na sale, wyslac wiadomosc na czacie | wiadomosc widoczna, autor jako imie i inicjal |
|
|
| D14 | Zadac pytanie i zaglosowac na nie z drugiej przegladarki | licznik glosow rosnie o 1, drugi glos tej samej osoby odrzucony |
|
|
| D15 | Panel prowadzenia: zatwierdzic pytanie | pytanie pojawia sie u uczestnika |
|
|
| D16 | Zglosic sie do zabrania glosu, przyznac glos z panelu | mikrofon uczestnika dziala |
|
|
| D17 | Zakonczyc webinar, zmienic termin na przeszly, odczekac `SUMMARY_DELAY_MINUTES` | podsumowanie dociera raz, nie dwa razy |
|
|
| D18 | Wystawic certyfikat uczestnikowi z odnotowana obecnoscia | PDF z **polskimi znakami** w nazwisku |
|
|
| D19 | Otworzyc `/certyfikat/{numer}` w oknie prywatnym | weryfikacja pokazuje numer, tytul, imie z inicjalem, **bez adresu e-mail** |
|
|
|
|
**D18 jest krytyczny.** Certyfikat z polamanym nazwiskiem jest bezuzyteczny, a blad
|
|
osadzania czcionki widac wylacznie na gotowym pliku.
|
|
|
|
---
|
|
|
|
## E. Sciezka Akademii
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| E1 | Otworzyc `/` w oknie prywatnym | strona glowna Akademii, przycisk `Zaloguj sie` |
|
|
| E2 | Panel -> Kursy -> nowy kurs z modulem i lekcja wideo | zapisany jako DRAFT |
|
|
| E3 | Wgrac nagranie lekcji, ustawic dlugosc | plik widoczny |
|
|
| E4 | Opublikowac kurs, ustawic cene | widoczny na `/kursy` |
|
|
| E5 | Zarejestrowac konto kursanta na `/rejestracja` | mail z linkiem potwierdzajacym |
|
|
| E6 | Potwierdzic adres z linku | konto aktywne, wejscie na `/moje-konto` |
|
|
| E7 | Zapisac sie na kurs **darmowy** | dostep od reki, kurs na pulpicie |
|
|
| E8 | Otworzyc odtwarzacz, obejrzec lekcje do konca | lekcja oznaczona jako ukonczona, postep rosnie |
|
|
| E9 | Przewinac nagranie w polowie | przewijanie dziala (naglowek Range) |
|
|
| E10 | Dodac quiz do lekcji, rozwiazac go jako kursant | wynik policzony, **poprawne odpowiedzi nie sa widoczne w zrodle strony przed koncem** |
|
|
| E11 | Ukonczyc wszystkie lekcje wymagane | kurs COMPLETED, certyfikat wystawiony automatycznie |
|
|
| E12 | Sprawdzic mail o ukonczeniu | zalacznik PDF, dzialajacy link do pulpitu |
|
|
| E13 | Panel -> Kursanci -> szczegoly | postep, zgody z historia, ostatnia aktywnosc |
|
|
| E14 | Zalogowac sie adresem majacym konto w obu swiatach | ekran wyboru: `Moje konto` i `Panel` |
|
|
|
|
---
|
|
|
|
## F. Czego NIE DA SIE sprawdzic lokalnie
|
|
|
|
Te punkty **musza** zostac wykonane po wdrozeniu, bo lokalnie nie ma jak ich
|
|
przejsc. Kazdy z nich to droga, ktora dotad nie zostala przebyta end-to-end.
|
|
|
|
### F1. Notyfikacja ITN Autopay
|
|
|
|
Operator laczy sie **z naszym serwerem**, wiec wymaga publicznej domeny z waznym
|
|
certyfikatem. Na localhost nie da sie tego wywolac.
|
|
|
|
| Krok | Oczekiwany wynik |
|
|
| --- | --- |
|
|
| Ustawic `AUTOPAY_MODE=TEST`, ServiceID i klucz ze srodowiska testowego operatora | Autopay: konfiguracja kompletna w wypisie startowym |
|
|
| Zamowic kurs platny jako kursant | przekierowanie na bramke testowa |
|
|
| Zaplacic karta testowa operatora | powrot na `/kurs/{slug}/platnosc` |
|
|
| Odczekac na ITN (do kilkudziesieciu sekund) | strona sama pokazuje nadany dostep |
|
|
| Panel -> Zamowienia | status PAID, w dzienniku wpis notyfikacji |
|
|
| Powtorzyc notyfikacje z panelu operatora | **dostep nadany raz**, drugi komunikat potwierdzony bez zmiany |
|
|
| Sprobowac zaplacic kwota inna niz w zamowieniu | notyfikacja odrzucona, wpis w dzienniku |
|
|
|
|
**Dopiero po przejsciu wszystkich krokow** przelaczyc `AUTOPAY_MODE=PRODUCTION`.
|
|
Wypis startowy pokaze wtedy ostrzezenie o prawdziwych pieniadzach: to jest
|
|
oczekiwane i ma zostac zauwazone.
|
|
|
|
### F2. Nagrywanie przez Egress
|
|
|
|
Lokalnie proces zatrzymywal sie na tym, ze szablon nie subskrybowal zadnej sciezki:
|
|
do domkniecia potrzebny jest publikujacy uczestnik w tej samej sieci co Egress,
|
|
czego nie da sie zestawic na Docker Desktop przy jednym `NODE_IP`.
|
|
|
|
| Krok | Oczekiwany wynik |
|
|
| --- | --- |
|
|
| `docker compose ... --profile livekit up -d` | cztery kontenery wideo dzialaja |
|
|
| `docker compose logs livekit-egress \| head -30` | polaczenie z Redisem, brak bledow ICE |
|
|
| Zestawic spotkanie z **dwoma** uczestnikami, jeden publikuje obraz | obraz i dzwiek plyna w obie strony |
|
|
| Uruchomic nagrywanie z panelu prowadzenia | wpis w `recordings` ze statusem DOWNLOADING |
|
|
| Zakonczyc nagrywanie, odczekac | status READY, plik w MinIO |
|
|
| Odtworzyc nagranie z panelu, przewinac | odtwarza sie i przewija |
|
|
|
|
Gdy nagrywanie nie ruszy: **reczne wgranie pliku dziala i jest droga awaryjna**.
|
|
Nie blokuje to wdrozenia.
|
|
|
|
### F3. Webhook dostawcy wideo
|
|
|
|
| Krok | Oczekiwany wynik |
|
|
| --- | --- |
|
|
| Ustawic `VIDEO_WEBHOOK_SECRET` w panelu i ten sam sekret u dostawcy | zapisane |
|
|
| Wywolac zdarzenie u dostawcy (zakonczenie nagrania) | wpis w logu backendu, odpowiedz 200 |
|
|
| Wyslac zadanie z **blednym** sekretem: `curl -X POST .../api/webhooks/video/livekit -d '{}'` | **404**, nie 403 |
|
|
|
|
Odpowiedz 404 jest celowa: 403 pozwalalaby sprawdzic, ktore webinary istnieja.
|
|
|
|
### F4. Zajawki w komunikatorach
|
|
|
|
Wymagaja publicznego adresu: robot musi pobrac strone z internetu.
|
|
|
|
| Krok | Oczekiwany wynik |
|
|
| --- | --- |
|
|
| Wkleic `https://webinary.klient.pl/w/{slug}` na Slacku albo Facebooku | zajawka z tytulem webinaru i opisem |
|
|
| `curl -A "facebookexternalhit/1.1" https://webinary.klient.pl/w/{slug}` | HTML z `og:title` zawierajacym tytul |
|
|
| To samo dla webinaru w stanie DRAFT | **404**, wersje robocze nie moga wyciekac |
|
|
|
|
### F5. Poczta wychodzaca do prawdziwych odbiorcow
|
|
|
|
| Krok | Oczekiwany wynik |
|
|
| --- | --- |
|
|
| Sprawdzic rekordy SPF i DKIM domeny nadawcy | skonfigurowane |
|
|
| Wyslac test na adres w Gmailu i w Outlooku | wiadomosc **nie trafia do spamu** |
|
|
| Sprawdzic naglowki dostarczonej wiadomosci | SPF `pass`, DKIM `pass` |
|
|
|
|
---
|
|
|
|
## G. Kopia zapasowa
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| G1 | `./scripts/backup.sh` | katalog w `./backups`, pliki `baza.dump` i `minio.tar.gz` niepuste |
|
|
| G2 | Sprawdzic `INFO.txt` w kopii | data, nazwa bazy, wersja obrazu |
|
|
| G3 | Dodac wpis do `crontab` (patrz README) | `crontab -l` pokazuje wpis |
|
|
| G4 | **Odtworzyc kopie na maszynie testowej**, nie na produkcji | dane zgodne ze stanem z chwili kopii |
|
|
|
|
**G4 jest obowiazkowy.** Kopia, ktorej nigdy nie odtworzono, nie jest kopia
|
|
zapasowa, tylko plikiem o nieznanej zawartosci.
|
|
|
|
---
|
|
|
|
## H. Bezpieczenstwo
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| H1 | `curl -s https://webinary.klient.pl/api/admin/webinars` | 401, nie lista |
|
|
| H2 | `nmap -p 5432,9000,9001 webinary.klient.pl` | porty **zamkniete** z internetu |
|
|
| H3 | Otworzyc `/swagger-ui.html` | 404 albo 403 (`SWAGGER_ENABLED=false`) |
|
|
| H4 | Zalogowac sie 6 razy blednym haslem | blokada po 5 probie, komunikat **taki sam** jak przy zlym hasle |
|
|
| H5 | Sprobowac pobrac certyfikat cudzym tokenem zapisu | 404 |
|
|
| H6 | Sprawdzic `/api/public/config` | wylacznie nazwa marki, adres i strefa, **zadnych sekretow** |
|
|
|
|
---
|
|
|
|
## I. Przelaczenie na ruch produkcyjny
|
|
|
|
**Dopiero po przejsciu wszystkich punktow powyzej.**
|
|
|
|
| # | Czynnosc | Oczekiwany wynik |
|
|
| --- | --- | --- |
|
|
| I1 | Skasowac dane testowe: webinary, kursy, zamowienia, kontakty testowe | listy puste albo z prawdziwymi danymi |
|
|
| I2 | **Nie kasowac** `app_settings` ani konta administratora | konfiguracja zachowana |
|
|
| I3 | Ustawienia -> E-mail: **wylaczyc** `MAIL_SAFE_MODE` | zapisane |
|
|
| I4 | Przy uzyciu SMS: wylaczyc `SMS_SAFE_MODE` | zapisane |
|
|
| I5 | Zrestartowac backend i przeczytac wypis startowy | ostrzezenie o wylaczonym trybie bezpiecznym: **oczekiwane** |
|
|
| I6 | Wyslac jedna prawdziwa wiadomosc testowa do siebie | dociera na wlasciwy adres |
|
|
| I7 | `./scripts/backup.sh` na czysto | kopia stanu wyjsciowego |
|
|
|
|
Po I3 kazda wysylka idzie do **prawdziwych odbiorcow**. Od tego momentu dane
|
|
testowe z terminem w przeszlosci moga uruchomic scheduler i wyslac wiadomosci
|
|
do osob z bazy: dlatego I1 jest **przed** I3, a nie po.
|