60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
|
|
package handler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
|
||
|
|
"github.com/company/ai-ops/internal/service"
|
||
|
|
"github.com/company/ai-ops/pkg/errors"
|
||
|
|
"github.com/company/ai-ops/pkg/response"
|
||
|
|
)
|
||
|
|
|
||
|
|
// AuthHandler 是认证 HTTP 处理器
|
||
|
|
type AuthHandler struct {
|
||
|
|
authSvc *service.AuthService
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewAuthHandler(authSvc *service.AuthService) *AuthHandler {
|
||
|
|
return &AuthHandler{authSvc: authSvc}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *AuthHandler) RegisterRoutes(mux *http.ServeMux) {
|
||
|
|
mux.HandleFunc("POST /api/v1/ai-ops/login", h.Login)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
||
|
|
var req struct {
|
||
|
|
Username string `json:"username"`
|
||
|
|
Password string `json:"password"`
|
||
|
|
}
|
||
|
|
if err := decodeJSON(r, &req); err != nil {
|
||
|
|
response.Error(w, errors.ErrBadRequest.WithDetail(map[string]any{"error": err.Error()}))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: 实现真实的用户验证(当前为简化实现)
|
||
|
|
if req.Username == "" || req.Password == "" {
|
||
|
|
response.Error(w, errors.ErrBadRequest.WithDetail(map[string]any{"error": "username and password required"}))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 默认角色为 viewer
|
||
|
|
role := "viewer"
|
||
|
|
if req.Username == "admin" {
|
||
|
|
role = "admin"
|
||
|
|
} else if req.Username == "ops" {
|
||
|
|
role = "operator"
|
||
|
|
}
|
||
|
|
|
||
|
|
token, err := h.authSvc.IssueToken(req.Username, role)
|
||
|
|
if err != nil {
|
||
|
|
response.Error(w, errors.Wrap(err, errors.ErrInternal))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
response.Success(w, map[string]any{
|
||
|
|
"token": token,
|
||
|
|
"expires_in": 28800,
|
||
|
|
"role": role,
|
||
|
|
})
|
||
|
|
}
|