You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
7.2 KiB
272 lines
7.2 KiB
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
|
|
}
|
|
|