diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-09-22 23:58:26 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-22 23:58:26 +0300 |
| commit | 9cd44de9be62e1291f84763bc029f995301e1e03 (patch) | |
| tree | 5b4b8bc6d7a89173373fbb32c5a8c5013f8c9d82 /backend | |
| parent | feat: map search (#78) (diff) | |
| download | lphub-9cd44de9be62e1291f84763bc029f995301e1e03.tar.gz lphub-9cd44de9be62e1291f84763bc029f995301e1e03.tar.bz2 lphub-9cd44de9be62e1291f84763bc029f995301e1e03.zip | |
feat: discussions (#59)
Former-commit-id: ac6ac59367650b6a37650f5aec0587c6ce4d3dd1
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/api/routes.go | 89 | ||||
| -rw-r--r-- | backend/database/init.sql | 34 | ||||
| -rw-r--r-- | backend/handlers/discussions.go | 291 | ||||
| -rw-r--r-- | backend/handlers/home.go | 2 | ||||
| -rw-r--r-- | backend/handlers/login.go | 1 | ||||
| -rw-r--r-- | backend/handlers/logs.go | 2 | ||||
| -rw-r--r-- | backend/handlers/map.go | 35 | ||||
| -rw-r--r-- | backend/handlers/mod.go | 28 | ||||
| -rw-r--r-- | backend/handlers/record.go | 13 | ||||
| -rw-r--r-- | backend/handlers/user.go | 16 |
10 files changed, 425 insertions, 86 deletions
diff --git a/backend/api/routes.go b/backend/api/routes.go index fd3b8cc..339dc73 100644 --- a/backend/api/routes.go +++ b/backend/api/routes.go | |||
| @@ -7,35 +7,72 @@ import ( | |||
| 7 | ginSwagger "github.com/swaggo/gin-swagger" | 7 | ginSwagger "github.com/swaggo/gin-swagger" |
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | const ( | ||
| 11 | apiPath string = "/api" | ||
| 12 | v1Path string = "/v1" | ||
| 13 | swaggerPath string = "/swagger/*any" | ||
| 14 | indexPath string = "/" | ||
| 15 | tokenPath string = "/token" | ||
| 16 | loginPath string = "/login" | ||
| 17 | profilePath string = "/profile" | ||
| 18 | usersPath string = "/users/:userid" | ||
| 19 | demosPath string = "/demos" | ||
| 20 | mapSummaryPath string = "/maps/:mapid/summary" | ||
| 21 | mapImagePath string = "/maps/:mapid/image" | ||
| 22 | mapLeaderboardsPath string = "/maps/:mapid/leaderboards" | ||
| 23 | mapRecordPath string = "/maps/:mapid/record" | ||
| 24 | mapDiscussionsPath string = "/maps/:mapid/discussions" | ||
| 25 | mapDiscussionIDPath string = "/maps/:mapid/discussions/:discussionid" | ||
| 26 | rankingsPath string = "/rankings" | ||
| 27 | searchPath string = "/search" | ||
| 28 | gamesPath string = "/games" | ||
| 29 | chaptersPath string = "/games/:gameid" | ||
| 30 | chapterMapsPath string = "/chapters/:chapterid" | ||
| 31 | scoreLogsPath string = "/logs/score" | ||
| 32 | modLogsPath string = "/logs/mod" | ||
| 33 | ) | ||
| 34 | |||
| 10 | func InitRoutes(router *gin.Engine) { | 35 | func InitRoutes(router *gin.Engine) { |
| 11 | api := router.Group("/api") | 36 | api := router.Group(apiPath) |
| 12 | { | 37 | { |
| 13 | v1 := api.Group("/v1") | 38 | v1 := api.Group(v1Path) |
| 14 | v1.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) | 39 | // Swagger |
| 15 | v1.GET("/", func(c *gin.Context) { | 40 | v1.GET(swaggerPath, ginSwagger.WrapHandler(swaggerfiles.Handler)) |
| 41 | v1.GET(indexPath, func(c *gin.Context) { | ||
| 16 | c.File("docs/index.html") | 42 | c.File("docs/index.html") |
| 17 | }) | 43 | }) |
| 18 | v1.GET("/token", handlers.GetCookie) | 44 | // Tokens, login |
| 19 | v1.DELETE("/token", handlers.DeleteCookie) | 45 | v1.GET(tokenPath, handlers.GetCookie) |
| 20 | v1.GET("/login", handlers.Login) | 46 | v1.DELETE(tokenPath, handlers.DeleteCookie) |
| 21 | v1.GET("/profile", CheckAuth, handlers.Profile) | 47 | v1.GET(loginPath, handlers.Login) |
| 22 | v1.PUT("/profile", CheckAuth, handlers.UpdateCountryCode) | 48 | // Users, profiles |
| 23 | v1.POST("/profile", CheckAuth, handlers.UpdateUser) | 49 | v1.GET(profilePath, CheckAuth, handlers.Profile) |
| 24 | v1.GET("/users/:id", CheckAuth, handlers.FetchUser) | 50 | v1.PUT(profilePath, CheckAuth, handlers.UpdateCountryCode) |
| 25 | v1.GET("/demos", handlers.DownloadDemoWithID) | 51 | v1.POST(profilePath, CheckAuth, handlers.UpdateUser) |
| 26 | v1.GET("/maps/:id/summary", handlers.FetchMapSummary) | 52 | v1.GET(usersPath, CheckAuth, handlers.FetchUser) |
| 27 | v1.POST("/maps/:id/summary", CheckAuth, handlers.CreateMapSummary) | 53 | // Maps |
| 28 | v1.PUT("/maps/:id/summary", CheckAuth, handlers.EditMapSummary) | 54 | v1.GET(mapSummaryPath, handlers.FetchMapSummary) |
| 29 | v1.DELETE("/maps/:id/summary", CheckAuth, handlers.DeleteMapSummary) | 55 | v1.POST(mapSummaryPath, CheckAuth, handlers.CreateMapSummary) |
| 30 | v1.PUT("/maps/:id/image", CheckAuth, handlers.EditMapImage) | 56 | v1.PUT(mapSummaryPath, CheckAuth, handlers.EditMapSummary) |
| 31 | v1.GET("/maps/:id/leaderboards", handlers.FetchMapLeaderboards) | 57 | v1.DELETE(mapSummaryPath, CheckAuth, handlers.DeleteMapSummary) |
| 32 | v1.POST("/maps/:id/record", CheckAuth, handlers.CreateRecordWithDemo) | 58 | v1.PUT(mapImagePath, CheckAuth, handlers.EditMapImage) |
| 33 | v1.GET("/rankings", handlers.Rankings) | 59 | v1.GET(mapLeaderboardsPath, handlers.FetchMapLeaderboards) |
| 34 | v1.GET("/search", handlers.SearchWithQuery) | 60 | v1.POST(mapRecordPath, CheckAuth, handlers.CreateRecordWithDemo) |
| 35 | v1.GET("/games", handlers.FetchGames) | 61 | v1.GET(demosPath, handlers.DownloadDemoWithID) |
| 36 | v1.GET("/games/:id", handlers.FetchChapters) | 62 | v1.GET(mapDiscussionsPath, handlers.FetchMapDiscussions) |
| 37 | v1.GET("/chapters/:id", handlers.FetchChapterMaps) | 63 | v1.GET(mapDiscussionIDPath, handlers.FetchMapDiscussion) |
| 38 | v1.GET("/logs/score", handlers.ScoreLogs) | 64 | v1.POST(mapDiscussionsPath, CheckAuth, handlers.CreateMapDiscussion) |
| 39 | v1.GET("/logs/mod", CheckAuth, handlers.ModLogs) | 65 | v1.PUT(mapDiscussionIDPath, CheckAuth, handlers.EditMapDiscussion) |
| 66 | v1.DELETE(mapDiscussionIDPath, CheckAuth, handlers.DeleteMapDiscussion) | ||
| 67 | // Rankings, search | ||
| 68 | v1.GET(rankingsPath, handlers.Rankings) | ||
| 69 | v1.GET(searchPath, handlers.SearchWithQuery) | ||
| 70 | // Games, chapters, maps | ||
| 71 | v1.GET(gamesPath, handlers.FetchGames) | ||
| 72 | v1.GET(chaptersPath, handlers.FetchChapters) | ||
| 73 | v1.GET(chapterMapsPath, handlers.FetchChapterMaps) | ||
| 74 | // Logs | ||
| 75 | v1.GET(scoreLogsPath, handlers.ScoreLogs) | ||
| 76 | v1.GET(modLogsPath, CheckAuth, handlers.ModLogs) | ||
| 40 | } | 77 | } |
| 41 | } | 78 | } |
diff --git a/backend/database/init.sql b/backend/database/init.sql index abace5c..0f8196b 100644 --- a/backend/database/init.sql +++ b/backend/database/init.sql | |||
| @@ -82,6 +82,40 @@ CREATE TABLE map_ratings ( | |||
| 82 | FOREIGN KEY (user_id) REFERENCES users(steam_id) | 82 | FOREIGN KEY (user_id) REFERENCES users(steam_id) |
| 83 | ); | 83 | ); |
| 84 | 84 | ||
| 85 | CREATE TABLE map_discussions ( | ||
| 86 | id SERIAL, | ||
| 87 | map_id SMALLINT NOT NULL, | ||
| 88 | user_id TEXT NOT NULL, | ||
| 89 | title TEXT NOT NULL, | ||
| 90 | content TEXT NOT NULL, | ||
| 91 | created_at TIMESTAMP NOT NULL DEFAULT now(), | ||
| 92 | updated_at TIMESTAMP NOT NULL DEFAULT now(), | ||
| 93 | PRIMARY KEY (id), | ||
| 94 | FOREIGN KEY (map_id) REFERENCES maps(id), | ||
| 95 | FOREIGN KEY (user_id) REFERENCES users(steam_id) | ||
| 96 | ); | ||
| 97 | |||
| 98 | CREATE TABLE map_discussions_comments ( | ||
| 99 | id SERIAL, | ||
| 100 | discussion_id INT NOT NULL, | ||
| 101 | user_id TEXT NOT NULL, | ||
| 102 | comment TEXT NOT NULL, | ||
| 103 | created_at TIMESTAMP NOT NULL DEFAULT now(), | ||
| 104 | PRIMARY KEY (id), | ||
| 105 | FOREIGN KEY (discussion_id) REFERENCES map_discussions(id), | ||
| 106 | FOREIGN KEY (user_id) REFERENCES users(steam_id) | ||
| 107 | ); | ||
| 108 | |||
| 109 | CREATE TABLE map_discussions_upvotes ( | ||
| 110 | id SERIAL, | ||
| 111 | discussion_id INT NOT NULL, | ||
| 112 | user_id TEXT NOT NULL, | ||
| 113 | upvoted BOOLEAN NOT NULL, | ||
| 114 | PRIMARY KEY (id), | ||
| 115 | FOREIGN KEY (discussion_id) REFERENCES map_discussions(id), | ||
| 116 | FOREIGN KEY (user_id) REFERENCES users(steam_id) | ||
| 117 | ); | ||
| 118 | |||
| 85 | CREATE TABLE demos ( | 119 | CREATE TABLE demos ( |
| 86 | id UUID, | 120 | id UUID, |
| 87 | location_id TEXT NOT NULL, | 121 | location_id TEXT NOT NULL, |
diff --git a/backend/handlers/discussions.go b/backend/handlers/discussions.go new file mode 100644 index 0000000..605c7c3 --- /dev/null +++ b/backend/handlers/discussions.go | |||
| @@ -0,0 +1,291 @@ | |||
| 1 | package handlers | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "net/http" | ||
| 5 | "strconv" | ||
| 6 | "time" | ||
| 7 | |||
| 8 | "github.com/gin-gonic/gin" | ||
| 9 | "github.com/pektezol/leastportalshub/backend/database" | ||
| 10 | "github.com/pektezol/leastportalshub/backend/models" | ||
| 11 | ) | ||
| 12 | |||
| 13 | type MapDiscussionResponse struct { | ||
| 14 | Discussion MapDiscussion `json:"discussion"` | ||
| 15 | } | ||
| 16 | |||
| 17 | type MapDiscussionsResponse struct { | ||
| 18 | Discussions []MapDiscussionOnlyTitle `json:"discussions"` | ||
| 19 | } | ||
| 20 | |||
| 21 | type MapDiscussion struct { | ||
| 22 | ID int `json:"id"` | ||
| 23 | Creator models.UserShortWithAvatar `json:"creator"` | ||
| 24 | Title string `json:"title"` | ||
| 25 | Content string `json:"content"` | ||
| 26 | // Upvotes int `json:"upvotes"` | ||
| 27 | UpdatedAt time.Time `json:"updated_at"` | ||
| 28 | Comments []MapDiscussionComment `json:"comments"` | ||
| 29 | } | ||
| 30 | |||
| 31 | type MapDiscussionOnlyTitle struct { | ||
| 32 | ID int `json:"id"` | ||
| 33 | Creator models.UserShortWithAvatar `json:"creator"` | ||
| 34 | Title string `json:"title"` | ||
| 35 | // Upvotes int `json:"upvotes"` | ||
| 36 | UpdatedAt time.Time `json:"updated_at"` | ||
| 37 | Comments []MapDiscussionComment `json:"comments"` | ||
| 38 | } | ||
| 39 | |||
| 40 | type MapDiscussionComment struct { | ||
| 41 | User models.UserShortWithAvatar `json:"user"` | ||
| 42 | Comment string `json:"comment"` | ||
| 43 | Date time.Time `json:"date"` | ||
| 44 | } | ||
| 45 | |||
| 46 | type CreateMapDiscussionRequest struct { | ||
| 47 | Title string `json:"title" binding:"required"` | ||
| 48 | Content string `json:"content" binding:"required"` | ||
| 49 | } | ||
| 50 | |||
| 51 | type EditMapDiscussionRequest struct { | ||
| 52 | Title string `json:"title" binding:"required"` | ||
| 53 | Content string `json:"content" binding:"required"` | ||
| 54 | } | ||
| 55 | |||
| 56 | // GET Map Discussions | ||
| 57 | // | ||
| 58 | // @Description Get map discussions with specified map id. | ||
| 59 | // @Tags maps | ||
| 60 | // @Produce json | ||
| 61 | // @Param mapid path int true "Map ID" | ||
| 62 | // @Success 200 {object} models.Response{data=MapDiscussionsResponse} | ||
| 63 | // @Router /maps/{mapid}/discussions [get] | ||
| 64 | func FetchMapDiscussions(c *gin.Context) { | ||
| 65 | // TODO: get upvotes | ||
| 66 | response := MapDiscussionsResponse{} | ||
| 67 | mapID, err := strconv.Atoi(c.Param("mapid")) | ||
| 68 | if err != nil { | ||
| 69 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 70 | return | ||
| 71 | } | ||
| 72 | sql := `SELECT md.id, u.steam_id, u.user_name, u.avatar_link, md.title, md.updated_at FROM map_discussions md | ||
| 73 | INNER JOIN users u ON md.user_id = u.steam_id WHERE md.map_id = $1 | ||
| 74 | ORDER BY md.updated_at DESC` | ||
| 75 | rows, err := database.DB.Query(sql, mapID) | ||
| 76 | if err != nil { | ||
| 77 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 78 | return | ||
| 79 | } | ||
| 80 | // Get discussion data | ||
| 81 | for rows.Next() { | ||
| 82 | discussion := MapDiscussionOnlyTitle{} | ||
| 83 | err := rows.Scan(&discussion.ID, &discussion.Creator.SteamID, &discussion.Creator.UserName, &discussion.Creator.AvatarLink, &discussion.Title, &discussion.UpdatedAt) | ||
| 84 | if err != nil { | ||
| 85 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 86 | return | ||
| 87 | } | ||
| 88 | response.Discussions = append(response.Discussions, discussion) | ||
| 89 | } | ||
| 90 | c.JSON(http.StatusOK, models.Response{ | ||
| 91 | Success: true, | ||
| 92 | Message: "Successfully retrieved map discussions.", | ||
| 93 | Data: response, | ||
| 94 | }) | ||
| 95 | } | ||
| 96 | |||
| 97 | // GET Map Discussion | ||
| 98 | // | ||
| 99 | // @Description Get map discussion with specified map and discussion id. | ||
| 100 | // @Tags maps | ||
| 101 | // @Produce json | ||
| 102 | // @Param mapid path int true "Map ID" | ||
| 103 | // @Param discussionid path int true "Discussion ID" | ||
| 104 | // @Success 200 {object} models.Response{data=MapDiscussionResponse} | ||
| 105 | // @Router /maps/{mapid}/discussions/{discussionid} [get] | ||
| 106 | func FetchMapDiscussion(c *gin.Context) { | ||
| 107 | // TODO: get upvotes | ||
| 108 | response := MapDiscussionResponse{} | ||
| 109 | mapID, err := strconv.Atoi(c.Param("mapid")) | ||
| 110 | if err != nil { | ||
| 111 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 112 | return | ||
| 113 | } | ||
| 114 | discussionID, err := strconv.Atoi(c.Param("discussionid")) | ||
| 115 | if err != nil { | ||
| 116 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 117 | return | ||
| 118 | } | ||
| 119 | sql := `SELECT md.id, u.steam_id, u.user_name, u.avatar_link, md.title, md.content, md.updated_at FROM map_discussions md | ||
| 120 | INNER JOIN users u ON md.user_id = u.steam_id WHERE md.map_id = $1 AND md.id = $2` | ||
| 121 | err = database.DB.QueryRow(sql, mapID, discussionID).Scan(&response.Discussion.ID, &response.Discussion.Creator.SteamID, &response.Discussion.Creator.UserName, &response.Discussion.Creator.AvatarLink, &response.Discussion.Title, &response.Discussion.Content, &response.Discussion.UpdatedAt) | ||
| 122 | if err != nil { | ||
| 123 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 124 | return | ||
| 125 | } | ||
| 126 | // Get commments | ||
| 127 | sql = `SELECT u.steam_id, u.user_name, u.avatar_link, mdc.comment, mdc.created_at FROM map_discussions_comments mdc | ||
| 128 | INNER JOIN users u ON mdc.user_id = u.steam_id WHERE mdc.discussion_id = $1` | ||
| 129 | comments, err := database.DB.Query(sql, response.Discussion.ID) | ||
| 130 | if err != nil { | ||
| 131 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 132 | return | ||
| 133 | } | ||
| 134 | for comments.Next() { | ||
| 135 | comment := MapDiscussionComment{} | ||
| 136 | err = comments.Scan(&comment.User.SteamID, &comment.User.UserName, &comment.User.AvatarLink, &comment.Comment, &comment.Date) | ||
| 137 | if err != nil { | ||
| 138 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 139 | return | ||
| 140 | } | ||
| 141 | response.Discussion.Comments = append(response.Discussion.Comments, comment) | ||
| 142 | } | ||
| 143 | c.JSON(http.StatusOK, models.Response{ | ||
| 144 | Success: true, | ||
| 145 | Message: "Successfully retrieved map discussion.", | ||
| 146 | Data: response, | ||
| 147 | }) | ||
| 148 | } | ||
| 149 | |||
| 150 | // POST Map Discussion | ||
| 151 | // | ||
| 152 | // @Description Create map discussion with specified map id. | ||
| 153 | // @Tags maps | ||
| 154 | // @Produce json | ||
| 155 | // @Param Authorization header string true "JWT Token" | ||
| 156 | // @Param mapid path int true "Map ID" | ||
| 157 | // @Param discussionid path int true "Discussion ID" | ||
| 158 | // @Param request body CreateMapDiscussionRequest true "Body" | ||
| 159 | // @Success 200 {object} models.Response{data=CreateMapDiscussionRequest} | ||
| 160 | // @Router /maps/{mapid}/discussions [post] | ||
| 161 | func CreateMapDiscussion(c *gin.Context) { | ||
| 162 | mapID, err := strconv.Atoi(c.Param("mapid")) | ||
| 163 | if err != nil { | ||
| 164 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 165 | return | ||
| 166 | } | ||
| 167 | user, exists := c.Get("user") | ||
| 168 | if !exists { | ||
| 169 | c.JSON(http.StatusOK, models.ErrorResponse("User not logged in.")) | ||
| 170 | return | ||
| 171 | } | ||
| 172 | var request CreateMapDiscussionRequest | ||
| 173 | if err := c.BindJSON(&request); err != nil { | ||
| 174 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 175 | return | ||
| 176 | } | ||
| 177 | sql := `INSERT INTO map_discussions (map_id,user_id,title,"content") | ||
| 178 | VALUES($1,$2,$3,$4);` | ||
| 179 | _, err = database.DB.Exec(sql, mapID, user.(models.User).SteamID, request.Title, request.Content) | ||
| 180 | if err != nil { | ||
| 181 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 182 | return | ||
| 183 | } | ||
| 184 | c.JSON(http.StatusOK, models.Response{ | ||
| 185 | Success: true, | ||
| 186 | Message: "Successfully created map discussion.", | ||
| 187 | Data: request, | ||
| 188 | }) | ||
| 189 | } | ||
| 190 | |||
| 191 | // PUT Map Discussion | ||
| 192 | // | ||
| 193 | // @Description Edit map discussion with specified map id. | ||
| 194 | // @Tags maps | ||
| 195 | // @Produce json | ||
| 196 | // @Param Authorization header string true "JWT Token" | ||
| 197 | // @Param mapid path int true "Map ID" | ||
| 198 | // @Param discussionid path int true "Discussion ID" | ||
| 199 | // @Param request body EditMapDiscussionRequest true "Body" | ||
| 200 | // @Success 200 {object} models.Response{data=EditMapDiscussionRequest} | ||
| 201 | // @Router /maps/{mapid}/discussions/{discussionid} [put] | ||
| 202 | func EditMapDiscussion(c *gin.Context) { | ||
| 203 | mapID, err := strconv.Atoi(c.Param("mapid")) | ||
| 204 | if err != nil { | ||
| 205 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 206 | return | ||
| 207 | } | ||
| 208 | discussionID, err := strconv.Atoi(c.Param("discussionid")) | ||
| 209 | if err != nil { | ||
| 210 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 211 | return | ||
| 212 | } | ||
| 213 | user, exists := c.Get("user") | ||
| 214 | if !exists { | ||
| 215 | c.JSON(http.StatusOK, models.ErrorResponse("User not logged in.")) | ||
| 216 | return | ||
| 217 | } | ||
| 218 | var request EditMapDiscussionRequest | ||
| 219 | if err := c.BindJSON(&request); err != nil { | ||
| 220 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 221 | return | ||
| 222 | } | ||
| 223 | sql := `UPDATE map_discussions SET title = $4, content = $5, updated_at = $6 WHERE id = $1 AND map_id = $2 AND user_id = $3` | ||
| 224 | result, err := database.DB.Exec(sql, discussionID, mapID, user.(models.User).SteamID, request.Title, request.Content, time.Now().UTC()) | ||
| 225 | if err != nil { | ||
| 226 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 227 | return | ||
| 228 | } | ||
| 229 | affectedRows, err := result.RowsAffected() | ||
| 230 | if err != nil { | ||
| 231 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 232 | return | ||
| 233 | } | ||
| 234 | if affectedRows == 0 { | ||
| 235 | c.JSON(http.StatusOK, models.ErrorResponse("You can only edit your own post.")) | ||
| 236 | return | ||
| 237 | } | ||
| 238 | c.JSON(http.StatusOK, models.Response{ | ||
| 239 | Success: true, | ||
| 240 | Message: "Successfully edited map discussion.", | ||
| 241 | Data: request, | ||
| 242 | }) | ||
| 243 | } | ||
| 244 | |||
| 245 | // DELETE Map Summary | ||
| 246 | // | ||
| 247 | // @Description Delete map summary with specified map id. | ||
| 248 | // @Tags maps | ||
| 249 | // @Produce json | ||
| 250 | // @Param Authorization header string true "JWT Token" | ||
| 251 | // @Param mapid path int true "Map ID" | ||
| 252 | // @Param discussionid path int true "Discussion ID" | ||
| 253 | // @Success 200 {object} models.Response | ||
| 254 | // @Router /maps/{mapid}/discussions/{discussionid} [delete] | ||
| 255 | func DeleteMapDiscussion(c *gin.Context) { | ||
| 256 | mapID, err := strconv.Atoi(c.Param("mapid")) | ||
| 257 | if err != nil { | ||
| 258 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 259 | return | ||
| 260 | } | ||
| 261 | discussionID, err := strconv.Atoi(c.Param("discussionid")) | ||
| 262 | if err != nil { | ||
| 263 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 264 | return | ||
| 265 | } | ||
| 266 | user, exists := c.Get("user") | ||
| 267 | if !exists { | ||
| 268 | c.JSON(http.StatusOK, models.ErrorResponse("User not logged in.")) | ||
| 269 | return | ||
| 270 | } | ||
| 271 | sql := `DELETE FROM map_discussions WHERE id = $1 AND map_id = $2 AND user_id = $3` | ||
| 272 | result, err := database.DB.Exec(sql, discussionID, mapID, user.(models.User).SteamID) | ||
| 273 | if err != nil { | ||
| 274 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 275 | return | ||
| 276 | } | ||
| 277 | affectedRows, err := result.RowsAffected() | ||
| 278 | if err != nil { | ||
| 279 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | ||
| 280 | return | ||
| 281 | } | ||
| 282 | if affectedRows == 0 { | ||
| 283 | c.JSON(http.StatusOK, models.ErrorResponse("You can only delete your own post.")) | ||
| 284 | return | ||
| 285 | } | ||
| 286 | c.JSON(http.StatusOK, models.Response{ | ||
| 287 | Success: true, | ||
| 288 | Message: "Successfully deleted map discussion.", | ||
| 289 | Data: nil, | ||
| 290 | }) | ||
| 291 | } | ||
diff --git a/backend/handlers/home.go b/backend/handlers/home.go index 42e27be..c9742f2 100644 --- a/backend/handlers/home.go +++ b/backend/handlers/home.go | |||
| @@ -35,7 +35,6 @@ type MapShortWithGame struct { | |||
| 35 | // @Tags rankings | 35 | // @Tags rankings |
| 36 | // @Produce json | 36 | // @Produce json |
| 37 | // @Success 200 {object} models.Response{data=RankingsResponse} | 37 | // @Success 200 {object} models.Response{data=RankingsResponse} |
| 38 | // @Failure 400 {object} models.Response | ||
| 39 | // @Router /rankings [get] | 38 | // @Router /rankings [get] |
| 40 | func Rankings(c *gin.Context) { | 39 | func Rankings(c *gin.Context) { |
| 41 | response := RankingsResponse{ | 40 | response := RankingsResponse{ |
| @@ -142,7 +141,6 @@ func Rankings(c *gin.Context) { | |||
| 142 | // @Produce json | 141 | // @Produce json |
| 143 | // @Param q query string false "Search user or map name." | 142 | // @Param q query string false "Search user or map name." |
| 144 | // @Success 200 {object} models.Response{data=SearchResponse} | 143 | // @Success 200 {object} models.Response{data=SearchResponse} |
| 145 | // @Failure 400 {object} models.Response | ||
| 146 | // @Router /search [get] | 144 | // @Router /search [get] |
| 147 | func SearchWithQuery(c *gin.Context) { | 145 | func SearchWithQuery(c *gin.Context) { |
| 148 | query := c.Query("q") | 146 | query := c.Query("q") |
diff --git a/backend/handlers/login.go b/backend/handlers/login.go index a7e4379..dc6e4a5 100644 --- a/backend/handlers/login.go +++ b/backend/handlers/login.go | |||
| @@ -26,7 +26,6 @@ type LoginResponse struct { | |||
| 26 | // @Accept json | 26 | // @Accept json |
| 27 | // @Produce json | 27 | // @Produce json |
| 28 | // @Success 200 {object} models.Response{data=LoginResponse} | 28 | // @Success 200 {object} models.Response{data=LoginResponse} |
| 29 | // @Failure 400 {object} models.Response | ||
| 30 | // @Router /login [get] | 29 | // @Router /login [get] |
| 31 | func Login(c *gin.Context) { | 30 | func Login(c *gin.Context) { |
| 32 | openID := steam_go.NewOpenId(c.Request) | 31 | openID := steam_go.NewOpenId(c.Request) |
diff --git a/backend/handlers/logs.go b/backend/handlers/logs.go index b6bcef6..6f59238 100644 --- a/backend/handlers/logs.go +++ b/backend/handlers/logs.go | |||
| @@ -78,7 +78,6 @@ type ScoreLogsResponseDetails struct { | |||
| 78 | // @Produce json | 78 | // @Produce json |
| 79 | // @Param Authorization header string true "JWT Token" | 79 | // @Param Authorization header string true "JWT Token" |
| 80 | // @Success 200 {object} models.Response{data=LogsResponse} | 80 | // @Success 200 {object} models.Response{data=LogsResponse} |
| 81 | // @Failure 400 {object} models.Response | ||
| 82 | // @Router /logs/mod [get] | 81 | // @Router /logs/mod [get] |
| 83 | func ModLogs(c *gin.Context) { | 82 | func ModLogs(c *gin.Context) { |
| 84 | mod, exists := c.Get("mod") | 83 | mod, exists := c.Get("mod") |
| @@ -125,7 +124,6 @@ func ModLogs(c *gin.Context) { | |||
| 125 | // @Tags logs | 124 | // @Tags logs |
| 126 | // @Produce json | 125 | // @Produce json |
| 127 | // @Success 200 {object} models.Response{data=ScoreLogsResponse} | 126 | // @Success 200 {object} models.Response{data=ScoreLogsResponse} |
| 128 | // @Failure 400 {object} models.Response | ||
| 129 | // @Router /logs/score [get] | 127 | // @Router /logs/score [get] |
| 130 | func ScoreLogs(c *gin.Context) { | 128 | func ScoreLogs(c *gin.Context) { |
| 131 | response := ScoreLogsResponse{Logs: []ScoreLogsResponseDetails{}} | 129 | response := ScoreLogsResponse{Logs: []ScoreLogsResponseDetails{}} |
diff --git a/backend/handlers/map.go b/backend/handlers/map.go index f3198ff..3bf14cd 100644 --- a/backend/handlers/map.go +++ b/backend/handlers/map.go | |||
| @@ -58,12 +58,11 @@ type RecordMultiplayer struct { | |||
| 58 | // @Description Get map summary with specified id. | 58 | // @Description Get map summary with specified id. |
| 59 | // @Tags maps | 59 | // @Tags maps |
| 60 | // @Produce json | 60 | // @Produce json |
| 61 | // @Param id path int true "Map ID" | 61 | // @Param mapid path int true "Map ID" |
| 62 | // @Success 200 {object} models.Response{data=MapSummaryResponse} | 62 | // @Success 200 {object} models.Response{data=MapSummaryResponse} |
| 63 | // @Failure 400 {object} models.Response | 63 | // @Router /maps/{mapid}/summary [get] |
| 64 | // @Router /maps/{id}/summary [get] | ||
| 65 | func FetchMapSummary(c *gin.Context) { | 64 | func FetchMapSummary(c *gin.Context) { |
| 66 | id := c.Param("id") | 65 | id := c.Param("mapid") |
| 67 | response := MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}} | 66 | response := MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}} |
| 68 | intID, err := strconv.Atoi(id) | 67 | intID, err := strconv.Atoi(id) |
| 69 | if err != nil { | 68 | if err != nil { |
| @@ -138,14 +137,13 @@ func FetchMapSummary(c *gin.Context) { | |||
| 138 | // @Description Get map leaderboards with specified id. | 137 | // @Description Get map leaderboards with specified id. |
| 139 | // @Tags maps | 138 | // @Tags maps |
| 140 | // @Produce json | 139 | // @Produce json |
| 141 | // @Param id path int true "Map ID" | 140 | // @Param mapid path int true "Map ID" |
| 142 | // @Param page query int false "Page Number (default: 1)" | 141 | // @Param page query int false "Page Number (default: 1)" |
| 143 | // @Param pageSize query int false "Number of Records Per Page (default: 20)" | 142 | // @Param pageSize query int false "Number of Records Per Page (default: 20)" |
| 144 | // @Success 200 {object} models.Response{data=MapLeaderboardsResponse} | 143 | // @Success 200 {object} models.Response{data=MapLeaderboardsResponse} |
| 145 | // @Failure 400 {object} models.Response | 144 | // @Router /maps/{mapid}/leaderboards [get] |
| 146 | // @Router /maps/{id}/leaderboards [get] | ||
| 147 | func FetchMapLeaderboards(c *gin.Context) { | 145 | func FetchMapLeaderboards(c *gin.Context) { |
| 148 | id := c.Param("id") | 146 | id := c.Param("mapid") |
| 149 | // Get map data | 147 | // Get map data |
| 150 | response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil, Pagination: models.Pagination{}} | 148 | response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil, Pagination: models.Pagination{}} |
| 151 | page, err := strconv.Atoi(c.DefaultQuery("page", "1")) | 149 | page, err := strconv.Atoi(c.DefaultQuery("page", "1")) |
| @@ -349,12 +347,11 @@ func FetchGames(c *gin.Context) { | |||
| 349 | // @Description Get chapters from the specified game id. | 347 | // @Description Get chapters from the specified game id. |
| 350 | // @Tags games & chapters | 348 | // @Tags games & chapters |
| 351 | // @Produce json | 349 | // @Produce json |
| 352 | // @Param id path int true "Game ID" | 350 | // @Param gameid path int true "Game ID" |
| 353 | // @Success 200 {object} models.Response{data=ChaptersResponse} | 351 | // @Success 200 {object} models.Response{data=ChaptersResponse} |
| 354 | // @Failure 400 {object} models.Response | 352 | // @Router /games/{gameid} [get] |
| 355 | // @Router /games/{id} [get] | ||
| 356 | func FetchChapters(c *gin.Context) { | 353 | func FetchChapters(c *gin.Context) { |
| 357 | gameID := c.Param("id") | 354 | gameID := c.Param("gameid") |
| 358 | intID, err := strconv.Atoi(gameID) | 355 | intID, err := strconv.Atoi(gameID) |
| 359 | if err != nil { | 356 | if err != nil { |
| 360 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 357 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
| @@ -391,12 +388,12 @@ func FetchChapters(c *gin.Context) { | |||
| 391 | // @Description Get maps from the specified chapter id. | 388 | // @Description Get maps from the specified chapter id. |
| 392 | // @Tags games & chapters | 389 | // @Tags games & chapters |
| 393 | // @Produce json | 390 | // @Produce json |
| 394 | // @Param id path int true "Chapter ID" | 391 | // @Param chapterid path int true "Chapter ID" |
| 395 | // @Success 200 {object} models.Response{data=ChapterMapsResponse} | 392 | // @Success 200 {object} models.Response{data=ChapterMapsResponse} |
| 396 | // @Failure 400 {object} models.Response | 393 | // @Failure 400 {object} models.Response |
| 397 | // @Router /chapters/{id} [get] | 394 | // @Router /chapters/{chapterid} [get] |
| 398 | func FetchChapterMaps(c *gin.Context) { | 395 | func FetchChapterMaps(c *gin.Context) { |
| 399 | chapterID := c.Param("id") | 396 | chapterID := c.Param("chapterid") |
| 400 | intID, err := strconv.Atoi(chapterID) | 397 | intID, err := strconv.Atoi(chapterID) |
| 401 | if err != nil { | 398 | if err != nil { |
| 402 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 399 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
diff --git a/backend/handlers/mod.go b/backend/handlers/mod.go index 1d04a96..3559887 100644 --- a/backend/handlers/mod.go +++ b/backend/handlers/mod.go | |||
| @@ -42,11 +42,10 @@ type EditMapImageRequest struct { | |||
| 42 | // @Tags maps | 42 | // @Tags maps |
| 43 | // @Produce json | 43 | // @Produce json |
| 44 | // @Param Authorization header string true "JWT Token" | 44 | // @Param Authorization header string true "JWT Token" |
| 45 | // @Param id path int true "Map ID" | 45 | // @Param mapid path int true "Map ID" |
| 46 | // @Param request body CreateMapSummaryRequest true "Body" | 46 | // @Param request body CreateMapSummaryRequest true "Body" |
| 47 | // @Success 200 {object} models.Response{data=CreateMapSummaryRequest} | 47 | // @Success 200 {object} models.Response{data=CreateMapSummaryRequest} |
| 48 | // @Failure 400 {object} models.Response | 48 | // @Router /maps/{mapid}/summary [post] |
| 49 | // @Router /maps/{id}/summary [post] | ||
| 50 | func CreateMapSummary(c *gin.Context) { | 49 | func CreateMapSummary(c *gin.Context) { |
| 51 | // Check if user exists | 50 | // Check if user exists |
| 52 | user, exists := c.Get("user") | 51 | user, exists := c.Get("user") |
| @@ -60,7 +59,7 @@ func CreateMapSummary(c *gin.Context) { | |||
| 60 | return | 59 | return |
| 61 | } | 60 | } |
| 62 | // Bind parameter and body | 61 | // Bind parameter and body |
| 63 | id := c.Param("id") | 62 | id := c.Param("mapid") |
| 64 | mapID, err := strconv.Atoi(id) | 63 | mapID, err := strconv.Atoi(id) |
| 65 | if err != nil { | 64 | if err != nil { |
| 66 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 65 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
| @@ -123,11 +122,10 @@ func CreateMapSummary(c *gin.Context) { | |||
| 123 | // @Tags maps | 122 | // @Tags maps |
| 124 | // @Produce json | 123 | // @Produce json |
| 125 | // @Param Authorization header string true "JWT Token" | 124 | // @Param Authorization header string true "JWT Token" |
| 126 | // @Param id path int true "Map ID" | 125 | // @Param mapid path int true "Map ID" |
| 127 | // @Param request body EditMapSummaryRequest true "Body" | 126 | // @Param request body EditMapSummaryRequest true "Body" |
| 128 | // @Success 200 {object} models.Response{data=EditMapSummaryRequest} | 127 | // @Success 200 {object} models.Response{data=EditMapSummaryRequest} |
| 129 | // @Failure 400 {object} models.Response | 128 | // @Router /maps/{mapid}/summary [put] |
| 130 | // @Router /maps/{id}/summary [put] | ||
| 131 | func EditMapSummary(c *gin.Context) { | 129 | func EditMapSummary(c *gin.Context) { |
| 132 | // Check if user exists | 130 | // Check if user exists |
| 133 | user, exists := c.Get("user") | 131 | user, exists := c.Get("user") |
| @@ -141,7 +139,7 @@ func EditMapSummary(c *gin.Context) { | |||
| 141 | return | 139 | return |
| 142 | } | 140 | } |
| 143 | // Bind parameter and body | 141 | // Bind parameter and body |
| 144 | id := c.Param("id") | 142 | id := c.Param("mapid") |
| 145 | mapID, err := strconv.Atoi(id) | 143 | mapID, err := strconv.Atoi(id) |
| 146 | if err != nil { | 144 | if err != nil { |
| 147 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 145 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
| @@ -204,11 +202,10 @@ func EditMapSummary(c *gin.Context) { | |||
| 204 | // @Tags maps | 202 | // @Tags maps |
| 205 | // @Produce json | 203 | // @Produce json |
| 206 | // @Param Authorization header string true "JWT Token" | 204 | // @Param Authorization header string true "JWT Token" |
| 207 | // @Param id path int true "Map ID" | 205 | // @Param mapid path int true "Map ID" |
| 208 | // @Param request body DeleteMapSummaryRequest true "Body" | 206 | // @Param request body DeleteMapSummaryRequest true "Body" |
| 209 | // @Success 200 {object} models.Response{data=DeleteMapSummaryRequest} | 207 | // @Success 200 {object} models.Response{data=DeleteMapSummaryRequest} |
| 210 | // @Failure 400 {object} models.Response | 208 | // @Router /maps/{mapid}/summary [delete] |
| 211 | // @Router /maps/{id}/summary [delete] | ||
| 212 | func DeleteMapSummary(c *gin.Context) { | 209 | func DeleteMapSummary(c *gin.Context) { |
| 213 | // Check if user exists | 210 | // Check if user exists |
| 214 | user, exists := c.Get("user") | 211 | user, exists := c.Get("user") |
| @@ -222,7 +219,7 @@ func DeleteMapSummary(c *gin.Context) { | |||
| 222 | return | 219 | return |
| 223 | } | 220 | } |
| 224 | // Bind parameter and body | 221 | // Bind parameter and body |
| 225 | id := c.Param("id") | 222 | id := c.Param("mapid") |
| 226 | mapID, err := strconv.Atoi(id) | 223 | mapID, err := strconv.Atoi(id) |
| 227 | if err != nil { | 224 | if err != nil { |
| 228 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 225 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
| @@ -289,11 +286,10 @@ func DeleteMapSummary(c *gin.Context) { | |||
| 289 | // @Tags maps | 286 | // @Tags maps |
| 290 | // @Produce json | 287 | // @Produce json |
| 291 | // @Param Authorization header string true "JWT Token" | 288 | // @Param Authorization header string true "JWT Token" |
| 292 | // @Param id path int true "Map ID" | 289 | // @Param mapid path int true "Map ID" |
| 293 | // @Param request body EditMapImageRequest true "Body" | 290 | // @Param request body EditMapImageRequest true "Body" |
| 294 | // @Success 200 {object} models.Response{data=EditMapImageRequest} | 291 | // @Success 200 {object} models.Response{data=EditMapImageRequest} |
| 295 | // @Failure 400 {object} models.Response | 292 | // @Router /maps/{mapid}/image [put] |
| 296 | // @Router /maps/{id}/image [put] | ||
| 297 | func EditMapImage(c *gin.Context) { | 293 | func EditMapImage(c *gin.Context) { |
| 298 | // Check if user exists | 294 | // Check if user exists |
| 299 | user, exists := c.Get("user") | 295 | user, exists := c.Get("user") |
| @@ -307,7 +303,7 @@ func EditMapImage(c *gin.Context) { | |||
| 307 | return | 303 | return |
| 308 | } | 304 | } |
| 309 | // Bind parameter and body | 305 | // Bind parameter and body |
| 310 | id := c.Param("id") | 306 | id := c.Param("mapid") |
| 311 | mapID, err := strconv.Atoi(id) | 307 | mapID, err := strconv.Atoi(id) |
| 312 | if err != nil { | 308 | if err != nil { |
| 313 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) | 309 | c.JSON(http.StatusOK, models.ErrorResponse(err.Error())) |
diff --git a/backend/handlers/record.go b/backend/handlers/record.go index 75b5583..70234c3 100644 --- a/backend/handlers/record.go +++ b/backend/handlers/record.go | |||
| @@ -37,18 +37,16 @@ type RecordResponse struct { | |||
| 37 | // @Tags maps | 37 | // @Tags maps |
| 38 | // @Accept mpfd | 38 | // @Accept mpfd |
| 39 | // @Produce json | 39 | // @Produce json |
| 40 | // @Param id path int true "Map ID" | 40 | // @Param mapid path int true "Map ID" |
| 41 | // @Param Authorization header string true "JWT Token" | 41 | // @Param Authorization header string true "JWT Token" |
| 42 | // @Param host_demo formData file true "Host Demo" | 42 | // @Param host_demo formData file true "Host Demo" |
| 43 | // @Param partner_demo formData file false "Partner Demo" | 43 | // @Param partner_demo formData file false "Partner Demo" |
| 44 | // @Param is_partner_orange formData boolean false "Is Partner Orange" | 44 | // @Param is_partner_orange formData boolean false "Is Partner Orange" |
| 45 | // @Param partner_id formData string false "Partner ID" | 45 | // @Param partner_id formData string false "Partner ID" |
| 46 | // @Success 200 {object} models.Response{data=RecordResponse} | 46 | // @Success 200 {object} models.Response{data=RecordResponse} |
| 47 | // @Failure 400 {object} models.Response | 47 | // @Router /maps/{mapid}/record [post] |
| 48 | // @Failure 401 {object} models.Response | ||
| 49 | // @Router /maps/{id}/record [post] | ||
| 50 | func CreateRecordWithDemo(c *gin.Context) { | 48 | func CreateRecordWithDemo(c *gin.Context) { |
| 51 | mapId := c.Param("id") | 49 | mapId := c.Param("mapid") |
| 52 | // Check if user exists | 50 | // Check if user exists |
| 53 | user, exists := c.Get("user") | 51 | user, exists := c.Get("user") |
| 54 | if !exists { | 52 | if !exists { |
| @@ -216,9 +214,8 @@ func CreateRecordWithDemo(c *gin.Context) { | |||
| 216 | // @Tags demo | 214 | // @Tags demo |
| 217 | // @Accept json | 215 | // @Accept json |
| 218 | // @Produce octet-stream | 216 | // @Produce octet-stream |
| 219 | // @Param uuid query string true "Demo UUID" | 217 | // @Param uuid query string true "Demo UUID" |
| 220 | // @Success 200 {file} binary "Demo File" | 218 | // @Success 200 {file} binary "Demo File" |
| 221 | // @Failure 400 {object} models.Response | ||
| 222 | // @Router /demos [get] | 219 | // @Router /demos [get] |
| 223 | func DownloadDemoWithID(c *gin.Context) { | 220 | func DownloadDemoWithID(c *gin.Context) { |
| 224 | uuid := c.Query("uuid") | 221 | uuid := c.Query("uuid") |
diff --git a/backend/handlers/user.go b/backend/handlers/user.go index 2df2040..f04145e 100644 --- a/backend/handlers/user.go +++ b/backend/handlers/user.go | |||
| @@ -63,8 +63,6 @@ type ScoreResponse struct { | |||
| 63 | // @Produce json | 63 | // @Produce json |
| 64 | // @Param Authorization header string true "JWT Token" | 64 | // @Param Authorization header string true "JWT Token" |
| 65 | // @Success 200 {object} models.Response{data=ProfileResponse} | 65 | // @Success 200 {object} models.Response{data=ProfileResponse} |
| 66 | // @Failure 400 {object} models.Response | ||
| 67 | // @Failure 401 {object} models.Response | ||
| 68 | // @Router /profile [get] | 66 | // @Router /profile [get] |
| 69 | func Profile(c *gin.Context) { | 67 | func Profile(c *gin.Context) { |
| 70 | // Check if user exists | 68 | // Check if user exists |
| @@ -343,13 +341,11 @@ func Profile(c *gin.Context) { | |||
| 343 | // @Tags users | 341 | // @Tags users |
| 344 | // @Accept json | 342 | // @Accept json |
| 345 | // @Produce json | 343 | // @Produce json |
| 346 | // @Param id path int true "User ID" | 344 | // @Param userid path int true "User ID" |
| 347 | // @Success 200 {object} models.Response{data=ProfileResponse} | 345 | // @Success 200 {object} models.Response{data=ProfileResponse} |
| 348 | // @Failure 400 {object} models.Response | 346 | // @Router /users/{userid} [get] |
| 349 | // @Failure 404 {object} models.Response | ||
| 350 | // @Router /users/{id} [get] | ||
| 351 | func FetchUser(c *gin.Context) { | 347 | func FetchUser(c *gin.Context) { |
| 352 | id := c.Param("id") | 348 | id := c.Param("userid") |
| 353 | // Check if id is all numbers and 17 length | 349 | // Check if id is all numbers and 17 length |
| 354 | match, _ := regexp.MatchString("^[0-9]{17}$", id) | 350 | match, _ := regexp.MatchString("^[0-9]{17}$", id) |
| 355 | if !match { | 351 | if !match { |
| @@ -634,8 +630,6 @@ func FetchUser(c *gin.Context) { | |||
| 634 | // @Produce json | 630 | // @Produce json |
| 635 | // @Param Authorization header string true "JWT Token" | 631 | // @Param Authorization header string true "JWT Token" |
| 636 | // @Success 200 {object} models.Response{data=ProfileResponse} | 632 | // @Success 200 {object} models.Response{data=ProfileResponse} |
| 637 | // @Failure 400 {object} models.Response | ||
| 638 | // @Failure 401 {object} models.Response | ||
| 639 | // @Router /profile [post] | 633 | // @Router /profile [post] |
| 640 | func UpdateUser(c *gin.Context) { | 634 | func UpdateUser(c *gin.Context) { |
| 641 | // Check if user exists | 635 | // Check if user exists |
| @@ -681,8 +675,6 @@ func UpdateUser(c *gin.Context) { | |||
| 681 | // @Param Authorization header string true "JWT Token" | 675 | // @Param Authorization header string true "JWT Token" |
| 682 | // @Param country_code query string true "Country Code [XX]" | 676 | // @Param country_code query string true "Country Code [XX]" |
| 683 | // @Success 200 {object} models.Response | 677 | // @Success 200 {object} models.Response |
| 684 | // @Failure 400 {object} models.Response | ||
| 685 | // @Failure 401 {object} models.Response | ||
| 686 | // @Router /profile [put] | 678 | // @Router /profile [put] |
| 687 | func UpdateCountryCode(c *gin.Context) { | 679 | func UpdateCountryCode(c *gin.Context) { |
| 688 | // Check if user exists | 680 | // Check if user exists |