Code-review popravke: RequireDozvola middleware, validacija backupa, dedup partiala

Bezbednost / dozvole:
  - Nov RequireDozvola(proveri, akcija) middleware (po uzoru na RequireAdmin):
    na odbijanje redirekt na /dashboard sa flash porukom umesto golog 403
  - 10 "pregled" ruta (prodaja, servis, klijenti, dobavljači, nabavke) prešlo
    na deklarativnu proveru na nivou rute
  - Uklonjene inline pregled-provere iz handlera — provera je sad na jednom
    mestu po ruti, vidljiva u ruteru

  Backup podešavanja:
  - Neispravan unos (van opsega ili ne-broj) više se ne preskače tiho;
    prikazuje se jasna greška i ne prikazuje se lažno "sačuvano"
  - Hvata se greška pri čuvanju u bazu (uklonjen progutani _ =)

  Šabloni:
  - "Premesti" dropdown izvučen u jedan {{define "premestiMeni"}} partial
    (više nije dupliran u tabeli i mobilnoj kartici)
  - Dodat dict helper u FuncMap saSidebar šablona radi prosleđivanja više
    vrednosti partialu; standalone šabloni namerno ostaju bez izmene
This commit is contained in:
2026-06-09 01:26:10 +02:00
parent 53432c8c41
commit cf13d0fe15
10 changed files with 93 additions and 95 deletions
+28 -12
View File
@@ -248,22 +248,38 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
}
}
// backup podešavanja — čuvamo samo ako su validni pozitivni brojevi u razumnom opsegu
if v := r.FormValue("backup_interval_sati"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n >= 1 && n <= 720 {
_ = ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_interval_sati", strconv.Itoa(n))
}
}
if v := r.FormValue("backup_broj_kopija"); v != "" {
if n, err := strconv.Atoi(v); err == nil && n >= 1 && n <= 100 {
_ = ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_broj_kopija", strconv.Itoa(n))
}
}
sledeci := r.FormValue("_next")
if sledeci == "" || !strings.HasPrefix(sledeci, "/") {
sledeci = "/podesavanja"
}
// backup podešavanja — pri neispravnom unosu javljamo jasnu grešku
// umesto da ga tiho preskočimo a korisniku prikažemo "sačuvano"
if v := r.FormValue("backup_interval_sati"); v != "" {
n, err := strconv.Atoi(v)
if err != nil || n < 1 || n > 720 {
middleware.SetFlash(w, r, h.DB, "greska", "Razmak između backupa mora biti broj između 1 i 720 sati.")
http.Redirect(w, r, sledeci, http.StatusSeeOther)
return
}
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_interval_sati", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return
}
}
if v := r.FormValue("backup_broj_kopija"); v != "" {
n, err := strconv.Atoi(v)
if err != nil || n < 1 || n > 100 {
middleware.SetFlash(w, r, h.DB, "greska", "Broj kopija mora biti broj između 1 i 100.")
http.Redirect(w, r, sledeci, http.StatusSeeOther)
return
}
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_broj_kopija", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return
}
}
http.Redirect(w, r, sledeci+"?sacuvano=1", http.StatusSeeOther)
}