Bezbednost: superadmin može da odblokira IP adrese zaključane bruteforce zaštitom
Nova stranica /admin/blokirane-ip — lista IP adresa sa previše neuspelih pokušaja prijave (broj neuspeha, poslednji pokušaj, preostalo vreme zaključavanja) i dugme za ručno odblokiranje. Nova dozvola 'bezbednost.odblokiraj', namerno rezervisana isključivo za ulogu superadmin (admin je nema — odblokiranje zaobilazi bruteforce zaštitu). Repo metode PokusajiPrijaveRepo.ListaBlokiranih/Odblokiraj.
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"ntech/internal/model"
|
||||
)
|
||||
|
||||
// PokusajiPrijaveRepo implementira db.PokusajiPrijaveRepository nad SQLite
|
||||
@@ -77,3 +79,51 @@ func (r *PokusajiPrijaveRepo) ObrisiStare(ctx context.Context, pre time.Time) er
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListaBlokiranih vraća IP adrese sa najmanje prag neuspelih pokušaja prijave od
|
||||
// zadatog trenutka, grupisano po IP adresi, poređano od najskorije zaključane.
|
||||
func (r *PokusajiPrijaveRepo) ListaBlokiranih(ctx context.Context, od time.Time, prag int) ([]model.BlokiranaIP, error) {
|
||||
redovi, err := r.db.QueryContext(ctx,
|
||||
`SELECT ip, COUNT(*), MAX(vreme) FROM pokusaji_prijave
|
||||
WHERE uspeh = 0 AND vreme > ?
|
||||
GROUP BY ip HAVING COUNT(*) >= ?
|
||||
ORDER BY MAX(vreme) DESC`,
|
||||
od.UTC().Format("2006-01-02 15:04:05"), prag,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ntech: PokusajiPrijaveRepo.ListaBlokiranih: %w", err)
|
||||
}
|
||||
defer redovi.Close()
|
||||
|
||||
var lista []model.BlokiranaIP
|
||||
for redovi.Next() {
|
||||
var b model.BlokiranaIP
|
||||
var poslednji string
|
||||
if err := redovi.Scan(&b.IP, &b.BrojNeuspeha, &poslednji); err != nil {
|
||||
return nil, fmt.Errorf("ntech: PokusajiPrijaveRepo.ListaBlokiranih: scan: %w", err)
|
||||
}
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05", poslednji, time.UTC)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ntech: PokusajiPrijaveRepo.ListaBlokiranih: parse vremena: %w", err)
|
||||
}
|
||||
b.PoslednjiPokusaj = t
|
||||
lista = append(lista, b)
|
||||
}
|
||||
if err := redovi.Err(); err != nil {
|
||||
return nil, fmt.Errorf("ntech: PokusajiPrijaveRepo.ListaBlokiranih: %w", err)
|
||||
}
|
||||
return lista, nil
|
||||
}
|
||||
|
||||
// Odblokiraj briše sve neuspele pokušaje prijave za datu IP adresu — brojač
|
||||
// neuspeha odmah pada na nulu, pa IP prestaje da bude zaključana.
|
||||
func (r *PokusajiPrijaveRepo) Odblokiraj(ctx context.Context, ip string) error {
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
"DELETE FROM pokusaji_prijave WHERE ip = ? AND uspeh = 0",
|
||||
ip,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ntech: PokusajiPrijaveRepo.Odblokiraj: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user