Initial commit: smartrun MVP
Garmin run classification and progression tracker. Go backend (MCP client to mcp-garmin, SQLite store, deterministic rule engine, REST API) and React/TS frontend (Dashboard, Review Queue, Workout Kinds). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
72
backend/internal/api/auth.go
Normal file
72
backend/internal/api/auth.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"smartrun/backend/internal/garmin"
|
||||
)
|
||||
|
||||
type authResponse struct {
|
||||
Status string `json:"status"` // "authenticated" | "mfa_required" | "failed"
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func authStatusString(s garmin.AuthStatus) string {
|
||||
switch s {
|
||||
case garmin.AuthSuccess:
|
||||
return "authenticated"
|
||||
case garmin.AuthMFARequired:
|
||||
return "mfa_required"
|
||||
case garmin.AuthFailed:
|
||||
return "failed"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) recordAuthResult(res garmin.AuthResult) {
|
||||
s.mu.Lock()
|
||||
s.authStatus = res.Status
|
||||
s.authMessage = res.Message
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *Server) handleAuthLogin(w http.ResponseWriter, r *http.Request) {
|
||||
res, err := s.Garmin.Authenticate(r.Context())
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadGateway, err.Error())
|
||||
return
|
||||
}
|
||||
s.recordAuthResult(res)
|
||||
writeJSON(w, http.StatusOK, authResponse{Status: authStatusString(res.Status), Message: res.Message})
|
||||
}
|
||||
|
||||
func (s *Server) handleAuthMFA(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
if body.Code == "" {
|
||||
writeError(w, http.StatusBadRequest, "code is required")
|
||||
return
|
||||
}
|
||||
|
||||
res, err := s.Garmin.CompleteMFA(r.Context(), body.Code)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadGateway, err.Error())
|
||||
return
|
||||
}
|
||||
s.recordAuthResult(res)
|
||||
writeJSON(w, http.StatusOK, authResponse{Status: authStatusString(res.Status), Message: res.Message})
|
||||
}
|
||||
|
||||
func (s *Server) handleAuthStatus(w http.ResponseWriter, r *http.Request) {
|
||||
s.mu.Lock()
|
||||
status, msg := s.authStatus, s.authMessage
|
||||
s.mu.Unlock()
|
||||
writeJSON(w, http.StatusOK, authResponse{Status: authStatusString(status), Message: msg})
|
||||
}
|
||||
Reference in New Issue
Block a user