Proširena wiki: arhitektura, bezbednost, razvoj, ažurirane sve stranice

Dasko
2026-06-21 02:16:00 +02:00
parent d2bf789731
commit ef3b7f2026
7 changed files with 671 additions and 89 deletions
+198
@@ -0,0 +1,198 @@
# Arhitektura
## Struktura direktorijuma
```
ntech/
├── assets.go # //go:embed za migrations, web/static, web/templates
├── cmd/ntech/main.go # ulazna tačka: ENV, FS izbor, migracije, ruter
├── go.mod # modul ntech, Go 1.26
├── internal/
│ ├── auth/ # bcrypt, TOTP, generisanje tokena, auth log
│ │ ├── auth.go # HashujLozinku, ProveriLozinku, TOTP operacije
│ │ └── log.go # fail2ban-kompatibilan format loga
│ ├── config/ # Prvo pokretanje (setup wizard)
│ │ ├── firstrun.go # JelPrvoPokretanje
│ │ └── setup.go # PokreniSetup (poseban HTTP server)
│ ├── db/
│ │ ├── repository.go # SVI interfejsi (ArtikalRepo, ServisRepo, ...)
│ │ ├── errors.go # ErrNedovoljnoKolicine
│ │ └── sqlite/ # SQLite implementacije (28 fajlova)
│ ├── handler/ # HTTP handleri — jedan fajl po domenu (26)
│ ├── middleware/ # Auth, CSRF, RBAC, bezbednost, flash
│ └── model/ # Domenske strukture i konstante (19 fajlova)
├── migrations/ # 61 SQL migracija (001-061), idempotentne
└── web/
├── static/ # CSS, JS, slike + uploads/
└── templates/ # Go html/template šabloni (komponente, stranice)
```
## Slojevi i zavisnosti
```
main.go
└─> handler/ → zna za: middleware, db (interfejsi), db/sqlite, model, auth
└─> middleware/ → zna za: db/sqlite, model
└─> db (interfejsi) → implementira: db/sqlite/
└─> model/ → ne zna ni za koga — čist domen, nula internih importa
└─> auth/ → samostalan, ne zavisi od handler/db
```
**Pravilo:** `model` je list (nema unutrašnje zavisnosti). `handler` je koren — svi putevi vode kroz njega. Nijedan drugi sloj ne sme da uvozi `handler`.
## Tok pokretanja programa
1. **MIME tipovi**`.js``text/javascript`, `.css``text/css`
2. **`godotenv.Load(ntech.env)`** — učitava ENV iz fajla
3. **`auth.InitAuthLog()`** — auth log u fail2ban formatu
4. **Izbor fajl-sistema** — disk-first za razvoj, embed za produkciju/demo
5. **Prvo pokretanje?** → Setup Wizard na portu 8080
6. **Baza + migracije**`sql.Open("sqlite", ...)`, WAL mod, migracije redom
7. **Init seme** — dozvole, TOTP ključ, bcrypt dummy hash, admin korisnik
8. **Chi ruter** — middleware stack, rute sa RBAC omotačima
9. **`http.ListenAndServe`** — server kreće
## Middleware stack
Redosled na chi ruteru:
```
1. middleware.RequestID # ID svakog zahteva
2. middleware.RealIP # Prava IP iz X-Forwarded-For
3. middleware.Logger # Slog logovanje
4. middleware.Recoverer # panic → 500
5. middleware.Compress(5, gzip) # GZip kompresija (nivo 5)
6. BezbednosniHeaderi # CSP, HSTS, X-Frame-Options, ...
7. CSRF # Double-submit cookie obrazac
8. FlashPoruke # Flash poruke u template kontekstu
--- (javne rute) ---
9. RequireAuth # Sesija → korisnik u context
10. RequireDozvola / RequireDozvolaMut # RBAC (zaštićene rute)
```
## Repository obrazac
Handleri **ne pišu SQL**. Sva komunikacija sa bazom ide preko interfejsa definisanih u `internal/db/repository.go`.
Primer interfejsa:
```go
// internal/db/repository.go
type ArtikalRepository interface {
Lista(ctx context.Context, filter ArtikalFilter) ([]model.ArtikalSaKategorijom, error)
DohvatiID(ctx context.Context, id int64) (*model.Artikal, error)
Kreiraj(ctx context.Context, a *model.Artikal) (int64, error)
Izmeni(ctx context.Context, a *model.Artikal) error
Obrisi(ctx context.Context, id int64) error
// ...
}
```
Implementacija:
```go
// internal/db/sqlite/artikal.go
type ArtikalRepo struct { db *sql.DB }
func NoviArtikalRepo(db *sql.DB) *ArtikalRepo { ... }
func (r *ArtikalRepo) Lista(ctx context.Context, f db.ArtikalFilter) ([]model.ArtikalSaKategorijom, error) {
// SELECT ... FROM artikli JOIN kategorije ...
}
```
Handler koristi interfejs:
```go
// internal/handler/magacin.go
type MagacinHandler struct {
Artikli db.ArtikalRepository
Kategorije db.KategorijaRepository
}
```
Ovakav dizajn omogućava:
- **Testiranje** — mock-ovanje repozitorijuma
- **Zamenu baze** — iste interfejse može implementirati PostgreSQL drajver
- **Jasne granice** — handler ne zavisi od SQL dijalekta
## Repozitorijumi (interfejsi)
| Interfejs | Domen |
|---|---|
| `ArtikalRepository` | Artikli, kategorije, cene, dobavljači, arhiviranje |
| `KategorijaRepository` | Kategorije artikala |
| `PdvStopaRepository` | Šifarnik PDV stopa |
| `DobavljacRepository` | Dobavljači |
| `KlijentRepository` | Klijenti (firme i fizička lica) |
| `ServisRepository` | Servisni nalozi, delovi, javni token |
| `ProdajaRepository` | Prodajni nalozi i stavke |
| `NabavkaRepository` | Nabavke, zavisni troškovi, nivelacije |
| `MagacinRepository` | Stanje zaliha, prometne kartice |
| `KorisniciRepository` | Korisnici i dozvole |
| `SesijeRepository` | Server-side sesije |
| `LoginIstorijaRepository` | Istorija prijava |
| `PokusajiPrijaveRepository` | Brute-force evidencija |
| `PodesavanjaRepository` | Sva sistemska podešavanja |
| `PodsetniciRepository` | Podsetnici |
| `PdvEvidencijaRepository` | PDV KIR/KPR evidencija |
| `IzvestajRepository` | Izveštajni upiti |
| `RezervniKodoviRepository` | Rezervni kodovi za 2FA |
## Handleri
Svaki handler je jedan Go fajl u `internal/handler/`:
| Fajl | Domen |
|---|---|
| `admin.go` | Admin panel: korisnici, dozvole |
| `dashboard.go` | Početna tabla sa statistikama |
| `dobavljac.go` | CRUD dobavljača |
| `izvestaji.go` | Izveštaji (promet, stanje, inventura, prihod) |
| `kategorija.go` | CRUD kategorija |
| `klijent.go` | CRUD klijenata, filteri |
| `magacin.go` | Magacin — pregled, pretraga, korekcija |
| `magacin_forma.go` | Forma za artikal |
| `nabavka.go` | Nabavke, nivelacije |
| `pdv_kir.go` | PDV KIR (knjiga izdatih računa) |
| `pdv_kpr.go` | PDV KPR (knjiga primljenih računa) |
| `pdv_obracun.go` | PDV obračun |
| `pdv_stopa.go` | Šifarnik PDV stopa |
| `podesavanja.go` | Sistemska podešavanja |
| `podsetnici.go` | Podsetnici |
| `prijava.go` | Prijava, odjava, TOTP, 2FA |
| `prodaja.go` | Prodajni nalozi |
| `profil.go` | Profil korisnika (lozinka, TOTP) |
| `servis.go` | Servisni nalozi |
| `handler.go` | Render helperi, `Render`, `RenderStranicu` |
| `kes.go` | Keširanje šablona |
| `utils.go` | Pomoćne funkcije (parsiranje, prikaz) |
## Frontend arhitektura
Frontend koristi tri biblioteke:
- **HTMX** — navigacija bez punog reload-a (`hx-get`, `hx-post`, `hx-target`, `hx-swap`)
- **Alpine.js** — reaktivnost na klijentu (`x-data`, `x-show`, `x-model`, `x-bind`)
- **Chart.js** — grafikoni (dashboard, izveštaji)
Stilovi su organizovani u `web/static/`:
- `main.css` — glavni stil (≈4000 linija)
- `glass.css` — glassmorphism efekti
- `login.css` — stilovi za prijavnu stranicu
Šabloni u `web/templates/`:
```
templates/
├── stranice/ # Kompletne stranice (dashboard.html, magacin.html, ...)
├── komponente/ # Deljive komponente (navbar.html, sidebar.html, modal.html)
├── teme/ # Varijacije tema
├── setup/ # Setup wizard
└── layout/ # Osnovni layout (base.html)
```
### HTMX pravila
- `hx-select` odbacuje `<head>` — stil koji mora da radi posle navigacije ide u `main.css`
- `hx-target` sa `#sadrzaj` — glavni kontejner za dinamički sadržaj
- `hx-push-url` — ažurira URL u adresnoj traci
- `hx-indicator` — prikazuje loader tokom zahteva
+121
@@ -0,0 +1,121 @@
# Bezbednost
## Autentifikacija
### Lozinke
- **bcrypt**, cost faktor **12**
- Heš se čuva u bazi, nikad u plaintext-u
- Anti-enumeracija: `IzjednaciVremeProvere` izvršava bcrypt poređenje i kad korisnik ne postoji — vreme odgovora je identično
```go
// internal/auth/auth.go
const bcryptCost = 12
func HashujLozinku(lozinka string) (string, error) {
return bcrypt.GenerateFromPassword([]byte(lozinka), bcryptCost)
}
func IzjednaciVremeProvere(lozinka string) {
_ = bcrypt.CompareHashAndPassword(dummyHash, []byte(lozinka))
}
```
### Dvofaktorska autentifikacija (2FA)
- **TOTP** (Time-based One-Time Password) — RFC 6238
- 6-cifreni kodovi, rotiraju na 30 sekundi
- Tajna se šifruje AES-256-GCM pre upisa u bazu
- QR kod za podešavanje u autentifikator aplikaciji
- Rezervni kodovi za oporavak (jednokratni, bcrypt heširani)
### Sesije
- **Server-side** — token u HTTP-only kolačiću `ntech_sesija`
- Token je **UUID v4** (`github.com/google/uuid`)
- Podaci sesije: `korisnik_id`, `token`, `created_at`, `expires_at`
- Nema osetljivih podataka u kolačiću — samo nasumični token
- `Secure` flag u produkciji i demo modu
- `HttpOnly` — JavaScript ne može da čita kolačić
- `SameSite=Lax` — zaštita od CSRF-a na nivou brauzera
## Brute-force zaštita
```
5 neuspelih pokušaja sa iste IP adrese u 15 minuta → IP se blokira
```
- Evidencija u tabeli `pokusaji_prijave`
- Auth log u fail2ban formatu (`/var/log/ntech/auth.log`)
- Pogodan za integraciju sa spoljnim fail2ban-om
## CSRF zaštita
- **Double-submit cookie** obrazac
- CSRF token se generiše na serveru i ubacuje u svaki `<form>`
- Token se upoređuje sa kolačićem pri svakoj POST/PUT/DELETE mutaciji
- Implementacija: `internal/middleware/csrf.go`
```html
<!-- Automatski ubacuje renderer -->
<form method="post" action="/magacin/novi">
<input type="hidden" name="csrf_token" value="...">
...
</form>
```
## RBAC — Kontrola pristupa zasnovana na ulogama
### Uloge
| Uloga | Opis |
|---|---|
| **superadmin** | Pun pristup — sve dozvole + dodela uloga |
| **admin** | Upravljanje korisnicima, podešavanja, svi moduli |
| **radnik** | Ograničen pristup — dodeljene dozvole po modulu |
### Dozvole (39 akcija)
Akcije su granularne: `modul.akcija` (npr. `artikal.dodaj`, `servis.obrisi`, `izvestaj.pregled`).
Neke rute su namerno **javne** (bez dozvole):
- `/magacin` — pregled magacina
- `/podsetnici` — svi prijavljeni vide svoje podsetnike
- `/prijava`, `/setup` — neautentifikovani pristup
### Middleware zaštita
```go
// Mutirajuće rute — vraća 403 na odbijanje
r.With(doz("prodaja.dodaj")).Post("/prodaja/nova", ...)
// GET rute — redirektuje na odbijanje
r.With(doz("nabavka.pregled")).Get("/nabavke", ...)
// Admin rute — po ulozi
r.Group(RequireAdmin) /admin/korisnici*, /admin/dozvole*
r.Group(RequireSuperAdmin) /admin/dozvole/uloga/{id}
```
## Security headeri
Svaki HTTP odgovor dobija:
| Header | Vrednost |
|---|---|
| `Content-Security-Policy` | Dinamički: `style-src`, `script-src`, `img-src`, `font-src` |
| `X-Content-Type-Options` | `nosniff` |
| `X-Frame-Options` | `DENY` |
| `X-XSS-Protection` | `0` (zastarelo, CSP preuzima) |
| `Referrer-Policy` | `strict-origin-when-cross-origin` |
| `Strict-Transport-Security` | `max-age=63072000` (samo u produkciji) |
## Ostale mere
- **XSS zaštita** — `ntechToast` koristi `textContent` (ne `innerHTML`)
- **Open redirect** — validacija `_next` parametra kroz whitelist
- **Limit upload-a** — `http.MaxBytesReader` za sve POST zahteve
- **Anti-MIME-sniffing** — `X-Content-Type-Options: nosniff`
- **CSP font-src** — dozvoljava samo `'self'` (rešava problem sa Chart.js fontovima u Operi/Chrome-u)
- **Secure kolačići** — `Secure=true` u produkciji i demo modu
- **OIE zaštita** — `SameSite=Lax` na svim kolačićima
+85 -35
@@ -2,57 +2,107 @@
## Magacin
- Skladištenje artikala sa kategorijama, šiframa i barkodovima
- Praćenje stanja zaliha sa kritičnim nivoima
- Prometna kartica — istorija ulaza i izlaza za svaki artikal
- Nabavna cena u formi artikla
- Inventura (popis magacina)
Upravljanje artiklima, kategorijama i zalihama.
- **Artikli** — naziv, opis, šifra, barkod, tip, jedinica mere
- **Kategorije** — grupisanje artikala, kategorije sa kodovima
- **Stanje zaliha** — trenutna količina, kritični minimum
- **Prometna kartica** — puna istorija ulaza i izlaza za svaki artikal
- **Korekcija količine** — ručno postavljanje stanja sa napomenom
- **Nabavna cena** — polje za nabavnu cenu u formi artikla
- **Arhiviranje** — artikal se ne briše već arhivira (čuva istoriju)
- **Šifra i barkod** — auto-generisanje (npr. `KOMP-0042`) + ručni unos
- **Pretraga** — po nazivu, šifri, barkodu, lokaciji, kategoriji
## Servis
- Servisni nalozi sa kompletnim praćenjem statusa
- Inline promena statusa direktno iz detalja naloga
- Štampa servisnog naloga sa QR kodom
- Otpremnica pri preuzimanju uređaja
- Pregled troškova i auto-cena delova
- Javni status naloga za klijente
Servisni nalozi sa kompletnim praćenjem.
- **Novi nalog** — prijem uređaja, opis kvara, klijent, garancija
- **Statusi** — primljen, u dijagnostici, čeka delove, u popravci, gotov, preuzet
- **Inline izmena statusa** — direktno iz detalja naloga, bez otvaranja forme
- **Delovi i troškovi** — auto-cena delova, pregled ukupnih troškova
- **Štampa** — štampa servisnog naloga sa QR kodom
- **Otpremnica** — pri preuzimanju uređaja
- **QR kod** — na štampanom nalogu i otpremnici
- **Javni status** — klijent može pratiti status preko tokena
- **Avans** — polje za avans na otpremnici
## Prodaja
- Fakture sa stavkama
- Obračun PDV-a (KIR, KPR)
- Formatiranje iznosa sa separatorom hiljada
- Avans na otpremnici
Prodajni nalozi i fakturisanje.
- **Nalozi** — prodajni dokumenti sa stavkama
- **Stavke** — artikal, količina, cena, PDV
- **Štampa** — štampanje prodajnog naloga/fakture
- **Storno** — poništavanje naloga
- **Formatiranje** — iznosi sa separatorom hiljada
## PDV
Potpuna evidencija PDV-a po srpskim propisima.
- **KIR** — Knjiga izdatih računa
- **KPR** — Knjiga primljenih računa
- **Obračun** — PDV obračun sa KIR/KPR podacima
- **Šifarnik stopa** — 20%, 10%, 0%, sa mogućnošću aktivacije/deaktivacije
- **Evidencija** — sve stavke sa PDV tretmanom, izvorom, iznosom
## Nabavka
- Nabavke po dobavljaču sa auto-vezom
- Predlog cene pri izboru artikla
- Filter artikala po dobavljaču
- Dvosmerno računanje marža ↔ prodajna cena
Upravljanje nabavkama i dobavljačima.
- **Dobavljači** — firme, PIB, mesto, kontakt
- **Nabavke** — dokumenti nabavke sa stavkama
- **Vezani dobavljači** — auto-veza artikaldobavljač pri nabavci
- **Filter po dobavljaču** — prikaz artikala vezanih za izabranog dobavljača
- **Predlog cene** — poslednja nabavna cena pri izboru artikla
- **Marža ↔ cena** — dvosmerno računanje: unesi maržu → dobiješ prodajnu, unesi prodajnu → dobiješ maržu
- **Zavisni troškovi** — transport, carina, špedicija na nabavci
- **Nivelacije** — korekcija nabavnih/prodajnih cena
## Klijenti
- Baza firmi i fizičkih lica
- Filter po tipu (Svi / Firme / Fizička lica)
- Interaktivna pretraga sa paginacijom
- Vezani dobavljači na kartici artikla
Baza klijenata — firme i fizička lica.
- **Firme** — naziv, PIB, mesto, kontakt, račun
- **Fizička lica** — ime, prezime, kontakt
- **Filter po tipu** — Svi / Firme / Fizička lica
- **Interaktivna pretraga** — pretraga po nazivu, mestu, kontaktu
- **Paginacija** — 50 po stranici
## Izveštaji
- Prometni list magacina
- Stanje zaliha
- Popis magacina (inventura)
- Servisni prihod — broji samo preuzete naloge
Pregled poslovanja kroz izveštaje.
## Podešavanja
- Logo firme u topbaru sa upload-om
- Tema sa slajderima za pozadinu i brzinu animacije
- Korisnici i RBAC dozvole (admin, korisnik)
- AJAX čuvanje podešavanja bez reload-a stranice
- **Prometni list** — ulaz/izlaz po artiklima za period
- **Stanje zaliha** — trenutno stanje svih artikala
- **Popis (inventura)** — popisne liste sa stvarnim stanjem
- **Servisni prihod** — prihod od servisa (samo preuzeti nalozi)
## Dashboard
- Statističke kartice sa linkovima na odgovarajuće stranice
- Hover efekti i glassmorphism dizajn
Početna tabla sa ključnim pokazateljima.
- **Stat kartice** — broj artikala, servisa, prodaja, klijenata
- **Grafikoni** — Chart.js vizualizacija prihoda
- **Linkovi** — kartice vode na odgovarajuće stranice
- **Hover efekti** — glassmorphism sa zatamnjenjem
## Podešavanja
Kompletna administracija sistema.
- **Opšte** — naziv firme, logo, kontakt, upload logoa, favicon
- **Tema** — pozadina, slajder za brzinu animacije, blur, glass opacity
- **Prijava** — pozadina prijavne stranice
- **Korisnici** — dodavanje, uređivanje, dozvole, reset lozinke
- **Dozvole** — RBAC matrica: uloga × akcija
- **Backup** — ručni backup baze i podešavanja
- **AJAX čuvanje** — podešavanja se čuvaju bez reload-a stranice
## Podsetnici
- Lični podsetnici za svakog korisnika
- Datum, vreme, opis
- Javni za sve prijavljene korisnike
+40 -24
@@ -1,37 +1,53 @@
# NTech — Servisni informacioni sistem
**NTech** je veb aplikacija za male servise, knjigovodstvo i upravljanje magacinom. Pisana je u **Go** jeziku, radi u brauzeru i podatke čuva u **SQLite** bazi.
**NTech** je veb aplikacija za male servise, knjigovodstvo i upravljanje magacinom. Pisana je u **Go** jeziku i radi u brauzeru. Podatke čuva u **SQLite** bazi — sve je upakovano u jedan binarni fajl, bez Docker-a, bez spoljnih servera.
---
## Osnovne mogućnosti
- **Magacin** — artikli, kategorije, stanje zaliha, prometne kartice, inventura
- **Servis** — servisni nalozi, otpremnice, štampa sa QR kodom, praćenje statusa
- **Prodaja** — fakture, stavke, obračun PDV-a
- **Nabavka** — nabavke po dobavljaču, auto-predlog cena, filter artikala
- **Klijenti** — firme i fizička lica, filteri, interaktivna pretraga
- **Izveštaji** — prometni list, stanje zaliha, popis magacina, servisni prihod
- **Podešavanja** — logo, tema, slajderi, korisnici i dozvole
| Modul | Opis |
|---|---|
| **Magacin** | Artikli, kategorije, stanje zaliha, prometne kartice, inventura |
| **Servis** | Servisni nalozi, otpremnice, štampa sa QR kodom, praćenje statusa, troškovi |
| **Prodaja** | Fakture, stavke, obračun PDV-a (KIR/KPR), avans |
| **Nabavka** | Nabavke po dobavljaču, auto-predlog cena, zavisni troškovi, nivelacije |
| **Klijenti** | Firme i fizička lica, filteri, interaktivna pretraga, vezani dobavljači |
| **Izveštaji** | Prometni list, stanje zaliha, popis magacina, servisni prihod |
| **Podešavanja** | Logo, tema, slajderi, animacije, korisnici, dozvole, backup |
## Tehnologije
---
## Tehnološki stek
| Komponenta | Tehnologija |
|---|---|
| Jezik | Go (najnovija stabilna verzija) |
| Baza | SQLite (`modernc.org/sqlite`, bez CGO) |
| HTTP ruter | `go-chi/chi` |
| Šabloni | `html/template` (Go standardna biblioteka) |
| Autentifikacija | bcrypt, TOTP 2FA, serverske sesije |
| Frontend | HTMX, Alpine.js, Chart.js |
| Jezik | **Go** (1.26+) |
| Baza | **SQLite** (`modernc.org/sqlite` — čist Go, bez CGO) |
| HTTP ruter | `go-chi/chi` v5 |
| Šabloni | `html/template` (Go stdlib) |
| Frontend | **HTMX** (navigacija), **Alpine.js** (reaktivnost), **Chart.js** (grafikoni) |
| Autentifikacija | bcrypt (cost 12), TOTP 2FA, serverske sesije |
| Sesije | HTTP-only kolačić sa tokenom (UUID), server-side u SQLite |
| Embed | `//go:embed` — šabloni, statika, migracije u binarnom fajlu |
## Bezbednost
---
- CSRF zaštita na svim mutacijama (double-submit cookie)
- Lozinke heširane bcrypt-om (cost 12)
- 2FA preko TOTP-a
- Brute-force zaštita (5 neuspelih pokušaja → 15 minuta blokada)
- Security headeri (CSP, HSTS, X-Content-Type-Options)
- Anti-enumeracija pri prijavi
## Arhitektura
## Licenca
- **Repository obrazac** — handleri ne znaju za SQL; rade preko interfejsa
- **Jedan binarni fajl** — sve je embed-ovano, nema spoljnih foldera u produkciji
- **Server-side sesije** — token u HTTP-only kolačiću, bez podataka u brauzeru
- **Migracije pri pokretanju** — 61 SQL migracija, idempotentne, rastuće numerisane
- **Bezbednost po difoltu** — CSRF, bcrypt, TOTP, brute-force zaštita, CSP, security headeri
- **Modularni handleri** — jedan Go fajl po domenu (magacin.go, servis.go, prodaja.go...)
Proprietary — sva prava zadržana.
---
## Linkovi
- [Instalacija](Instalacija)
- [Arhitektura](Arhitektura)
- [Funkcionalnosti](Funkcionalnosti)
- [Bezbednost](Bezbednost)
- [Razvoj](Razvoj)
+75 -30
@@ -3,60 +3,105 @@
## Preduslovi
- **Go** 1.26 ili noviji
- [Git](https://git-scm.com/) (opciono, za kloniranje)
- **Git** (za kloniranje)
- **Linux** ili **Windows** (build skripta podržava oba)
## Kloniranje i pokretanje
## Brzi start
```bash
# Kloniraj repozitorijum
git clone https://git.vm-net.in.rs/Dasko/GoNtech.git
cd GoNtech
# Pripremi konfiguraciju
cp ntech.env.example ntech.env
# uredi ntech.env po potrebi
# Pokreni
go run ./cmd/ntech
```
Aplikacija se pokreće na `http://localhost:8080`.
## Build za produkciju
## Prvo pokretanje — Setup Wizard
Kad se program prvi put pokrene (nema `ntech.env`), automatski se otvara **Setup Wizard** na portu `8080`. Podešava se:
1. Port servera
2. Admin korisničko ime i lozinka
3. Naziv firme
Po završetku, `ntech.env` se kreira automatski i aplikacija se restartuje.
## Produkcijski build
Interaktivna skripta:
```bash
./build.sh
# → unesi verziju (npr. 0.1.5)
# → izaberi OS (linux / windows)
# → UPX kompresija (da/ne)
```
Interaktivna skripta — biraš verziju, OS (Linux/Windows) i da li želiš UPX kompresiju.
Ručni build:
```bash
# Linux, AMD64
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o ntech ./cmd/ntech
# Sa verzijom
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux \
go build -ldflags "-X main.Verzija=0.1.5" -o ntech ./cmd/ntech
```
## Prvo pokretanje
Build je statički (`CGO_ENABLED=0`) — binarni fajl radi svuda bez zavisnosti.
Pri prvom pokretanju pokreće se **Setup Wizard** gde podešavaš:
1. Port servera
2. Admin korisničko ime i lozinku
3. Naziv firme
Posle toga, `ntech.env` se automatski kreira i aplikacija je spremna za korišćenje.
## Demo mod
Postavljanjem `NTECH_DEMO=true` u `ntech.env`:
- Setup wizard se preskače
- Bekapi su onemogućeni
- Promena lozinke je blokirana
- TOTP aktivacija nije dozvoljena
## Konfiguracija
Sva podešavanja su u `ntech.env` fajlu:
## Konfiguracija (`ntech.env`)
| Promenljiva | Opis | Podrazumevano |
|---|---|---|
| `NTECH_PORT` | Port servera | `8080` |
| `NTECH_DB` | Putanja SQLite baze | `ntech.db` |
| `NTECH_DEMO` | Demo mod | `false` |
| `NTECH_DEV` | Dev mod (disk-first šabloni) | `false` |
| `NTECH_SQLITE` | Putanja SQLite baze | `ntech.db` |
| `NTECH_ENV` | `development` / `production` / `demo` | `development` |
| `NTECH_DOMAIN` | Domen sajta (za kolačiće i CSP) | `localhost` |
### Režimi rada
| Režim | Šabloni | Statika | Migracije |
|---|---|---|---|
| `development` | Sa diska (hot-reload) | Sa diska | Sa diska |
| `production` | Embed | Embed (immutable keš) | Embed |
| `demo` | Embed | Embed (immutable keš) | Embed |
### Demo mod (`NTECH_ENV=demo`)
- Setup wizard se preskače — `ntech.env` se automatski kreira prazan
- Backup je onemogućen
- Promena lozinke je blokirana
- TOTP aktivacija nije dozvoljena
- Kolačići su Secure (kao u produkciji)
## Pokretanje
```bash
# U produkciji
NTECH_ENV=production ./ntech
# Sa custom portom
NTECH_PORT=9090 ./ntech
# Demo mod
NTECH_ENV=demo ./ntech
```
## Struktura foldera posle build-a
```
.
├── ntech # binarni fajl (sve ugrađeno)
├── ntech.env # konfiguracija
├── ntech.db # SQLite baza (kreira se automatski)
└── logs/ # auth.log (opciono)
```
Ništa više nije potrebno — jedan fajl, jedna konfiguracija, jedna baza.
+144
@@ -0,0 +1,144 @@
# Razvoj
## Okruženje
```bash
# 1. Kloniraj
git clone git@git.vm-net.in.rs:Dasko/GoNtech.git
cd GoNtech
# 2. Podesi ENV
export $(grep -v '^#' ntech.env | xargs)
# 3. Pokreni u dev modu (šabloni sa diska — hot-reload nije ugrađen)
go run ./cmd/ntech
```
## Struktura koda po konvenciji
- **Handleri** — grupisani po domenu u `internal/handler/` (jedan fajl = jedan domen)
- **Modeli**`internal/model/` — čiste strukture, nula poslovne logike
- **Middleware** — stacked na chi ruter u `main.go`
- **Šabloni** — komponentna struktura u `web/templates/komponente/`
- **Migracije** — numerisane prefiksom (`001_`, `002_`, ...), **append-only**, nikad ne renumber-ovati
## Konvencije koda
- **Indentacija:** tabovi (Go standard)
- **Formatiranje:** `gofmt -s -w .` pre svakog commit-a
- **Imenovanje:**
- Izvezeni: PascalCase (`MagacinHandler`, `ListaArtikala`)
- Neizvezeni: camelCase (`renderStranicu`, `parsirajFormu`)
- Fajlovi: `snake_case.go` po domenu (`magacin.go`, `servis.go`)
- **Importi:** stdlib → third-party → internal (blank-line razdvajanje)
- **Error handling:** eksplicitna provera, wrap kroz `fmt.Errorf("ntech: ...: %w", err)`
## Jezik
| Šta | Jezik |
|---|---|
| Korisnički interfejs | srpski (ekavica, latinica) |
| Poruke o greškama | srpski |
| Komentari u kodu | srpski |
| Git commit poruke | srpski |
| Dokumentacija | srpski |
| Imena promenljivih/funkcija | engleski |
| Nazivi SQL kolona/tabela | engleski |
| Nazivi ENV promenljivih | engleski |
## Testiranje
```bash
# Svi testovi
go test ./...
# Bez keša
go test ./... -v -count=1
# Specifični test
go test ./internal/handler/ -run TestPrijava -v
```
Test fajlovi su pored koda koji testiraju:
- `internal/handler/prijava_test.go`
- `internal/handler/parseformu_test.go`
- `internal/model/model_test.go`
- `internal/db/sqlite/izvestaj_test.go`
## Build i provera
```bash
# Formatiranje
gofmt -s -w .
# Statička analiza
go vet ./...
# Build
CGO_ENABLED=0 go build ./cmd/ntech
```
## Migracije
Migracije su u `migrations/`, numerisane trocifrenim prefiksom:
```
001_kategorije.sql
002_artikli.sql
...
061_backfill_kategorija_kod.sql
```
**Pravila:**
- **Append-only** — nove migracije se dodaju, postojeće se nikad ne menjaju
- **Idempotentne** — koriste `CREATE TABLE IF NOT EXISTS`, `ALTER TABLE ... ADD COLUMN` (SQLite)
- **Redosled** — izvršavaju se po imenu fajla, rastuće
- **Transakcije** — SQLite implicitno, `migration` tabela prati koje su izvršene
## Grane i workflow
```bash
# Nova funkcionalnost
git switch -c feature/kratak-opis
# Posle izmene
gofmt -s -w .
go vet ./...
git commit -m "Kratak opis promene"
git push -u origin feature/kratak-opis
```
## Commit poruke
Format: srpski, kratak opis (max 50 karaktera), opciono detaljnije u telu.
Primeri:
```
Magacin: modal za premeštanje + ujednačen slajder na svim brauzerima
Bezbednosni audit i refaktoring: HP popravke, RBAC, flash poruke, go:embed, CSP
```
## Dodavanje novog modula
1. **Model** — struktura u `internal/model/novi_modul.go`
2. **Repozitorijum** — interfejs u `internal/db/repository.go`, implementacija u `internal/db/sqlite/novi_modul.go`
3. **Migracija**`migrations/062_novi_modul.sql`
4. **Handler**`internal/handler/novi_modul.go`
5. **Rute** — dodati u `cmd/ntech/main.go`
6. **Dozvole** — dodati u `internal/middleware/dozvole.go`
7. **Šabloni**`web/templates/stranice/novi_modul.html`
8. **CSS** — dodati u `web/static/main.css` (ako treba novi stil)
## Zavisnosti (go.mod)
| Direktna | Verzija | Uloga |
|---|---|---|
| `go-chi/chi/v5` | 5.3.0 | HTTP ruter + middleware |
| `google/uuid` | 1.6.0 | UUID generator (tokeni sesije) |
| `joho/godotenv` | 1.5.1 | `.env` fajl loader |
| `pquerna/otp` | 1.5.0 | TOTP 2FA |
| `x/crypto` | 0.52.0 | bcrypt |
| `modernc.org/sqlite` | 1.51.0 | SQLite bez CGO |
Sve ostalo je **Go standardna biblioteka**: `net/http`, `database/sql`, `html/template`, `crypto/rand`, `embed`, `io/fs`, `log/slog`.
+8
@@ -0,0 +1,8 @@
# Wiki
- [Početna](Home)
- [Instalacija](Instalacija)
- [Funkcionalnosti](Funkcionalnosti)
- [Arhitektura](Arhitektura)
- [Bezbednost](Bezbednost)
- [Razvoj](Razvoj)