Files
Dasko 1cfb44b9a4 Demo mod, favicon ispravka i putanja ntech.env uz bazu
- NTECH_ENV=demo aktivira demo mod: korisnik Demo/Demo1234 (admin)
  se kreira ili resetuje pri svakom pokretanju
- Login ekran u demo modu prikazuje pre-popunjena polja i "DEMO verzija"
- ntech.env se čuva u istom direktorijumu kao SQLite baza (umesto
  uvek u radnom direktorijumu) — rešava Docker volume problem
- favicon.svg: uklonjen width="100%" koji je sprečavao prikaz ikone u brauzeru
2026-06-19 01:11:40 +02:00

124 lines
3.5 KiB
Go

package config
import (
"context"
"encoding/json"
"fmt"
"io/fs"
"log/slog"
"net"
"net/http"
"os"
"strings"
"github.com/go-chi/chi/v5"
)
// nadjiLokalneAdrese vraća sve ne-loopback IPv4 adrese mrežnih kartica
func nadjiLokalneAdrese() []string {
var adrese []string
ifaces, err := net.Interfaces()
if err != nil {
return adrese
}
for _, iface := range ifaces {
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
if ip4 := ip.To4(); ip4 != nil {
adrese = append(adrese, ip4.String())
}
}
}
return adrese
}
// PokreniSetup pokreće HTTP server za prvo podešavanje i čeka da korisnik završi
func PokreniSetup(fsys fs.FS, envFajl string) {
port := NadjiSlobodanPort()
if port == 0 {
slog.Error("setup: nije pronađen nijedan slobodan port"); os.Exit(1)
}
gotov := make(chan struct{})
adresa := fmt.Sprintf(":%d", port)
r := chi.NewRouter()
// serviraj setup stranicu
r.Get("/setup", func(w http.ResponseWriter, req *http.Request) {
portovi := StatusPortova()
podaci, err := json.Marshal(portovi)
if err != nil {
http.Error(w, "Greška", http.StatusInternalServerError)
return
}
sadrzaj, err := fs.ReadFile(fsys, "web/templates/setup/index.html")
if err != nil {
http.Error(w, "Greška", http.StatusInternalServerError)
return
}
html := strings.Replace(string(sadrzaj), "PORT_PODACI", string(podaci), 1)
w.Header().Set("Content-Type", "text/html")
fmt.Fprint(w, html)
})
// proverava da li je određeni port slobodan
r.Get("/setup/proveriPort", func(w http.ResponseWriter, req *http.Request) {
portStr := req.URL.Query().Get("port")
var p int
fmt.Sscanf(portStr, "%d", &p)
slobodan := JelPortSlobodan(p)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]bool{"slobodan": slobodan})
})
// prima izabrani port, upisuje ntech.env i signalizira završetak
r.Post("/setup/potvrdi", func(w http.ResponseWriter, req *http.Request) {
var telo struct {
Port int `json:"port"`
}
json.NewDecoder(req.Body).Decode(&telo)
if err := SacuvajEnv(telo.Port, envFajl); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]bool{"ok": true})
close(gotov)
})
srv := &http.Server{Addr: adresa, Handler: r}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
slog.Error("setup server", "error", err); os.Exit(1)
}
}()
fmt.Printf("\n╔══════════════════════════════════════════════╗\n")
fmt.Printf("║ NTech — prvo pokretanje ║\n")
fmt.Printf("║ ║\n")
fmt.Printf("║ Otvorite u browseru: ║\n")
fmt.Printf("║ http://localhost:%d/setup ║\n", port)
for _, ip := range nadjiLokalneAdrese() {
fmt.Printf("║ http://%s:%d/setup ║\n", ip, port)
}
fmt.Printf("║ ║\n")
fmt.Printf("╚══════════════════════════════════════════════╝\n\n")
<-gotov
srv.Shutdown(context.Background())
}