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

8.9 KiB

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%
2 klub 4249 Streljački klub DVD svojevrstan vodič za roditelje 1/12 8%
3 klub 4530 MOK RIJEKA II 2/12 17%
4 klub 4532 MOK RIJEKA III 2/12 17%
5 klub 4531 OK KASTAV 1998 2/12 17%
6 klub 3758 BK Podhum 2/12 17%
7 klub 2290 KK Metal - Jurdani 2/12 17%
8 klub 2315 RK PŠR SELCE 5. u III HRL Zapad od 8 2/12 17%
9 klub 2356 ŽRK MURVICA 6. u II HRL Zapad od 9 2/12 17%
10 klub 2360 ŽRK ZAMET II 3. u III HRL Zapad od 8 2/12 17%
11 klub 3898 VK Primorjem [MERGED→3896] 2/12 17%
12 klub 2311 RK LIBURNIJA 8. u II HRL Zapad od 12 2/12 17%
13 klub 2312 RK MORNAR 3. u II HRL Zapad od 10 2/12 17%
14 klub 2324 RK ČAVLE 2. u II HRL Zapad od 10 2/12 17%
15 klub 2325 RK ČAVLE 7. u III HRL Zapad od 8 2/12 17%
16 klub 2331 SK IJANJE 2/12 17%
17 klub 2332 SK IJAŠKO ROLKANJE 2/12 17%
18 klub 2333 SK RAD 2/12 17%
19 klub 2355 ŽRK MURVICA 6. u II HRL Zapad od 12 2/12 17%
20 klub 3749 AK Velenje 2/12 17%
21 klub 2291 KK OI KOSTRENA 2/12 17%
22 klub 3797 JK Špinut 2/12 17%
23 klub 3890 VK Lošinj 2/12 17%
24 klub 4533 HNK Goranin 2/12 17%
25 klub 3899 VK Šilo 2/12 17%
26 klub 3741 AK Elena Ban 2/12 17%
27 klub 2321 RK ZAMET 10. u Premijer ligi od 16 2/12 17%
28 klub 2322 RK ZAMET II 6. u II HRL Zapad od 10 2/12 17%
29 klub 3744 AK Koper 2/12 17%
30 klub 3748 AK Rijeka 2/12 17%
31 klub 3761 BK SVETA JELENA 2/12 17%
32 klub 3753 BK Vjekoslav Mance 2/12 17%
33 klub 3754 BK BROD MORAVICE 2/12 17%
34 klub 2352 ŠK Volosko - Volosko 2/12 17%
35 klub 3763 BK Sivke Postojna 2/12 17%
36 klub 3764 BK Zameta 2/12 17%
37 klub 3750 AK Viškovo 2/12 17%
38 klub 3747 AK Kvarnera 2/12 17%
39 klub 3765 BK Čavle 2/12 17%
40 klub 3917 BK Boćari 2/12 17%
41 klub 3918 BK Sivke 2/12 17%
42 klub 3759 BK Predator 2/12 17%
43 klub 3795 JK Vega 2/12 17%
44 klub 3780 JK Neverin 2/12 17%
45 klub 3792 JK Trogir 2/12 17%
46 klub 3919 JK Labud 2/12 17%
47 klub 3794 JK Val 2/12 17%
48 klub 3790 JK Split 2/12 17%
49 klub 3784 JK Optimist 2/12 17%
50 klub 4426 [UNRESOLVED] empty naziv & grad — id 4426 2/12 17%

Akcije za poboljšanje coverage-a

  1. Pokreni "Obogati podatke" na top 50 zapisaPOST /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).