Files
Bernt e5623d2f84 feat: integrate Grafana dashboards into BOC DashboardPage
- Add Infrastructure Health section with CPU/Memory/Disk panels
- Add Service Status section with PM2/Docker panels
- Create GrafanaPanel component for iframe embedding
- Build passes successfully
2026-07-29 19:03:06 +00:00

152 lines
4.1 KiB
Go

package handlers
import (
"encoding/json"
"net/http"
"boc/sms"
)
// SMSHandler hanterar SMS- och 2FA-endpoints
type SMSHandler struct {
TwoFactor *sms.TwoFactorAuth
Notifier *sms.NotificationService
}
// NewSMSHandler skapar ny SMS-handler
func NewSMSHandler(twoFactor *sms.TwoFactorAuth, notifier *sms.NotificationService) *SMSHandler {
return &SMSHandler{
TwoFactor: twoFactor,
Notifier: notifier,
}
}
// SendVerificationCode skickar 2FA-kod
func (h *SMSHandler) SendVerificationCode(w http.ResponseWriter, r *http.Request) {
if h.TwoFactor == nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]interface{}{
"error": "SMS not configured",
"message": "Set ELK46_USERNAME and ELK46_PASSWORD environment variables",
})
return
}
var req struct {
Phone string `json:"phone"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
return
}
code, err := h.TwoFactor.SendVerificationCode(req.Phone)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"message": "Verification code sent",
"phone": req.Phone,
// I produktion: skicka INTE koden tillbaka!
"code": code, // Endast för test
})
}
// VerifyCode verifierar 2FA-kod
func (h *SMSHandler) VerifyCode(w http.ResponseWriter, r *http.Request) {
if h.TwoFactor == nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]interface{}{
"error": "SMS not configured",
"message": "Set ELK46_USERNAME and ELK46_PASSWORD environment variables",
})
return
}
var req struct {
Phone string `json:"phone"`
Code string `json:"code"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
return
}
valid, err := h.TwoFactor.VerifyCode(req.Phone, req.Code)
if err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]interface{}{
"error": err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"valid": valid,
})
}
// SendNotification skickar generisk notifikation
func (h *SMSHandler) SendNotification(w http.ResponseWriter, r *http.Request) {
var req struct {
Phone string `json:"phone"`
Type string `json:"type"` // task_reminder, onboarding, document, performance, training, security
Message string `json:"message"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, `{"error":"invalid request"}`, http.StatusBadRequest)
return
}
var err error
switch req.Type {
case "task_reminder":
err = h.Notifier.SendTaskReminder(req.Phone, req.Message, "idag")
case "onboarding":
err = h.Notifier.SendOnboardingWelcome(req.Phone, req.Message)
case "document":
err = h.Notifier.SendDocumentSignatureRequest(req.Phone, req.Message)
case "security":
err = h.Notifier.SendSecurityAlert(req.Phone, req.Message)
default:
http.Error(w, `{"error":"unknown notification type"}`, http.StatusBadRequest)
return
}
if err != nil {
http.Error(w, `{"error":"`+err.Error()+`"}`, http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"message": "Notification sent",
})
}
// SMSStatus kontrollerar SMS-konfiguration
func (h *SMSHandler) SMSStatus(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"configured": h.TwoFactor != nil,
"provider": "46elks",
"features": []string{
"two_way_sms",
"bulk_sms",
"2fa_verification",
"notifications",
},
})
}