package handler import ( "net/http" "evanpage-backend/internal/service" "github.com/gin-gonic/gin" ) type AuthHandler struct { userService *service.UserService } func NewAuthHandler(userService *service.UserService) *AuthHandler { return &AuthHandler{userService: userService} } func (h *AuthHandler) Register(c *gin.Context) { var req struct { Username string `json:"username" binding:"required"` Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=6"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userService.Register(req.Username, req.Email, req.Password, "user") if err != nil { c.JSON(http.StatusConflict, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "role": user.Role, }) } func (h *AuthHandler) LocalLogin(c *gin.Context) { var req struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userService.ValidateLocalLogin(req.Username, req.Password) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "role": user.Role, }) } func (h *AuthHandler) LookupBinding(c *gin.Context) { var req struct { KeycloakID string `json:"keycloakId" binding:"required"` Email string `json:"email"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userService.LookupKeycloakBinding(req.KeycloakID) if err != nil { c.JSON(http.StatusOK, gin.H{"bound": false}) return } c.JSON(http.StatusOK, gin.H{ "bound": true, "user": gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "role": user.Role, }, }) } func (h *AuthHandler) BindKeycloak(c *gin.Context) { var req struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` KeycloakID string `json:"keycloakId" binding:"required"` KeycloakEmail string `json:"keycloakEmail"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userService.BindKeycloak(req.Username, req.Password, req.KeycloakID, req.KeycloakEmail) if err != nil { c.JSON(http.StatusConflict, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "bound": true, "user": gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "role": user.Role, }, }) } func (h *AuthHandler) InitAdmin(c *gin.Context) { count, err := h.userService.CountUsers() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "db error"}) return } if count > 0 { c.JSON(http.StatusForbidden, gin.H{"error": "already initialized"}) return } var req struct { Username string `json:"username" binding:"required"` Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=6"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := h.userService.Register(req.Username, req.Email, req.Password, "admin") if err != nil { c.JSON(http.StatusConflict, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "role": user.Role, }) }