b77a8857e6
Uveden podrazumevani slog logger u main.go (podesiLog): JSON u produkciji, tekst u razvoju, nivo Info. Svih ~70 poziva log.Printf/Println/Fatalf zamenjeno slog.Error/Warn/Info: greška se prosleđuje kao atribut "error", informativne vrednosti kao imenovani atributi (port, broj, putanja...), Fatalf -> Error + os.Exit(1). Upozorenja (inicijalizacija/čišćenje dozvola, migracija kolone) idu kao slog.Warn. Auth log (internal/auth/log.go) namerno NIJE diran — ostaje zaseban *log.Logger u fail2ban formatu. (slog.SetDefault usput preusmerava i standardni log paket.)
124 lines
3.5 KiB
Go
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) {
|
|
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); 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())
|
|
}
|