64 lines
2.0 KiB
Go
64 lines
2.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/dchest/captcha"
|
|
|
|
"go-dy/internal/auth"
|
|
"go-dy/internal/config"
|
|
dbpkg "go-dy/internal/db"
|
|
"go-dy/internal/repo"
|
|
"go-dy/internal/resp"
|
|
)
|
|
|
|
func LoginHandler(cfg config.Config) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// Expect form data: name, password (+ optional captcha when enabled)
|
|
name := c.PostForm("name")
|
|
password := c.PostForm("password")
|
|
|
|
if name == "" || password == "" {
|
|
resp.Error(c, http.StatusBadRequest, "missing name or password")
|
|
return
|
|
}
|
|
|
|
// captcha gate (if enabled)
|
|
if cfg.LoginRequireCaptcha {
|
|
cid := c.PostForm("captcha_id")
|
|
ccode := c.PostForm("captcha_code")
|
|
if cid == "" || ccode == "" {
|
|
resp.Error(c, http.StatusBadRequest, "missing captcha_id or captcha_code")
|
|
return
|
|
}
|
|
if !captcha.VerifyString(cid, ccode) {
|
|
resp.Error(c, http.StatusUnauthorized, "invalid captcha")
|
|
return
|
|
}
|
|
}
|
|
|
|
// Database-backed login only: always check users table
|
|
db, err := dbpkg.Get(cfg)
|
|
if err != nil {
|
|
resp.Error(c, http.StatusServiceUnavailable, "database unavailable")
|
|
return
|
|
}
|
|
u, err := repo.GetUserByName(db, name)
|
|
if err != nil {
|
|
resp.Error(c, http.StatusInternalServerError, "query user failed")
|
|
return
|
|
}
|
|
if u == nil || !repo.CheckPassword(u, password) {
|
|
resp.Error(c, http.StatusUnauthorized, "invalid credentials")
|
|
return
|
|
}
|
|
token, err := auth.GenerateToken(name, cfg.JWTSecret, 24*time.Hour)
|
|
if err != nil {
|
|
resp.Error(c, http.StatusInternalServerError, "could not generate token")
|
|
return
|
|
}
|
|
resp.OK(c, gin.H{"token": token})
|
|
}
|
|
} |