78b57273e2
- Add password hashing with bcrypt - Add AuthService with proper login - Add password strength validation - Add RBAC middleware (AdminOnly, ManagerOrAdmin) - Add tenant isolation middleware - Update CRM handler with tenant filtering - Add JWT fallback for development mode - Add user context helpers - Build successful
225 lines
5.5 KiB
Go
225 lines
5.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
// LandvexRealHandler hanterar riktig integration mot Landvex API
|
|
type LandvexRealHandler struct {
|
|
baseURL string
|
|
client *http.Client
|
|
}
|
|
|
|
// NewLandvexRealHandler skapar en ny handler
|
|
func NewLandvexRealHandler() *LandvexRealHandler {
|
|
return &LandvexRealHandler{
|
|
baseURL: getEnv("LANDVEX_API_URL", "http://172.17.0.1:8081"),
|
|
client: &http.Client{Timeout: 10 * time.Second},
|
|
}
|
|
}
|
|
|
|
// LandvexObject representerar ett Landvex-objekt
|
|
type LandvexObject struct {
|
|
LvxID string `json:"lvx_id"`
|
|
Slug string `json:"slug"`
|
|
Namn map[string]string `json:"namn"`
|
|
Beskrivning map[string]string `json:"beskrivning"`
|
|
Kategorier []string `json:"kategorier"`
|
|
Standarder []string `json:"standarder"`
|
|
Metadata map[string]interface{} `json:"metadata"`
|
|
}
|
|
|
|
// LandvexSearchResult representerar sökresultat
|
|
type LandvexSearchResult struct {
|
|
LvxID string `json:"lvx_id"`
|
|
Namn map[string]string `json:"namn"`
|
|
Relevans float64 `json:"relevans"`
|
|
Kategorier []string `json:"kategorier"`
|
|
}
|
|
|
|
// fetchFromLandvex hämtar data från Landvex API
|
|
func (h *LandvexRealHandler) fetchFromLandvex(endpoint string) (map[string]interface{}, error) {
|
|
resp, err := h.client.Get(h.baseURL + endpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
if err := json.Unmarshal(body, &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetHealth hämtar health från Landvex
|
|
func (h *LandvexRealHandler) GetHealth(w http.ResponseWriter, r *http.Request) {
|
|
health, err := h.fetchFromLandvex("/health")
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"landvex": health,
|
|
})
|
|
}
|
|
|
|
// GetObjects hämtar alla objekt
|
|
func (h *LandvexRealHandler) GetObjects(w http.ResponseWriter, r *http.Request) {
|
|
// Sök efter alla objekt (tom sökning)
|
|
results, err := h.fetchFromLandvex("/v0/search?q=")
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"results": results,
|
|
})
|
|
}
|
|
|
|
// GetObject hämtar ett specifikt objekt
|
|
func (h *LandvexRealHandler) GetObject(w http.ResponseWriter, r *http.Request) {
|
|
lvxID := chi.URLParam(r, "id")
|
|
|
|
obj, err := h.fetchFromLandvex("/v0/objects/" + lvxID)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"object": obj,
|
|
})
|
|
}
|
|
|
|
// Search söker i Landvex
|
|
func (h *LandvexRealHandler) Search(w http.ResponseWriter, r *http.Request) {
|
|
query := r.URL.Query().Get("q")
|
|
if query == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]interface{}{
|
|
"ok": false,
|
|
"error": "missing query parameter 'q'",
|
|
})
|
|
return
|
|
}
|
|
|
|
resp, err := h.client.Get(h.baseURL + "/v0/search?q=" + url.QueryEscape(query))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Landvex returnerar inte JSON med ok/error, utan direkt resultat
|
|
var result map[string]interface{}
|
|
if err := json.Unmarshal(body, &result); err != nil {
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"query": query,
|
|
"raw": string(body),
|
|
"parse_error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"query": query,
|
|
"results": result,
|
|
})
|
|
}
|
|
|
|
// Identify identifierar ett objekt från bild/text
|
|
func (h *LandvexRealHandler) Identify(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
ImageURL string `json:"image_url,omitempty"`
|
|
Description string `json:"description,omitempty"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Vidarebefordra till Landvex identify
|
|
landvexReq := map[string]interface{}{
|
|
"image_url": req.ImageURL,
|
|
"description": req.Description,
|
|
}
|
|
|
|
reqBody, _ := json.Marshal(landvexReq)
|
|
resp, err := h.client.Post(h.baseURL+"/v0/identify", "application/json", strings.NewReader(string(reqBody)))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
if err := json.Unmarshal(body, &result); err != nil {
|
|
writeJSON(w, http.StatusInternalServerError, map[string]interface{}{
|
|
"ok": false,
|
|
"error": err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]interface{}{
|
|
"ok": true,
|
|
"result": result,
|
|
})
|
|
}
|