feat(rbac): zaštita mutirajućih ruta na ruteru (RequireDozvolaMut)
Mutirajuće rute (POST + brisanja preko GET-a) više se ne oslanjaju samo na
ručnu proveru u handleru. Uvedena middleware RequireDozvolaMut koja na odbijanje
vraća 403 (za razliku od RequireDozvola koja redirektuje, a ostaje za GET
preglede). U main.go svaka mutacija je obmotana helperom doz("modul.akcija"),
pa je ruter sada garantovani sloj zaštite — zaboravljena provera u handleru ne
ostavlja endpoint nezaštićenim.
Mapiranje rute->dozvola izvučeno iz postojećih provera u handlerima. Ručne
provere (zahtevajDozvolu) zadržane kao odbrana u dubinu. Namerni izuzeci:
javne rute, /podsetnici/* (bez dozvole po dizajnu), /admin/* (RequireAdmin po
ulozi) i lične profil-akcije.
This commit is contained in:
+39
-32
@@ -189,6 +189,13 @@ func main() {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(ntechmw.RequireAuth(db, totpKljuc))
|
||||
|
||||
// doz vraća middleware koji na ruteru zahteva datu dozvolu za mutirajuću
|
||||
// rutu (403 ako uloga nema dozvolu). Ruter je time garantovani sloj zaštite
|
||||
// — zaboravljena provera u handleru ne ostavlja endpoint nezaštićenim.
|
||||
doz := func(akcija string) func(http.Handler) http.Handler {
|
||||
return ntechmw.RequireDozvolaMut(h.DozvoleRepo.ImaDozvolu, akcija)
|
||||
}
|
||||
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/dashboard", http.StatusFound)
|
||||
})
|
||||
@@ -197,56 +204,56 @@ func main() {
|
||||
r.Get("/admin/podesavanja/opste", h.PodesavanjaOpste)
|
||||
r.Get("/admin/podesavanja/izgled", h.PodesavanjaIzgled)
|
||||
r.Get("/admin/podesavanja/sistem", h.PodesavanjaSistem)
|
||||
r.Post("/podesavanja/sacuvaj", h.SacuvajPodesavanja)
|
||||
r.Post("/podesavanja/logo", h.OtpremiLogo)
|
||||
r.Post("/podesavanja/login-pozadina", h.OtpremiLoginPozadinu)
|
||||
r.Post("/podesavanja/login-pozadina/ukloni", h.UkloniLoginPozadinu)
|
||||
r.Post("/podesavanja/login-pozadina/stilovi", h.SacuvajLoginPozadinaStilove)
|
||||
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/sacuvaj", h.SacuvajPodesavanja)
|
||||
r.With(doz("podesavanja.izmeni")).Post("/podesavanja/logo", h.OtpremiLogo)
|
||||
r.With(doz("podesavanja.login_pozadina")).Post("/podesavanja/login-pozadina", h.OtpremiLoginPozadinu)
|
||||
r.With(doz("podesavanja.login_pozadina")).Post("/podesavanja/login-pozadina/ukloni", h.UkloniLoginPozadinu)
|
||||
r.With(doz("podesavanja.login_pozadina")).Post("/podesavanja/login-pozadina/stilovi", h.SacuvajLoginPozadinaStilove)
|
||||
|
||||
r.Get("/podesavanja/backup", h.BackupBaze)
|
||||
r.Post("/podesavanja/backup/vrati", h.VratiBackup)
|
||||
r.With(doz("backup.pokreni")).Post("/podesavanja/backup/vrati", h.VratiBackup)
|
||||
r.Get("/magacin", h.Magacin)
|
||||
r.Get("/magacin/novi", h.NoviArtikal)
|
||||
r.Post("/magacin/novi", h.SacuvajArtikal)
|
||||
r.With(doz("artikal.dodaj")).Post("/magacin/novi", h.SacuvajArtikal)
|
||||
r.Get("/magacin/izmeni/{id}", h.IzmeniArtikal)
|
||||
r.Post("/magacin/izmeni/{id}", h.SacuvajIzmenuArtikla)
|
||||
r.Get("/magacin/obrisi/{id}", h.ObrisiArtikal)
|
||||
r.Post("/magacin/premesti/{id}", h.PremestiArtikal)
|
||||
r.With(doz("artikal.izmeni")).Post("/magacin/izmeni/{id}", h.SacuvajIzmenuArtikla)
|
||||
r.With(doz("artikal.obrisi")).Get("/magacin/obrisi/{id}", h.ObrisiArtikal)
|
||||
r.With(doz("artikal.premesti")).Post("/magacin/premesti/{id}", h.PremestiArtikal)
|
||||
r.Get("/magacin/kategorije", h.Kategorije)
|
||||
r.Post("/magacin/kategorije/dodaj", h.DodajKategoriju)
|
||||
r.Get("/magacin/kategorije/obrisi/{id}", h.ObrisiKategoriju)
|
||||
r.With(doz("kategorija.dodaj")).Post("/magacin/kategorije/dodaj", h.DodajKategoriju)
|
||||
r.With(doz("kategorija.obrisi")).Get("/magacin/kategorije/obrisi/{id}", h.ObrisiKategoriju)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "nabavka.pregled")).Get("/nabavke", h.Nabavke)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "nabavka.pregled")).Get("/nabavke/nova", h.NovaNabavka)
|
||||
r.Post("/nabavke/nova", h.SacuvajNabavku)
|
||||
r.With(doz("nabavka.dodaj")).Post("/nabavke/nova", h.SacuvajNabavku)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "nabavka.pregled")).Get("/nabavke/{id}", h.DetaljiNabavke)
|
||||
r.Post("/nabavke/obrisi/{id}", h.ObrisiNabavku)
|
||||
r.With(doz("nabavka.obrisi")).Post("/nabavke/obrisi/{id}", h.ObrisiNabavku)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "dobavljac.pregled")).Get("/dobavljaci", h.Dobavljaci)
|
||||
r.Get("/dobavljaci/novi", h.NoviDobavljac)
|
||||
r.Post("/dobavljaci/novi", h.SacuvajDobavljaca)
|
||||
r.With(doz("dobavljac.dodaj")).Post("/dobavljaci/novi", h.SacuvajDobavljaca)
|
||||
r.Get("/dobavljaci/izmeni/{id}", h.IzmeniDobavljaca)
|
||||
r.Post("/dobavljaci/izmeni/{id}", h.SacuvajIzmeneDobavljaca)
|
||||
r.Post("/dobavljaci/obrisi/{id}", h.ObrisiDobavljaca)
|
||||
r.With(doz("dobavljac.izmeni")).Post("/dobavljaci/izmeni/{id}", h.SacuvajIzmeneDobavljaca)
|
||||
r.With(doz("dobavljac.obrisi")).Post("/dobavljaci/obrisi/{id}", h.ObrisiDobavljaca)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "klijent.pregled")).Get("/klijenti", h.Klijenti)
|
||||
r.Get("/klijenti/novi", h.NoviKlijent)
|
||||
r.Post("/klijenti/novi", h.SacuvajKlijenta)
|
||||
r.With(doz("klijent.dodaj")).Post("/klijenti/novi", h.SacuvajKlijenta)
|
||||
r.Get("/klijenti/izmeni/{id}", h.IzmeniKlijenta)
|
||||
r.Post("/klijenti/izmeni/{id}", h.SacuvajIzmenuKlijenta)
|
||||
r.Post("/klijenti/obrisi/{id}", h.ObrisiKlijenta)
|
||||
r.With(doz("klijent.izmeni")).Post("/klijenti/izmeni/{id}", h.SacuvajIzmenuKlijenta)
|
||||
r.With(doz("klijent.obrisi")).Post("/klijenti/obrisi/{id}", h.ObrisiKlijenta)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis", h.Servis)
|
||||
r.Get("/servis/novi", h.NoviNalog)
|
||||
r.Post("/servis/novi", h.SacuvajNalog)
|
||||
r.With(doz("servis.dodaj")).Post("/servis/novi", h.SacuvajNalog)
|
||||
r.Get("/servis/izmeni/{id}", h.IzmeniNalog)
|
||||
r.Post("/servis/izmeni/{id}", h.SacuvajIzmenaNaloga)
|
||||
r.Post("/servis/obrisi/{id}", h.ObrisiNalog)
|
||||
r.With(doz("servis.izmeni")).Post("/servis/izmeni/{id}", h.SacuvajIzmenaNaloga)
|
||||
r.With(doz("servis.obrisi")).Post("/servis/obrisi/{id}", h.ObrisiNalog)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}", h.DetaljiNaloga)
|
||||
r.Post("/servis/{id}/delovi", h.DodajDeloNalogu)
|
||||
r.Post("/servis/{id}/delovi/{deo_id}/obrisi", h.ObrisiDeloNaloga)
|
||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/delovi", h.DodajDeloNalogu)
|
||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/delovi/{deo_id}/obrisi", h.ObrisiDeloNaloga)
|
||||
r.Get("/izvestaji", h.Izvestaji)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "prodaja.pregled")).Get("/prodaja", h.Prodaja)
|
||||
r.Get("/prodaja/nova", h.NovaProdaja)
|
||||
r.Post("/prodaja/nova", h.SacuvajProdaju)
|
||||
r.Post("/prodaja/obrisi/{id}", h.ObrisiProdaju)
|
||||
r.Post("/prodaja/storno/{id}", h.StornoProdaje)
|
||||
r.With(doz("prodaja.dodaj")).Post("/prodaja/nova", h.SacuvajProdaju)
|
||||
r.With(doz("prodaja.obrisi")).Post("/prodaja/obrisi/{id}", h.ObrisiProdaju)
|
||||
r.With(doz("prodaja.storno")).Post("/prodaja/storno/{id}", h.StornoProdaje)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "prodaja.pregled")).Get("/prodaja/{id}/stampa", h.StampaProdaje)
|
||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "prodaja.pregled")).Get("/prodaja/{id}", h.DetaljiProdaje)
|
||||
|
||||
@@ -284,11 +291,11 @@ func main() {
|
||||
r.Get("/admin/profil/totp/pokreni", h.AdminTotpPokreni)
|
||||
r.Post("/admin/profil/totp/aktiviraj", h.AdminTotpAktivacija)
|
||||
r.Post("/admin/profil/totp/deaktiviraj", h.AdminTotpDeaktivacija)
|
||||
r.Post("/profil/tema", h.SacuvajLokalnuTemu)
|
||||
r.With(doz("tema.lokalno")).Post("/profil/tema", h.SacuvajLokalnuTemu)
|
||||
r.Get("/profil/tema", h.ProfilTema)
|
||||
r.Post("/profil/pozadina", h.ProfilOtpremiPozadinu)
|
||||
r.Post("/profil/pozadina/ukloni", h.ProfilUkloniPozadinu)
|
||||
r.Post("/profil/pozadina/stilovi", h.ProfilSacuvajPozadinuStilove)
|
||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina", h.ProfilOtpremiPozadinu)
|
||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina/ukloni", h.ProfilUkloniPozadinu)
|
||||
r.With(doz("tema.lokalno")).Post("/profil/pozadina/stilovi", h.ProfilSacuvajPozadinuStilove)
|
||||
})
|
||||
|
||||
log.Printf("NTech pokrenut na portu %s", port)
|
||||
|
||||
Reference in New Issue
Block a user