package handler import ( "fmt" "loveuer/utodo/internal/model" "loveuer/utodo/internal/opt" "loveuer/utodo/pkg/database/db" "loveuer/utodo/pkg/resp" "loveuer/utodo/pkg/tool" "strings" "time" "github.com/gofiber/fiber/v3" ) func Login() fiber.Handler { return func(c fiber.Ctx) error { type Req struct { Username string `json:"username"` Phone string `json:"phone"` Email string `json:"email"` Password string `json:"password" validate:"required,min=8"` } var ( err error req Req op = new(model.User) token string ) if err = c.Bind().JSON(&req); err != nil { return resp.R400(c, "", nil, err.Error()) } tx := db.Default.Session(tool.TimeoutCtx(c.Context(), 5), db.Config{Debug: opt.Cfg.Debug}). Model(&model.User{}) conds := make([]string, 0) if req.Username != "" { conds = append(conds, fmt.Sprintf("username = %q", req.Username)) } if req.Phone != "" { conds = append(conds, fmt.Sprintf("phone = %q", req.Phone)) } if req.Email != "" { conds = append(conds, fmt.Sprintf("email = %q", req.Email)) } if len(conds) == 0 { return resp.R400(c, "", nil, "username, phone or email is required") } tx = tx.Where("deleted_at = 0 AND (" + strings.Join(conds, " OR ") + ")") if err = tx.First(op).Error; err != nil { return resp.R400(c, "用户信息错误, 登录失败", nil, err.Error()) } if !tool.ComparePassword(req.Password, op.Password) { return resp.R400(c, "用户信息错误, 登录失败", nil, "密码错误") } op.LastLoginAt = time.Now().UnixMilli() if err = db.Default.Session(tool.TimeoutCtx(c.Context(), 5)). Model(&model.User{}). Where("id = ?", op.Id). Updates(map[string]any{ "last_login_at": op.LastLoginAt, }).Error; err != nil { return resp.R500(c, "登录失败", nil, err.Error()) } if token, err = model.UserJWT.Generate(op); err != nil { return resp.R500(c, "登录失败", nil, err.Error()) } return resp.R200(c, map[string]any{ "token": token, "user": op, }) } } func Verify(key string) fiber.Handler { if key == "" { key = "Authorization" } return func(c fiber.Ctx) error { token := c.Get(key) if token == "" { return resp.R401(c, "", nil, "token is required") } token = strings.TrimPrefix(token, "Bearer ") user, err := model.UserJWT.Parse(token) if err != nil { return resp.R401(c, "", nil, err.Error()) } c.Locals("user", user) return resp.R200(c, fiber.Map{ "user": user, "token": token, }) } }