package handlers import ( "net/http" "strconv" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" "smoop-api/internal/crypto" "smoop-api/internal/dto" "smoop-api/internal/models" ) type UsersHandler struct { db *gorm.DB } func NewUsersHandler(db *gorm.DB) *UsersHandler { return &UsersHandler{db: db} } func (h *UsersHandler) Profile(c *gin.Context) { claims := MustClaims(c) uid := ClaimUserID(claims) var u models.User if err := h.db.First(&u, uid).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "user not found"}) return } c.JSON(http.StatusOK, dto.MapUser(u)) } func (h *UsersHandler) SetRole(c *gin.Context) { idStr := c.Param("id") uid, _ := strconv.Atoi(idStr) var u models.User if err := h.db.First(&u, uid).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "user not found"}) return } var req dto.UserRoleDto if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } u.Role = req.Role if err := h.db.Save(&u).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "save failed"}) return } c.JSON(http.StatusCreated, dto.MapUser(u)) } func (h *UsersHandler) List(c *gin.Context) { var users []models.User if err := h.db.Order("id asc").Find(&users).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "query failed"}) return } out := make([]dto.UserDto, 0, len(users)) for _, u := range users { out = append(out, dto.MapUser(u)) } c.JSON(http.StatusOK, out) } // POST /users/create (admin) — create user with given role func (h *UsersHandler) Create(c *gin.Context) { var req dto.CreateUserDto if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } role := models.Role(strings.ToLower(req.Role)) if role != models.RoleAdmin && role != models.RoleUser { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid role"}) return } hash, err := crypto.Hash(req.Password, crypto.DefaultArgon2) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "hash error"}) return } u := models.User{Username: req.Username, Password: hash, Role: role} if err := h.db.Create(&u).Error; err != nil { // hint duplicate username e := strings.ToLower(err.Error()) if strings.Contains(e, "duplicate") || strings.Contains(e, "unique") || strings.Contains(e, "exists") { c.JSON(http.StatusBadRequest, gin.H{"error": "username already exists"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": "create failed"}) return } c.JSON(http.StatusCreated, dto.MapUser(u)) }