From 6cafff378b94e6681b357690016a7c6394192aea Mon Sep 17 00:00:00 2001 From: Kittipat Jusingha <6531304621@student.chula.ac.th> Date: Wed, 23 Apr 2025 09:06:33 +0700 Subject: [PATCH 1/2] final --- controllers/room_controller.go | 195 ++++++++++++++++----------------- main.go | 26 +++-- 2 files changed, 113 insertions(+), 108 deletions(-) diff --git a/controllers/room_controller.go b/controllers/room_controller.go index 01259fb..3d3f49a 100644 --- a/controllers/room_controller.go +++ b/controllers/room_controller.go @@ -200,10 +200,9 @@ func CreateRoom(c *gin.Context) { // Create the room room := models.Room{ - Name: input.Name, - Type: input.Type, - CreatedBy: userID, + Name: input.Name, Type: input.Type, + CreatedBy: userID, } if err := database.DB.Create(&room).Error; err != nil { @@ -297,15 +296,16 @@ func GetRoom(c *gin.Context) { // @Security BearerAuth // @Router /api/rooms/groups [get] func GetGroupRooms(c *gin.Context) { - var groups []models.Room - if err := database.DB.Preload("Users"). - Where("type = ?", "group"). - Find(&groups).Error; err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch group rooms"}) - return - } - c.JSON(http.StatusOK, gin.H{"rooms": groups}) + var groups []models.Room + if err := database.DB.Preload("Users"). + Where("type = ?", "group"). + Find(&groups).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch group rooms"}) + return + } + c.JSON(http.StatusOK, gin.H{"rooms": groups}) } + // UpdateRoom godoc // @Summary Update a room's details // @Description Updates a room's name and/or members @@ -568,56 +568,56 @@ func SetActivateRoom(c *gin.Context) { // @Failure 404 {object} map[string]string "Room not found" // @Router /api/rooms/{id}/join [post] func JoinRoom(c *gin.Context) { - userID := c.MustGet("userID").(uint) - roomID64, err := strconv.ParseUint(c.Param("id"), 10, 32) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"}) - return - } - roomID := uint(roomID64) - - // Check room exists - var room models.Room - if err := database.DB.First(&room, roomID).Error; err != nil { - c.JSON(http.StatusNotFound, gin.H{"error": "Room not found"}) - return - } - - // Check user is not already in room - var existing models.RoomUser - if err := database.DB. - Where("room_id = ? AND user_id = ?", roomID, userID). - First(&existing).Error; err == nil { - c.Status(http.StatusNoContent) - return - } - - // Create membership - ru := models.RoomUser{ - RoomID: roomID, - UserID: userID, - LastReadAt: time.Now(), - } - if err := database.DB.Create(&ru).Error; err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to join room"}) - return - } + userID := c.MustGet("userID").(uint) + roomID64, err := strconv.ParseUint(c.Param("id"), 10, 32) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"}) + return + } + roomID := uint(roomID64) + + // Check room exists + var room models.Room + if err := database.DB.First(&room, roomID).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Room not found"}) + return + } + + // Check user is not already in room + var existing models.RoomUser + if err := database.DB. + Where("room_id = ? AND user_id = ?", roomID, userID). + First(&existing).Error; err == nil { + c.Status(http.StatusNoContent) + return + } + + // Create membership + ru := models.RoomUser{ + RoomID: roomID, + UserID: userID, + LastReadAt: time.Now(), + } + if err := database.DB.Create(&ru).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to join room"}) + return + } var u models.User - if err := database.DB.First(&u, userID).Error; err == nil { - websocket.BroadcastToRoom( - roomID, - "system", - map[string]interface{}{ - "room_id": roomID, - "user_id": userID, - "username": u.Username, - "action": "join", - "timestamp": time.Now().UTC(), - }, - ) - } - - c.Status(http.StatusNoContent) + if err := database.DB.First(&u, userID).Error; err == nil { + websocket.BroadcastToRoom( + roomID, + "system", + map[string]interface{}{ + "room_id": roomID, + "user_id": userID, + "username": u.Username, + "action": "join", + "timestamp": time.Now().UTC(), + }, + ) + } + + c.Status(http.StatusNoContent) } // LeaveRoom godoc @@ -635,43 +635,42 @@ func JoinRoom(c *gin.Context) { // @Failure 404 {object} map[string]string "Room not found or not a member" // @Router /api/rooms/{id}/leave [post] func LeaveRoom(c *gin.Context) { - userID := c.MustGet("userID").(uint) - roomID64, err := strconv.ParseUint(c.Param("id"), 10, 32) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"}) - return - } - roomID := uint(roomID64) - - // Ensure membership exists - var ru models.RoomUser - if err := database.DB. - Where("room_id = ? AND user_id = ?", roomID, userID). - First(&ru).Error; err != nil { - c.JSON(http.StatusNotFound, gin.H{"error": "You are not a member of this room"}) - return - } - - // Remove membership - if err := database.DB.Delete(&ru).Error; err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to leave room"}) - return - } + userID := c.MustGet("userID").(uint) + roomID64, err := strconv.ParseUint(c.Param("id"), 10, 32) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid room ID"}) + return + } + roomID := uint(roomID64) + + // Ensure membership exists + var ru models.RoomUser + if err := database.DB. + Where("room_id = ? AND user_id = ?", roomID, userID). + First(&ru).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "You are not a member of this room"}) + return + } + + // Remove membership + if err := database.DB.Delete(&ru).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to leave room"}) + return + } var u models.User - if err := database.DB.First(&u, userID).Error; err == nil { - websocket.BroadcastToRoom( - roomID, - "system", - map[string]interface{}{ - "room_id": roomID, - "user_id": userID, - "username": u.Username, - "action": "leave", - "timestamp": time.Now().UTC(), - }, - ) - } - - c.Status(http.StatusNoContent) -} + if err := database.DB.First(&u, userID).Error; err == nil { + websocket.BroadcastToRoom( + roomID, + "system", + map[string]interface{}{ + "room_id": roomID, + "user_id": userID, + "username": u.Username, + "action": "leave", + "timestamp": time.Now().UTC(), + }, + ) + } + c.Status(http.StatusNoContent) +} diff --git a/main.go b/main.go index abb67aa..ab94e57 100644 --- a/main.go +++ b/main.go @@ -49,23 +49,29 @@ func main() { // Set up router router := gin.Default() -// CORS middleware + // CORS middleware router.Use(func(c *gin.Context) { + envHost := os.Getenv("DB_HOST") + if envHost == "" { + envHost = "localhost" // fallback + } + allowedOrigin := "http://" + envHost + ":3000" + origin := c.Request.Header.Get("Origin") - if origin == "http://192.168.1.37:3000" { + if origin == allowedOrigin { c.Writer.Header().Set("Access-Control-Allow-Origin", origin) } c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE") - if c.Request.Method == "OPTIONS" { - c.AbortWithStatus(204) - return - } + if c.Request.Method == "OPTIONS" { + c.AbortWithStatus(204) + return + } - c.Next() -}) + c.Next() + }) // Swagger documentation router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) @@ -93,8 +99,8 @@ func main() { api.GET("/rooms/groups", controllers.GetGroupRooms) api.PUT("/rooms/:id", controllers.UpdateRoom) api.DELETE("/rooms/:id", controllers.DeleteRoom) - api.POST("/rooms/:id/join",controllers.JoinRoom) - api.POST("/rooms/:id/leave",controllers.LeaveRoom) + api.POST("/rooms/:id/join", controllers.JoinRoom) + api.POST("/rooms/:id/leave", controllers.LeaveRoom) api.GET("/rooms/:id/unread", controllers.GetUnreadCount) api.POST("/rooms/set-activate-room", controllers.SetActivateRoom) From 04ba44e9e57894775c28a19d94747954de44692c Mon Sep 17 00:00:00 2001 From: Kittipat Jusingha <6531304621@student.chula.ac.th> Date: Wed, 23 Apr 2025 21:11:47 +0700 Subject: [PATCH 2/2] final --- controllers/user_controller.go | 2 +- main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/user_controller.go b/controllers/user_controller.go index bb72c2f..7b961b0 100644 --- a/controllers/user_controller.go +++ b/controllers/user_controller.go @@ -33,7 +33,7 @@ func SearchUsers(c *gin.Context) { // Find users with usernames that start with the provided prefix var users []models.User if err := database.DB.Where("username LIKE ?", usernamePrefix+"%"). - Select("id, username, email, created_at, updated_at"). + Select("id, username, email, status, created_at, updated_at"). Limit(10). Find(&users).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to search users"}) diff --git a/main.go b/main.go index ab94e57..e29b18c 100644 --- a/main.go +++ b/main.go @@ -51,7 +51,7 @@ func main() { // CORS middleware router.Use(func(c *gin.Context) { - envHost := os.Getenv("DB_HOST") + envHost := os.Getenv("HOST") if envHost == "" { envHost = "localhost" // fallback }