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", }, }) }