// Package controller 定义 MVC 架构中的 Controller 层。 package controller import ( "encoding/json" "fmt" "net/http" "strings" "stock-analysis/internal/model" "stock-analysis/internal/service" ) // AuthController 提供用户认证相关的 HTTP 接口。 type AuthController struct { svc *service.AuthService } // NewAuthController 创建认证控制器。 func NewAuthController(svc *service.AuthService) *AuthController { return &AuthController{svc: svc} } // CurrentUser 返回当前请求对应的登录用户,未登录返回错误。 func (c *AuthController) CurrentUser(r *http.Request) (*model.User, error) { token := extractToken(r) if token == "" { return nil, fmt.Errorf("未登录") } return c.svc.ValidateToken(r.Context(), token) } // sendCodeRequest 发送验证码请求。 type sendCodeRequest struct { Email string `json:"email"` Purpose string `json:"purpose"` // register 或 login } // SendCode 处理 POST /api/auth/send-code,发送邮箱验证码。 func (c *AuthController) SendCode(w http.ResponseWriter, r *http.Request) { var req sendCodeRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, err) return } if req.Purpose == "" { req.Purpose = "register" } if err := c.svc.SendVerifyCode(r.Context(), req.Email, req.Purpose); err != nil { writeError(w, http.StatusBadRequest, err) return } writeJSON(w, http.StatusOK, map[string]string{"message": "验证码已发送"}) } // registerRequest 注册请求。 type registerRequest struct { Username string `json:"username"` Email string `json:"email"` Code string `json:"code"` Password string `json:"password"` } // Register 处理 POST /api/auth/register,邮箱+验证码注册。 func (c *AuthController) Register(w http.ResponseWriter, r *http.Request) { var req registerRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, err) return } user, err := c.svc.Register(r.Context(), req.Username, req.Email, req.Code, req.Password) if err != nil { writeError(w, http.StatusBadRequest, err) return } writeJSON(w, http.StatusOK, map[string]any{ "id": user.ID, "username": user.Username, "email": user.Email, }) } // loginRequest 登录请求。 type loginRequest struct { Username string `json:"username"` Email string `json:"email"` Code string `json:"code"` Password string `json:"password"` } // Login 处理 POST /api/auth/login。 // 支持两种登录方式: // - 用户名+密码:{ username, password } // - 邮箱+验证码:{ email, code } func (c *AuthController) Login(w http.ResponseWriter, r *http.Request) { var req loginRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, err) return } var user *model.User var token string var err error if req.Username != "" { // 用户名+密码登录 user, token, err = c.svc.LoginByUsername(r.Context(), req.Username, req.Password) } else if req.Code != "" { // 邮箱+验证码登录 user, token, err = c.svc.Login(r.Context(), req.Email, req.Code) } else { writeError(w, http.StatusBadRequest, fmt.Errorf("请输入用户名密码或邮箱验证码")) return } if err != nil { writeError(w, http.StatusUnauthorized, err) return } writeJSON(w, http.StatusOK, map[string]any{ "id": user.ID, "username": user.Username, "email": user.Email, "token": token, }) } // Me 处理 GET /api/auth/me,返回当前登录用户信息。 func (c *AuthController) Me(w http.ResponseWriter, r *http.Request) { token := extractToken(r) if token == "" { writeError(w, http.StatusUnauthorized, fmt.Errorf("未登录")) return } u, err := c.svc.ValidateToken(r.Context(), token) if err != nil { writeError(w, http.StatusUnauthorized, err) return } writeJSON(w, http.StatusOK, map[string]any{ "id": u.ID, "username": u.Username, "email": u.Email, }) } // Logout 处理 POST /api/auth/logout,注销当前会话。 func (c *AuthController) Logout(w http.ResponseWriter, r *http.Request) { token := extractToken(r) if token != "" { c.svc.Logout(token) } writeJSON(w, http.StatusOK, map[string]string{"message": "已退出"}) } // extractToken 从 Cookie 或 Authorization 头中提取 token。 func extractToken(r *http.Request) string { if c, err := r.Cookie("auth_token"); err == nil && c.Value != "" { return c.Value } if h := r.Header.Get("Authorization"); h != "" { if strings.HasPrefix(h, "Bearer ") { return strings.TrimPrefix(h, "Bearer ") } } return "" }