Demo mod: ograničenje bekapa i blokada promene lozinke

- Bekap se ograničava na 2 kopije u demo modu (umesto 7)
- Promena lozinke je blokirana u demo modu — handler odbija zahtev,
  a šablon sakriva formu i prikazuje obaveštenje korisniku
This commit is contained in:
2026-06-19 01:16:24 +02:00
parent 1cfb44b9a4
commit 1ab16c9efa
3 changed files with 29 additions and 4 deletions
+14 -4
View File
@@ -125,7 +125,13 @@ func main() {
slog.Info("šifrovane postojeće TOTP tajne", "broj", br)
}
napraviBackup(db, putanjaBaze)
{
max := procitajIntPodesavanje(db, "backup_broj_kopija", 7)
if os.Getenv("NTECH_ENV") == "demo" {
max = 2
}
napraviBackup(db, putanjaBaze, max)
}
os.MkdirAll("web/static/uploads", 0755)
@@ -168,7 +174,11 @@ func main() {
})
time.Sleep(time.Duration(sati) * time.Hour)
h.SaBazom(func(db *sql.DB) {
napraviBackup(db, putanjaBaze)
max := procitajIntPodesavanje(db, "backup_broj_kopija", 7)
if h.JelDemo {
max = 2
}
napraviBackup(db, putanjaBaze, max)
})
}
}()
@@ -456,7 +466,7 @@ func postaviDemoKorisnika(ctx context.Context, repo db.KorisniciRepository) erro
// napraviBackup kreira konzistentnu kopiju baze i briše najstarije preko zadatog broja kopija.
// Koristi već otvorenu vezu ka bazi (VACUUM INTO je bezbedan na pooled konekciji).
func napraviBackup(db *sql.DB, putanjaBaze string) {
func napraviBackup(db *sql.DB, putanjaBaze string, maxKopija int) {
if _, err := os.Stat(putanjaBaze); os.IsNotExist(err) {
return
}
@@ -476,7 +486,7 @@ func napraviBackup(db *sql.DB, putanjaBaze string) {
}
slog.Info("backup kreiran", "putanja", odrediste)
ocistiStareBackupe(folder, procitajIntPodesavanje(db, "backup_broj_kopija", 7))
ocistiStareBackupe(folder, maxKopija)
}
// procitajIntPodesavanje vraća celobrojnu vrednost podešavanja iz baze,
+11
View File
@@ -35,6 +35,7 @@ type podaciAdminProfil struct {
BrojRezervnih int // koliko neiskorišćenih rezervnih kodova je preostalo
LokalnaTema string
KoristiLokalnuTemu bool
JelDemo bool
}
type podaciProfilTema struct {
@@ -312,6 +313,7 @@ func (h *Handler) AdminProfil(w http.ResponseWriter, r *http.Request) {
BrojRezervnih: brojRezervnih,
LokalnaTema: svezi.LokalnaTema,
KoristiLokalnuTemu: svezi.KoristiLokalnuTemu,
JelDemo: h.JelDemo,
})
}
@@ -352,6 +354,7 @@ func (h *Handler) generisiIPrikaziKodove(w http.ResponseWriter, r *http.Request,
TotpAktivan: true,
RezervniKodovi: kodovi,
BrojRezervnih: len(kodovi),
JelDemo: h.JelDemo,
})
}
@@ -363,6 +366,12 @@ func (h *Handler) AdminPromeniLozinku(w http.ResponseWriter, r *http.Request) {
return
}
if h.JelDemo {
middleware.SetFlash(w, r, h.DB, "greska", "Promena lozinke nije dozvoljena u demo modu.")
http.Redirect(w, r, "/admin/profil", http.StatusSeeOther)
return
}
if err := r.ParseForm(); err != nil {
middleware.SetFlash(w, r, h.DB, "greska", "Greška. Pokušajte ponovo.")
http.Redirect(w, r, "/admin/profil", http.StatusSeeOther)
@@ -426,6 +435,7 @@ func (h *Handler) AdminTotpPokreni(w http.ResponseWriter, r *http.Request) {
TotpURI: totp.URI,
TotpTajna: totp.Tajna,
TotpQR: template.URL("data:image/png;base64," + totp.QRBase64),
JelDemo: h.JelDemo,
})
}
@@ -465,6 +475,7 @@ func (h *Handler) AdminTotpAktivacija(w http.ResponseWriter, r *http.Request) {
TotpTajna: tajna,
TotpQR: template.URL("data:image/png;base64," + qr),
Greska: "totp",
JelDemo: h.JelDemo,
})
return
}
+4
View File
@@ -5,6 +5,9 @@
<div class="kartica animiraj">
<div style="font-size: 15px; font-weight: 500; color: var(--tekst-glavni); margin-bottom: 16px; padding-bottom: 12px; border-bottom: 0.5px solid var(--ivica)">Promena lozinke</div>
{{if .JelDemo}}
<p style="font-size: 13px; color: var(--tekst-sporedni)">Promena lozinke nije dostupna u demo modu.</p>
{{else}}
<form method="POST" action="/admin/profil/lozinka">
<div style="display: flex; flex-direction: column; gap: 12px">
<div>
@@ -24,6 +27,7 @@
</div>
</div>
</form>
{{end}}
</div>
<!-- TOTP / 2FA -->