Files
2026-04-07 21:21:18 +08:00

74 lines
1.8 KiB
Go

package handler
import (
"fmt"
"net/http"
"regexp"
"gitea.starryskymeow.cn/B309/datamarket/internal/service"
"github.com/go-chi/jwtauth/v5"
"github.com/go-chi/render"
)
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
const usernameExpr = `^\S{3,32}$`
const passwordExpr = `^\S{8,64}$`
func (req *LoginRequest) Bind(_ *http.Request) error {
// username
if ok, _ := regexp.MatchString(usernameExpr, req.Username); !ok {
return fmt.Errorf("invalid username, must match %q", usernameExpr)
}
// password
if ok, _ := regexp.MatchString(passwordExpr, req.Password); !ok {
return fmt.Errorf("invalid password, must match %q", passwordExpr)
}
return nil
}
// LoginHandler POST /api/auth/login
func LoginHandler(auth service.AuthService) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
req := &LoginRequest{}
if err := render.Bind(r, req); err != nil {
w.WriteHeader(http.StatusBadRequest)
renderServiceError(w, r, err)
return
}
user, err := auth.VerifyUser(r.Context(), service.VerifyUserInput{
Username: req.Username,
Password: req.Password,
})
if err != nil {
renderServiceError(w, r, err)
return
}
http.SetCookie(w, &http.Cookie{
Name: "jwt",
Value: user.Token,
Path: "/",
HttpOnly: true,
Secure: true,
MaxAge: 60 * 60 * 24, // 1d
SameSite: http.SameSiteLaxMode,
})
renderSuccess(w, r, http.StatusAccepted, "登录成功", user)
}
}
func MeHandler(auth service.AuthService) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, claims, err := jwtauth.FromContext(r.Context())
if err != nil {
renderServiceError(w, r, err)
}
renderSuccess(w, r, http.StatusOK, "logged in", claims)
}
}