diff --git a/Arhitektura.md b/Arhitektura.md new file mode 100644 index 0000000..43a9bbb --- /dev/null +++ b/Arhitektura.md @@ -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 `` — 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 diff --git a/Bezbednost.md b/Bezbednost.md new file mode 100644 index 0000000..51aef90 --- /dev/null +++ b/Bezbednost.md @@ -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 `
` +- Token se upoređuje sa kolačićem pri svakoj POST/PUT/DELETE mutaciji +- Implementacija: `internal/middleware/csrf.go` + +```html + + + + ... +
+``` + +## 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 diff --git a/Funkcionalnosti.md b/Funkcionalnosti.md index 4dd1a97..5f3fc15 100644 --- a/Funkcionalnosti.md +++ b/Funkcionalnosti.md @@ -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 artikal–dobavljač 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 diff --git a/Home.md b/Home.md index f8a84cc..23ad2ed 100644 --- a/Home.md +++ b/Home.md @@ -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) diff --git a/Instalacija.md b/Instalacija.md index 494abc6..4eb5967 100644 --- a/Instalacija.md +++ b/Instalacija.md @@ -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. diff --git a/Razvoj.md b/Razvoj.md new file mode 100644 index 0000000..0f5b842 --- /dev/null +++ b/Razvoj.md @@ -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`. diff --git a/_Sidebar.md b/_Sidebar.md new file mode 100644 index 0000000..113312a --- /dev/null +++ b/_Sidebar.md @@ -0,0 +1,8 @@ +# Wiki + +- [Početna](Home) +- [Instalacija](Instalacija) +- [Funkcionalnosti](Funkcionalnosti) +- [Arhitektura](Arhitektura) +- [Bezbednost](Bezbednost) +- [Razvoj](Razvoj)