Files
pgz-sport/data_quality_report.md
T
Damir Radulić f9ebcddf28 CC2 R6: middleware-wide JWT, avatar demo mode, mock mailer, login rate limit
#1 JWT middleware extended:
- Was: /api/admin/* only
- Now: any POST/PUT/PATCH/DELETE under /api/* requires Bearer JWT
- Whitelist (still anonymous): /api/auth/login, /refresh, /forgot-password,
  /password/reset, /reset-password, /setup-password, /google;
  /api/gdpr/consent; any path ending /avatar
- 14 mutating endpoints verified to return 401 without token

#2 Avatar upload demo mode (routers/clan_panel_router.py):
- Anonymous → returns {demo_mode:true, slika_url:null,
  message:'Demo mode — slika nije spremljena. Prijavite se za pravu pohranu.'},
  no FS write, no DB write
- Authenticated (valid JWT, allowed role) → real save as before
- Auth check now uses auth.auth_v2.decode_token (proper secret + revocation)
  instead of the broken local _resolve_role

#3 Mock mailer (auth/mailer.py):
- send_email writes RFC 822 .eml to /tmp/pgz_mailbox + appends to INDEX.jsonl
- send_password_reset, send_invite helpers with HR text + HTML alt
- Real SMTP active when PGZ_SMTP_HOST is set (env-driven, off by default)
- forgot-password and admin invite both call mailer; audit logs mail status

#5 Rate limiting on /api/auth/login:
- Per-user: 5 wrong attempts → 5-minute DB-backed lockout
  (was 5 → 15 min). Configurable via PGZ_LOGIN_LOCK_THRESHOLD/MINUTES.
- Per-IP: 10 fails / 5-min sliding window in-memory → HTTP 429
  Configurable via PGZ_LOGIN_IP_THRESHOLD/WINDOW_SEC. Successful
  login clears the IP counter.
- Failed attempts respond '(N/5) — račun je zaključan na 5 minuta'
- New audit actions: login.ratelimit.ip; login.fail meta now
  includes fails count, locked, lock_minutes

#4 Live test report: 46/46 across 6 demo users — login, JWT gate on 14
   mutating endpoints, public path whitelist, demo-mode avatar +
   real save, forgot-password e-mail to mailbox, no-leak unknown email,
   5-fail lockout, 423 during lockout, audit coverage.
2026-05-05 01:42:53 +02:00

101 lines
8.9 KiB
Markdown

# Data Quality Report — pgz_sport schema
**Generirano:** 2026-05-04T23:40:32.512034+00:00
**Skripta:** `/opt/pgz-sport/scripts/coverage_report.py`
**Ukupno entiteta:** 5952
## Sažetak po tipu
| Tip | n | Polja po entitetu | Srednje (%) | Median (%) | Praznih | Potpunih (≥99%) |
|---|---:|---:|---:|---:|---:|---:|
| savez | 246 | 10 | 59.8% | 60.0% | 0 | 24 |
| klub | 2244 | 12 | 57.1% | 66.7% | 0 | 8 |
| sportas | 3243 | 10 | 46.2% | 40.0% | 0 | 0 |
| objekt | 106 | 10 | 79.7% | 80.0% | 0 | 14 |
| manifestacija | 113 | 7 | 81.9% | 85.7% | 0 | 0 |
**Ponderirana srednja popunjenost svih 5952 zapisa:** **52.1%**
## Distribucija po tipu (postotak entiteta u svakom rasponu)
| Tip | 0-9% | 10-19% | 20-29% | 30-39% | 40-49% | 50-59% | 60-69% | 70-79% | 80-89% | 90-100% |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| savez | 0 (0.0%) | 0 (0.0%) | 21 (8.5%) | 9 (3.7%) | 19 (7.7%) | 55 (22.4%) | 42 (17.1%) | 55 (22.4%) | 16 (6.5%) | 29 (11.8%) |
| klub | 2 (0.1%) | 115 (5.1%) | 412 (18.4%) | 91 (4.1%) | 45 (2.0%) | 294 (13.1%) | 528 (23.5%) | 560 (25.0%) | 169 (7.5%) | 28 (1.2%) |
| sportas | 0 (0.0%) | 0 (0.0%) | 4 (0.1%) | 323 (10.0%) | 1462 (45.1%) | 951 (29.3%) | 297 (9.2%) | 50 (1.5%) | 144 (4.4%) | 12 (0.4%) |
| objekt | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 28 (26.4%) | 12 (11.3%) | 15 (14.2%) | 51 (48.1%) |
| manifestacija | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 0 (0.0%) | 4 (3.5%) | 0 (0.0%) | 22 (19.5%) | 87 (77.0%) | 0 (0.0%) |
## Definicija "popunjenog polja"
| Tip | Polja koja čine coverage |
|---|---|
| **savez** (10) | naziv, sport, predsjednik, tajnik, email, telefon, web, oib, adresa, godina_osnutka |
| **klub** (12) | naziv, sport, grad, oib, predsjednik, tajnik, email, telefon, web/web_stranica, sjediste/adresa, ciljevi, opis_djelatnosti |
| **sportas** (10) | ime, prezime, sport, klub_id, datum_rodenja, slika_url, oib, profile_url, biografija, hns_igrac_id |
| **objekt** (10) | naziv, tip, grad, adresa, lat, lng, upravitelj, kapacitet, sportovi, izgradeno |
| **manifestacija** (7) | naziv, mjesto, organizator, razina, broj_ucesnika, godina_od, source_url |
## TOP 50 entiteta za manualnu reviziju
Sortirano po najniže popunjenosti, zatim po veličini definicije (najviše-polja-prazno prvo).
Klikni link da otvori detaljni panel u portalu.
| # | Tip | ID | Naziv | Popunjeno | Postotak | Otvori |
|---:|---|---:|---|---:|---:|---|
| 1 | klub | 4250 | Streljački klub DVD Opatija | 1/12 | 8% | [](https://sport.rinet.one/static/sport2.html#klubovi/4250) |
| 2 | klub | 4249 | Streljački klub DVD svojevrstan vodič za roditelje | 1/12 | 8% | [](https://sport.rinet.one/static/sport2.html#klubovi/4249) |
| 3 | klub | 4530 | MOK RIJEKA II | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/4530) |
| 4 | klub | 4532 | MOK RIJEKA III | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/4532) |
| 5 | klub | 4531 | OK KASTAV 1998 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/4531) |
| 6 | klub | 3758 | BK Podhum | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3758) |
| 7 | klub | 2290 | KK Metal - Jurdani | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2290) |
| 8 | klub | 2315 | RK PŠR SELCE 5. u III HRL Zapad od 8 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2315) |
| 9 | klub | 2356 | ŽRK MURVICA 6. u II HRL Zapad od 9 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2356) |
| 10 | klub | 2360 | ŽRK ZAMET II 3. u III HRL Zapad od 8 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2360) |
| 11 | klub | 3898 | VK Primorjem [MERGED→3896] | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3898) |
| 12 | klub | 2311 | RK LIBURNIJA 8. u II HRL Zapad od 12 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2311) |
| 13 | klub | 2312 | RK MORNAR 3. u II HRL Zapad od 10 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2312) |
| 14 | klub | 2324 | RK ČAVLE 2. u II HRL Zapad od 10 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2324) |
| 15 | klub | 2325 | RK ČAVLE 7. u III HRL Zapad od 8 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2325) |
| 16 | klub | 2331 | SK IJANJE | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2331) |
| 17 | klub | 2332 | SK IJAŠKO ROLKANJE | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2332) |
| 18 | klub | 2333 | SK RAD | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2333) |
| 19 | klub | 2355 | ŽRK MURVICA 6. u II HRL Zapad od 12 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2355) |
| 20 | klub | 3749 | AK Velenje | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3749) |
| 21 | klub | 2291 | KK OI KOSTRENA | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2291) |
| 22 | klub | 3797 | JK Špinut | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3797) |
| 23 | klub | 3890 | VK Lošinj | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3890) |
| 24 | klub | 4533 | HNK Goranin | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/4533) |
| 25 | klub | 3899 | VK Šilo | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3899) |
| 26 | klub | 3741 | AK Elena Ban | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3741) |
| 27 | klub | 2321 | RK ZAMET 10. u Premijer ligi od 16 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2321) |
| 28 | klub | 2322 | RK ZAMET II 6. u II HRL Zapad od 10 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2322) |
| 29 | klub | 3744 | AK Koper | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3744) |
| 30 | klub | 3748 | AK Rijeka | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3748) |
| 31 | klub | 3761 | BK SVETA JELENA | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3761) |
| 32 | klub | 3753 | BK Vjekoslav Mance | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3753) |
| 33 | klub | 3754 | BK BROD MORAVICE | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3754) |
| 34 | klub | 2352 | ŠK Volosko - Volosko | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/2352) |
| 35 | klub | 3763 | BK Sivke Postojna | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3763) |
| 36 | klub | 3764 | BK Zameta | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3764) |
| 37 | klub | 3750 | AK Viškovo | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3750) |
| 38 | klub | 3747 | AK Kvarnera | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3747) |
| 39 | klub | 3765 | BK Čavle | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3765) |
| 40 | klub | 3917 | BK Boćari | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3917) |
| 41 | klub | 3918 | BK Sivke | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3918) |
| 42 | klub | 3759 | BK Predator | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3759) |
| 43 | klub | 3795 | JK Vega | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3795) |
| 44 | klub | 3780 | JK Neverin | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3780) |
| 45 | klub | 3792 | JK Trogir | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3792) |
| 46 | klub | 3919 | JK Labud | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3919) |
| 47 | klub | 3794 | JK Val | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3794) |
| 48 | klub | 3790 | JK Split | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3790) |
| 49 | klub | 3784 | JK Optimist | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/3784) |
| 50 | klub | 4426 | [UNRESOLVED] empty naziv & grad — id 4426 | 2/12 | 17% | [](https://sport.rinet.one/static/sport2.html#klubovi/4426) |
## Akcije za poboljšanje coverage-a
1. **Pokreni "Obogati podatke" na top 50 zapisa**`POST /sport/api/v2/enrich/{kind}/{id}/apply` već puni nedostajuće web/email/telefon/opis polja iz CSE+Wikipedia+sport-pgz.hr.
2. **CC6 enrichment loop** trenutno targetira coverage<70 i confidence>=0.7 — proširiti na coverage<80 nakon QA prolaza.
3. **HNS/HOS scraper** za sportaše: hns_igrac_id i slika_url stvaraju 70% coverage skoka za nogometaše. CC2-tip rader na ovome.
4. **OIB validacija** preko sudreg API-ja — popraviti `naziv`/`adresa` paralelno (vidi `data_cleanup_report.md`).