package core import ( "encoding/json" "errors" "net/http" "time" "aufs/crypto" "aufs/db" ) // LoginRequest 登录请求结构 type LoginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } // LoginResponse 登录响应结构 type LoginResponse struct { Token string `json:"token"` User User `json:"user"` ExpiresAt time.Time `json:"expires_at"` } // User 用户数据结构 type User struct { ID int `json:"id" db:"id"` Username string `json:"username" db:"username"` Email string `json:"email" db:"email"` Role string `json:"role" db:"role"` CreatedAt time.Time `json:"created_at" db:"created_at"` UpdatedAt time.Time `json:"updated_at" db:"updated_at"` LastLogin time.Time `json:"last_login" db:"last_login"` Status string `json:"status" db:"status"` // active, locked, deleted } // 处理登录传入的数据 func LoginHandler(w http.ResponseWriter, r *http.Request) { // 解析请求体中的JSON数据 var loginReq LoginRequest err := json.NewDecoder(r.Body).Decode(&loginReq) if err != nil { http.Error(w, "Invalid request payload", http.StatusBadRequest) return } // 验证用户名和密码 user, err := authenticateUser(loginReq.Username, loginReq.Password) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } // 生成访问令牌(这里简化处理,实际项目中可能需要使用JWT等) token := "temp_token_" + time.Now().Format("20060102150405") expiresAt := time.Now().Add(24 * time.Hour) // 令牌有效期24小时 // 更新用户最后登录时间 err = db.UpdateUserLastLogin(user.ID) if err != nil { // 记录错误但不影响登录流程 // 实际项目中应该有日志记录 } // 构建响应 response := LoginResponse{ Token: token, User: *user, ExpiresAt: expiresAt, } // 返回JSON响应 w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } // 用户状态常量 const ( UserStatusActive = "active" UserStatusLocked = "locked" UserStatusDeleted = "deleted" ) // RegisterRequest 注册请求结构 type RegisterRequest struct { Username string `json:"username" binding:"required"` Email string `json:"email" binding:"required"` Password string `json:"password" binding:"required"` } // RegisterResponse 注册响应结构 type RegisterResponse struct { User User `json:"user"` Message string `json:"message"` CreatedAt time.Time `json:"created_at"` } // RegisterHandler 处理用户注册 func RegisterHandler(w http.ResponseWriter, r *http.Request) { // 解析请求体中的JSON数据 var registerReq RegisterRequest err := json.NewDecoder(r.Body).Decode(®isterReq) if err != nil { http.Error(w, "Invalid request payload", http.StatusBadRequest) return } // 检查用户名是否已存在 usernameExists, err := db.CheckUsernameExists(registerReq.Username) if err != nil { http.Error(w, "Internal server error", http.StatusInternalServerError) return } if usernameExists { http.Error(w, "Username already exists", http.StatusConflict) return } // 检查邮箱是否已存在 emailExists, err := db.CheckEmailExists(registerReq.Email) if err != nil { http.Error(w, "Internal server error", http.StatusInternalServerError) return } if emailExists { http.Error(w, "Email already exists", http.StatusConflict) return } // 对密码进行哈希处理 hashedPassword, err := crypto.HashPassword(registerReq.Password) if err != nil { http.Error(w, "Failed to process password", http.StatusInternalServerError) return } // 创建用户对象 userDB := db.User{ Username: registerReq.Username, Email: registerReq.Email, PasswordHash: hashedPassword, Role: "user", // 默认角色 Status: UserStatusActive, CreatedAt: time.Now(), UpdatedAt: time.Now(), LastLogin: time.Time{}, // 初始为零值 } // 保存用户到数据库 createdUser, err := db.AddUser(userDB) if err != nil { http.Error(w, "Failed to create user", http.StatusInternalServerError) return } // 转换为core包的User对象 user := User{ ID: createdUser.ID, Username: createdUser.Username, Email: createdUser.Email, Role: createdUser.Role, CreatedAt: createdUser.CreatedAt, UpdatedAt: createdUser.UpdatedAt, LastLogin: createdUser.LastLogin, Status: createdUser.Status, } // 构建响应 response := RegisterResponse{ User: user, Message: "User registered successfully", CreatedAt: user.CreatedAt, } // 返回JSON响应 w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(response) } // ResetPasswordRequest 重置密码请求结构 type ResetPasswordRequest struct { Username string `json:"username" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } // ResetPasswordResponse 重置密码响应结构 type ResetPasswordResponse struct { Message string `json:"message"` UpdatedAt time.Time `json:"updated_at"` } // ResetPasswordHandler 处理密码重置 func ResetPasswordHandler(w http.ResponseWriter, r *http.Request) { // 解析请求体中的JSON数据 var resetReq ResetPasswordRequest err := json.NewDecoder(r.Body).Decode(&resetReq) if err != nil { http.Error(w, "Invalid request payload", http.StatusBadRequest) return } // 检查用户是否存在 userDB, err := db.GetUserByUsername(resetReq.Username) if err != nil { http.Error(w, "User not found", http.StatusNotFound) return } // 检查用户状态 if userDB.Status != UserStatusActive { http.Error(w, "User account is locked or disabled", http.StatusForbidden) return } // 对新密码进行哈希处理 hashedPassword, err := crypto.HashPassword(resetReq.NewPassword) if err != nil { http.Error(w, "Failed to process new password", http.StatusInternalServerError) return } // 更新用户密码 updatedAt := time.Now() err = db.UpdateUserPassword(userDB.ID, hashedPassword, updatedAt) if err != nil { http.Error(w, "Failed to update password", http.StatusInternalServerError) return } // 构建响应 response := ResetPasswordResponse{ Message: "Password reset successful", UpdatedAt: updatedAt, } // 返回JSON响应 w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) } // authenticateUser 验证用户身份 func authenticateUser(username, password string) (*User, error) { // 根据用户名查询用户信息 userDB, err := db.GetUserByUsername(username) if err != nil { return nil, errors.New("用户名或密码错误") } // 检查用户状态 if userDB.Status != UserStatusActive { return nil, errors.New("用户账号已被锁定或禁用") } // 验证密码 isValid, err := crypto.VerifyPassword(userDB.PasswordHash, password) if err != nil || !isValid { return nil, errors.New("用户名或密码错误") } // 转换为core包的User对象 return &User{ ID: userDB.ID, Username: userDB.Username, Email: userDB.Email, Role: userDB.Role, CreatedAt: userDB.CreatedAt, UpdatedAt: userDB.UpdatedAt, LastLogin: userDB.LastLogin, Status: userDB.Status, }, nil }