Izmena u radu tema

This commit is contained in:
2026-06-06 17:47:52 +02:00
parent 6a3500c25a
commit 5d94ea34cf
32 changed files with 1182 additions and 179 deletions
+5 -2
View File
@@ -86,6 +86,8 @@ type KorisniciRepository interface {
AzurirajAktivan(ctx context.Context, id int64, aktivan bool) error
PromeniLozinku(ctx context.Context, id int64, hash string) error
SacuvajTotpTajnu(ctx context.Context, id int64, tajna string) error
SacuvajLokalnuTemu(ctx context.Context, id int64, lokalnaTema string, koristi bool) error
SacuvajLokalnuPozadinu(ctx context.Context, id int64, pozadina, opacity, blur, blurPozadine string) error
PostojiIjedan(ctx context.Context) (bool, error)
Obrisi(ctx context.Context, id int64) error
}
@@ -101,7 +103,8 @@ type SesijeRepository interface {
// PodsetnikFilter definiše parametre za filtriranje liste podsetnika
type PodsetnikFilter struct {
SamoAktivni bool // true = samo nezavršeni; false = svi
SamoAktivni bool // true = samo nezavršeni; false = svi
KorisnikID *int64 // ako nije nil — samo podsetnici tog korisnika
}
// PokusajiPrijaveRepository definiše operacije nad evidencijom pokušaja prijave
@@ -134,5 +137,5 @@ type PodsetnikRepository interface {
Izmeni(ctx context.Context, p *model.Podsetnik) error
OznaciZavrsenim(ctx context.Context, id int64, zavrseno bool) error
Obrisi(ctx context.Context, id int64) error
BrojAktivnih(ctx context.Context) (int, error)
BrojAktivnih(ctx context.Context, filter PodsetnikFilter) (int, error)
}
+78 -10
View File
@@ -29,41 +29,69 @@ func (r *sqliteKorisniciRepo) Kreiraj(ctx context.Context, korisnickoIme, lozink
func (r *sqliteKorisniciRepo) DohvatiPoImenu(ctx context.Context, korisnickoIme string) (*model.Korisnik, error) {
k := &model.Korisnik{}
var aktivan int
var totpTajna sql.NullString
var aktivan, koristiLokalnuTemu int
var totpTajna, lokalnaTema sql.NullString
var lokalnaPozadina, lokalnaPozadinaOpacity, lokalnaPozadinaBlur, lokalnaPozadinaBlurPozadine sql.NullString
var datumKreiranja time.Time
err := r.db.QueryRowContext(ctx,
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''), datum_kreiranja
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''),
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0')
FROM korisnici WHERE korisnicko_ime = ?`, korisnickoIme).
Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &totpTajna, &datumKreiranja)
Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &totpTajna,
&lokalnaTema, &koristiLokalnuTemu, &datumKreiranja,
&lokalnaPozadina, &lokalnaPozadinaOpacity, &lokalnaPozadinaBlur, &lokalnaPozadinaBlurPozadine)
if err != nil {
return nil, fmt.Errorf("ntech: korisnici.DohvatiPoImenu: %w", err)
}
k.Aktivan = aktivan == 1
k.TotpTajna = totpTajna.String
k.LokalnaTema = lokalnaTema.String
k.KoristiLokalnuTemu = koristiLokalnuTemu == 1
k.DatumKreiranja = datumKreiranja
k.LokalnaPozadina = lokalnaPozadina.String
k.LokalnaPozadinaOpacity = lokalnaPozadinaOpacity.String
k.LokalnaPozadinaBlur = lokalnaPozadinaBlur.String
k.LokalnaPozadinaBlurPozadine = lokalnaPozadinaBlurPozadine.String
return k, nil
}
func (r *sqliteKorisniciRepo) DohvatiPoID(ctx context.Context, id int64) (*model.Korisnik, error) {
k := &model.Korisnik{}
var aktivan int
var aktivan, koristiLokalnuTemu int
var lokalnaTema sql.NullString
var lokalnaPozadina, lokalnaPozadinaOpacity, lokalnaPozadinaBlur, lokalnaPozadinaBlurPozadine sql.NullString
var datumKreiranja time.Time
err := r.db.QueryRowContext(ctx,
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''), datum_kreiranja
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''),
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0')
FROM korisnici WHERE id = ?`, id).
Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &k.TotpTajna, &datumKreiranja)
Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &k.TotpTajna,
&lokalnaTema, &koristiLokalnuTemu, &datumKreiranja,
&lokalnaPozadina, &lokalnaPozadinaOpacity, &lokalnaPozadinaBlur, &lokalnaPozadinaBlurPozadine)
if err != nil {
return nil, fmt.Errorf("ntech: korisnici.DohvatiPoID: %w", err)
}
k.Aktivan = aktivan == 1
k.LokalnaTema = lokalnaTema.String
k.KoristiLokalnuTemu = koristiLokalnuTemu == 1
k.DatumKreiranja = datumKreiranja
k.LokalnaPozadina = lokalnaPozadina.String
k.LokalnaPozadinaOpacity = lokalnaPozadinaOpacity.String
k.LokalnaPozadinaBlur = lokalnaPozadinaBlur.String
k.LokalnaPozadinaBlurPozadine = lokalnaPozadinaBlurPozadine.String
return k, nil
}
func (r *sqliteKorisniciRepo) Lista(ctx context.Context) ([]model.Korisnik, error) {
rows, err := r.db.QueryContext(ctx,
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''), datum_kreiranja
`SELECT id, korisnicko_ime, lozinka_hash, uloga, aktivan, COALESCE(totp_tajna, ''),
COALESCE(lokalna_tema, ''), koristi_lokalnu_temu, datum_kreiranja,
COALESCE(lokalna_pozadina, ''), COALESCE(lokalna_pozadina_opacity, '50'),
COALESCE(lokalna_pozadina_blur, '12'), COALESCE(lokalna_pozadina_blur_pozadine, '0')
FROM korisnici ORDER BY datum_kreiranja ASC`)
if err != nil {
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
@@ -72,18 +100,58 @@ func (r *sqliteKorisniciRepo) Lista(ctx context.Context) ([]model.Korisnik, erro
var lista []model.Korisnik
for rows.Next() {
var k model.Korisnik
var aktivan int
var aktivan, koristiLokalnuTemu int
var lokalnaTema sql.NullString
var lokalnaPozadina, lokalnaPozadinaOpacity, lokalnaPozadinaBlur, lokalnaPozadinaBlurPozadine sql.NullString
var datumKreiranja time.Time
if err := rows.Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &k.TotpTajna, &datumKreiranja); err != nil {
if err := rows.Scan(&k.ID, &k.KorisnickoIme, &k.LozinkaHash, &k.Uloga, &aktivan, &k.TotpTajna,
&lokalnaTema, &koristiLokalnuTemu, &datumKreiranja,
&lokalnaPozadina, &lokalnaPozadinaOpacity, &lokalnaPozadinaBlur, &lokalnaPozadinaBlurPozadine); err != nil {
return nil, fmt.Errorf("ntech: korisnici.Lista: %w", err)
}
k.Aktivan = aktivan == 1
k.LokalnaTema = lokalnaTema.String
k.KoristiLokalnuTemu = koristiLokalnuTemu == 1
k.DatumKreiranja = datumKreiranja
k.LokalnaPozadina = lokalnaPozadina.String
k.LokalnaPozadinaOpacity = lokalnaPozadinaOpacity.String
k.LokalnaPozadinaBlur = lokalnaPozadinaBlur.String
k.LokalnaPozadinaBlurPozadine = lokalnaPozadinaBlurPozadine.String
lista = append(lista, k)
}
return lista, nil
}
func (r *sqliteKorisniciRepo) SacuvajLokalnuPozadinu(ctx context.Context, id int64, pozadina, opacity, blur, blurPozadine string) error {
_, err := r.db.ExecContext(ctx,
`UPDATE korisnici SET lokalna_pozadina = ?, lokalna_pozadina_opacity = ?, lokalna_pozadina_blur = ?, lokalna_pozadina_blur_pozadine = ? WHERE id = ?`,
pozadina, opacity, blur, blurPozadine, id)
if err != nil {
return fmt.Errorf("ntech: korisnici.SacuvajLokalnuPozadinu: %w", err)
}
return nil
}
func (r *sqliteKorisniciRepo) SacuvajLokalnuTemu(ctx context.Context, id int64, lokalnaTema string, koristi bool) error {
koristiInt := 0
if koristi {
koristiInt = 1
}
var tema interface{}
if lokalnaTema == "" {
tema = nil
} else {
tema = lokalnaTema
}
_, err := r.db.ExecContext(ctx,
`UPDATE korisnici SET lokalna_tema = ?, koristi_lokalnu_temu = ? WHERE id = ?`,
tema, koristiInt, id)
if err != nil {
return fmt.Errorf("ntech: korisnici.SacuvajLokalnuTemu: %w", err)
}
return nil
}
func (r *sqliteKorisniciRepo) AzurirajUlogu(ctx context.Context, id int64, uloga string) error {
_, err := r.db.ExecContext(ctx, `UPDATE korisnici SET uloga = ? WHERE id = ?`, uloga, id)
if err != nil {
+46 -15
View File
@@ -22,17 +22,24 @@ func NoviPodsetnikRepo(db *sql.DB) *PodsetnikRepo {
// Lista vraća listu podsetnika sa opcionim filterom
func (r *PodsetnikRepo) Lista(ctx context.Context, filter db.PodsetnikFilter) ([]model.Podsetnik, error) {
upit := `
SELECT id, naslov, napomena, datum_podsecanja, zavrseno, tip, datum_unosa
SELECT id, naslov, napomena, datum_podsecanja, zavrseno, tip, datum_unosa, korisnik_id
FROM podsetnici
WHERE 1=1`
var args []any
if filter.SamoAktivni {
upit += " AND zavrseno = 0"
}
if filter.KorisnikID != nil {
upit += " AND korisnik_id = ?"
args = append(args, *filter.KorisnikID)
}
upit += " ORDER BY datum_podsecanja ASC"
redovi, err := r.db.QueryContext(ctx, upit)
redovi, err := r.db.QueryContext(ctx, upit, args...)
if err != nil {
return nil, fmt.Errorf("ntech: PodsetnikRepo.Lista: %w", err)
}
@@ -42,15 +49,19 @@ func (r *PodsetnikRepo) Lista(ctx context.Context, filter db.PodsetnikFilter) ([
for redovi.Next() {
var p model.Podsetnik
var napomena sql.NullString
var korisnikID sql.NullInt64
var zavrseno int
err := redovi.Scan(
&p.ID, &p.Naslov, &napomena, &p.DatumPodsecanja, &zavrseno, &p.Tip, &p.DatumUnosa,
&p.ID, &p.Naslov, &napomena, &p.DatumPodsecanja, &zavrseno, &p.Tip, &p.DatumUnosa, &korisnikID,
)
if err != nil {
return nil, fmt.Errorf("ntech: PodsetnikRepo.Lista: scan: %w", err)
}
p.Napomena = napomena.String
p.Zavrseno = zavrseno == 1
if korisnikID.Valid {
p.KorisnikID = &korisnikID.Int64
}
rezultat = append(rezultat, p)
}
@@ -61,12 +72,13 @@ func (r *PodsetnikRepo) Lista(ctx context.Context, filter db.PodsetnikFilter) ([
func (r *PodsetnikRepo) DohvatiID(ctx context.Context, id int64) (*model.Podsetnik, error) {
var p model.Podsetnik
var napomena sql.NullString
var korisnikID sql.NullInt64
var zavrseno int
err := r.db.QueryRowContext(ctx, `
SELECT id, naslov, napomena, datum_podsecanja, zavrseno, tip, datum_unosa
SELECT id, naslov, napomena, datum_podsecanja, zavrseno, tip, datum_unosa, korisnik_id
FROM podsetnici WHERE id = ?`, id).Scan(
&p.ID, &p.Naslov, &napomena, &p.DatumPodsecanja, &zavrseno, &p.Tip, &p.DatumUnosa,
&p.ID, &p.Naslov, &napomena, &p.DatumPodsecanja, &zavrseno, &p.Tip, &p.DatumUnosa, &korisnikID,
)
if err != nil {
return nil, fmt.Errorf("ntech: PodsetnikRepo.DohvatiID: %w", err)
@@ -74,16 +86,24 @@ func (r *PodsetnikRepo) DohvatiID(ctx context.Context, id int64) (*model.Podsetn
p.Napomena = napomena.String
p.Zavrseno = zavrseno == 1
if korisnikID.Valid {
p.KorisnikID = &korisnikID.Int64
}
return &p, nil
}
// Kreiraj dodaje novi podsetnik u bazu
func (r *PodsetnikRepo) Kreiraj(ctx context.Context, p *model.Podsetnik) (int64, error) {
var korisnikID interface{}
if p.KorisnikID != nil {
korisnikID = *p.KorisnikID
}
rezultat, err := r.db.ExecContext(ctx, `
INSERT INTO podsetnici (naslov, napomena, datum_podsecanja, tip)
VALUES (?, ?, ?, ?)`,
p.Naslov, nullString(p.Napomena), p.DatumPodsecanja, p.Tip,
INSERT INTO podsetnici (naslov, napomena, datum_podsecanja, tip, korisnik_id)
VALUES (?, ?, ?, ?, ?)`,
p.Naslov, nullString(p.Napomena), p.DatumPodsecanja, p.Tip, korisnikID,
)
if err != nil {
return 0, fmt.Errorf("ntech: PodsetnikRepo.Kreiraj: %w", err)
@@ -99,11 +119,16 @@ func (r *PodsetnikRepo) Kreiraj(ctx context.Context, p *model.Podsetnik) (int64,
// Izmeni ažurira postojeći podsetnik
func (r *PodsetnikRepo) Izmeni(ctx context.Context, p *model.Podsetnik) error {
var korisnikID interface{}
if p.KorisnikID != nil {
korisnikID = *p.KorisnikID
}
_, err := r.db.ExecContext(ctx, `
UPDATE podsetnici SET
naslov = ?, napomena = ?, datum_podsecanja = ?, tip = ?
naslov = ?, napomena = ?, datum_podsecanja = ?, tip = ?, korisnik_id = ?
WHERE id = ?`,
p.Naslov, nullString(p.Napomena), p.DatumPodsecanja, p.Tip, p.ID,
p.Naslov, nullString(p.Napomena), p.DatumPodsecanja, p.Tip, korisnikID, p.ID,
)
if err != nil {
return fmt.Errorf("ntech: PodsetnikRepo.Izmeni: %w", err)
@@ -138,12 +163,18 @@ func (r *PodsetnikRepo) Obrisi(ctx context.Context, id int64) error {
return nil
}
// BrojAktivnih vraća broj nezavršenih podsetnika
func (r *PodsetnikRepo) BrojAktivnih(ctx context.Context) (int, error) {
// BrojAktivnih vraća broj nezavršenih podsetnika, opcionalno filtrirano po korisniku
func (r *PodsetnikRepo) BrojAktivnih(ctx context.Context, filter db.PodsetnikFilter) (int, error) {
upit := "SELECT COUNT(*) FROM podsetnici WHERE zavrseno = 0"
var args []any
if filter.KorisnikID != nil {
upit += " AND korisnik_id = ?"
args = append(args, *filter.KorisnikID)
}
var broj int
err := r.db.QueryRowContext(ctx,
"SELECT COUNT(*) FROM podsetnici WHERE zavrseno = 0",
).Scan(&broj)
err := r.db.QueryRowContext(ctx, upit, args...).Scan(&broj)
if err != nil {
return 0, fmt.Errorf("ntech: PodsetnikRepo.BrojAktivnih: %w", err)
}