package api import ( "net/http" "github.com/gin-gonic/gin" "hightube/internal/db" "hightube/internal/model" "hightube/internal/utils" ) type RegisterRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } type LoginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } type ChangePasswordRequest struct { OldPassword string `json:"old_password" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } func Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // Check if user exists var existingUser model.User if err := db.DB.Where("username = ?", req.Username).First(&existingUser).Error; err == nil { c.JSON(http.StatusConflict, gin.H{"error": "Username already exists"}) return } // Hash password hashedPassword, err := utils.HashPassword(req.Password) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"}) return } // Create user user := model.User{ Username: req.Username, Password: hashedPassword, Role: "user", Enabled: true, } if err := db.DB.Create(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"}) return } // Create a default live room for the new user room := model.Room{ UserID: user.ID, Title: user.Username + "'s Live Room", StreamKey: utils.GenerateStreamKey(), IsActive: false, } if err := db.DB.Create(&room).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create room for user"}) return } c.JSON(http.StatusCreated, gin.H{"message": "User registered successfully", "user_id": user.ID}) } func Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var user model.User if err := db.DB.Where("username = ?", req.Username).First(&user).Error; err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"}) return } if !utils.CheckPasswordHash(req.Password, user.Password) { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"}) return } if !user.Enabled { c.JSON(http.StatusForbidden, gin.H{"error": "Account is disabled"}) return } token, err := utils.GenerateToken(user.ID, user.Username, user.Role) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) return } c.JSON(http.StatusOK, gin.H{ "token": token, "username": user.Username, "role": user.Role, "enabled": user.Enabled, }) } func ChangePassword(c *gin.Context) { userID, _ := c.Get("user_id") var req ChangePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var user model.User if err := db.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) return } // Verify old password if !utils.CheckPasswordHash(req.OldPassword, user.Password) { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid old password"}) return } // Hash new password hashedPassword, err := utils.HashPassword(req.NewPassword) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"}) return } // Update user if err := db.DB.Model(&user).Update("password", hashedPassword).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update password"}) return } c.JSON(http.StatusOK, gin.H{"message": "Password updated successfully"}) }