refactor: reorganize models to pkg/model and add authentication module
- Move ORM models from internal/model to pkg/model organized by module (auth/k8s/registry) - Add authentication module with login, user management handlers - Update all import paths to use new model locations - Add frontend auth pages (Login, UserManagement) and authStore - Remove deprecated internal/model/model.go
This commit is contained in:
97
internal/module/auth/handler.login.go
Normal file
97
internal/module/auth/handler.login.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
authModel "gitea.loveuer.com/loveuer/cluster/pkg/model/auth"
|
||||
"gitea.loveuer.com/loveuer/cluster/pkg/resp"
|
||||
"gitea.loveuer.com/loveuer/cluster/pkg/tool"
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
JWTSecret = "cluster-secret-key-change-in-production"
|
||||
TokenDuration = 7 * 24 * time.Hour
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
Token string `json:"token"`
|
||||
Username string `json:"username"`
|
||||
Nickname string `json:"nickname"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
|
||||
type Claims struct {
|
||||
UserID uint `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func Login(ctx context.Context, db *gorm.DB) fiber.Handler {
|
||||
return func(c fiber.Ctx) error {
|
||||
var req LoginRequest
|
||||
|
||||
body := c.Body()
|
||||
if len(body) == 0 {
|
||||
return resp.R400(c, "EMPTY_BODY", nil, "request body is empty")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(body, &req); err != nil {
|
||||
return resp.R400(c, "INVALID_REQUEST", nil, "invalid request body")
|
||||
}
|
||||
|
||||
if req.Username == "" || req.Password == "" {
|
||||
return resp.R400(c, "MISSING_CREDENTIALS", nil, "username and password are required")
|
||||
}
|
||||
|
||||
var user authModel.User
|
||||
if err := db.Where("username = ?", req.Username).First(&user).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return resp.R401(c, "INVALID_CREDENTIALS", nil, "invalid username or password")
|
||||
}
|
||||
return resp.R500(c, "", nil, err.Error())
|
||||
}
|
||||
|
||||
if user.Status != "active" {
|
||||
return resp.R403(c, "USER_INACTIVE", nil, "user account is inactive")
|
||||
}
|
||||
|
||||
if !tool.ComparePassword(req.Password, user.Password) {
|
||||
return resp.R401(c, "INVALID_CREDENTIALS", nil, "invalid username or password")
|
||||
}
|
||||
|
||||
claims := &Claims{
|
||||
UserID: user.ID,
|
||||
Username: user.Username,
|
||||
Role: user.Role,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(TokenDuration)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(JWTSecret))
|
||||
if err != nil {
|
||||
return resp.R500(c, "", nil, "failed to generate token")
|
||||
}
|
||||
|
||||
return resp.R200(c, LoginResponse{
|
||||
Token: tokenString,
|
||||
Username: user.Username,
|
||||
Nickname: user.Nickname,
|
||||
Role: user.Role,
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user