diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-06-28 23:27:22 +0300 |
|---|---|---|
| committer | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-06-28 23:27:22 +0300 |
| commit | 8cce8b446e63d03161f0807c76721b40d851b50d (patch) | |
| tree | 5c990d3e7e3f89550ea77107d4b1ed253a16b238 | |
| parent | feat: image field for maps (diff) | |
| download | lphub-8cce8b446e63d03161f0807c76721b40d851b50d.tar.gz lphub-8cce8b446e63d03161f0807c76721b40d851b50d.tar.bz2 lphub-8cce8b446e63d03161f0807c76721b40d851b50d.zip | |
feat: mod edit for map summary
Former-commit-id: dbef520658347a8c23546371ced24f1c0271749d
| -rw-r--r-- | backend/controllers/modController.go | 91 | ||||
| -rw-r--r-- | backend/middleware/auth.go | 10 | ||||
| -rw-r--r-- | backend/models/models.go | 1 | ||||
| -rw-r--r-- | backend/models/requests.go | 29 | ||||
| -rw-r--r-- | backend/routes/routes.go | 1 |
5 files changed, 127 insertions, 5 deletions
diff --git a/backend/controllers/modController.go b/backend/controllers/modController.go new file mode 100644 index 0000000..ebf1cb7 --- /dev/null +++ b/backend/controllers/modController.go | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | package controllers | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "net/http" | ||
| 5 | "strconv" | ||
| 6 | |||
| 7 | "github.com/gin-gonic/gin" | ||
| 8 | "github.com/pektezol/leastportals/backend/database" | ||
| 9 | "github.com/pektezol/leastportals/backend/models" | ||
| 10 | ) | ||
| 11 | |||
| 12 | // PUT Map Summary | ||
| 13 | // | ||
| 14 | // @Summary Edit map summary with specified map id. | ||
| 15 | // @Tags maps | ||
| 16 | // @Produce json | ||
| 17 | // @Param id path int true "Map ID" | ||
| 18 | // @Success 200 {object} models.Response{data=models.EditMapSummaryRequest} | ||
| 19 | // @Failure 400 {object} models.Response | ||
| 20 | // @Router /maps/{id}/summary [put] | ||
| 21 | func EditMapSummary(c *gin.Context) { | ||
| 22 | // Check if user exists | ||
| 23 | user, exists := c.Get("user") | ||
| 24 | if !exists { | ||
| 25 | c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) | ||
| 26 | return | ||
| 27 | } | ||
| 28 | var moderator bool | ||
| 29 | for _, title := range user.(models.User).Titles { | ||
| 30 | if title == "Moderator" { | ||
| 31 | moderator = true | ||
| 32 | } | ||
| 33 | } | ||
| 34 | if !moderator { | ||
| 35 | c.JSON(http.StatusUnauthorized, "Insufficient permissions.") | ||
| 36 | return | ||
| 37 | } | ||
| 38 | // Bind parameter and body | ||
| 39 | id := c.Param("id") | ||
| 40 | mapID, err := strconv.Atoi(id) | ||
| 41 | if err != nil { | ||
| 42 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 43 | return | ||
| 44 | } | ||
| 45 | var request models.EditMapSummaryRequest | ||
| 46 | if err := c.BindJSON(&request); err != nil { | ||
| 47 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 48 | return | ||
| 49 | } | ||
| 50 | // Fetch route category and score count | ||
| 51 | var categoryID, scoreCount int | ||
| 52 | sql := `SELECT mr.category_id, mr.score_count | ||
| 53 | FROM map_routes mr | ||
| 54 | INNER JOIN maps m | ||
| 55 | WHERE m.id = $1 AND mr.id = $2` | ||
| 56 | err = database.DB.QueryRow(sql, mapID, request.RouteID).Scan(&categoryID, &scoreCount) | ||
| 57 | if err != nil { | ||
| 58 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 59 | return | ||
| 60 | } | ||
| 61 | // Start database transaction | ||
| 62 | tx, err := database.DB.Begin() | ||
| 63 | if err != nil { | ||
| 64 | c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) | ||
| 65 | return | ||
| 66 | } | ||
| 67 | defer tx.Rollback() | ||
| 68 | // Update database with new data | ||
| 69 | sql = `UPDATE map_routes SET score_count = $2, description = $3, showcase = $4 WHERE id = $1` | ||
| 70 | _, err = tx.Exec(sql, request.RouteID, request.ScoreCount, request.Description, request.Showcase) | ||
| 71 | if err != nil { | ||
| 72 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 73 | return | ||
| 74 | } | ||
| 75 | sql = `UPDATE map_history SET user_name = $3, score_count = $4, record_date = $5 WHERE map_id = $1 AND category_id = $2` | ||
| 76 | _, err = tx.Exec(sql, mapID, categoryID, request.UserName, request.ScoreCount, request.RecordDate) | ||
| 77 | if err != nil { | ||
| 78 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | ||
| 79 | return | ||
| 80 | } | ||
| 81 | if err = tx.Commit(); err != nil { | ||
| 82 | c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error())) | ||
| 83 | return | ||
| 84 | } | ||
| 85 | // Return response | ||
| 86 | c.JSON(http.StatusOK, models.Response{ | ||
| 87 | Success: true, | ||
| 88 | Message: "Successfully updated map summary.", | ||
| 89 | Data: request, | ||
| 90 | }) | ||
| 91 | } | ||
diff --git a/backend/middleware/auth.go b/backend/middleware/auth.go index 14a0b78..86e79d9 100644 --- a/backend/middleware/auth.go +++ b/backend/middleware/auth.go | |||
| @@ -36,13 +36,21 @@ func CheckAuth(c *gin.Context) { | |||
| 36 | } | 36 | } |
| 37 | // Get user from DB | 37 | // Get user from DB |
| 38 | var user models.User | 38 | var user models.User |
| 39 | database.DB.QueryRow(`SELECT * FROM users WHERE steam_id = $1`, claims["sub"]).Scan( | 39 | database.DB.QueryRow(`SELECT u.steam_id, u.user_name, u.avatar_link, u.country_code, u.created_at, u.updated_at, array_agg(t.) FROM users u WHERE steam_id = $1`, claims["sub"]).Scan( |
| 40 | &user.SteamID, &user.UserName, &user.AvatarLink, | 40 | &user.SteamID, &user.UserName, &user.AvatarLink, |
| 41 | &user.CountryCode, &user.CreatedAt, &user.UpdatedAt) | 41 | &user.CountryCode, &user.CreatedAt, &user.UpdatedAt) |
| 42 | if user.SteamID == "" { | 42 | if user.SteamID == "" { |
| 43 | c.Next() | 43 | c.Next() |
| 44 | return | 44 | return |
| 45 | } | 45 | } |
| 46 | // Get user titles from DB | ||
| 47 | user.Titles = []string{} | ||
| 48 | rows, _ := database.DB.Query(`SELECT t.title_name FROM titles t WHERE t.user_id = $1`, user.SteamID) | ||
| 49 | for rows.Next() { | ||
| 50 | var title string | ||
| 51 | rows.Scan(&title) | ||
| 52 | user.Titles = append(user.Titles, title) | ||
| 53 | } | ||
| 46 | c.Set("user", user) | 54 | c.Set("user", user) |
| 47 | c.Next() | 55 | c.Next() |
| 48 | } else { | 56 | } else { |
diff --git a/backend/models/models.go b/backend/models/models.go index 7b8cbc4..5355a9f 100644 --- a/backend/models/models.go +++ b/backend/models/models.go | |||
| @@ -11,6 +11,7 @@ type User struct { | |||
| 11 | CountryCode string `json:"country_code"` | 11 | CountryCode string `json:"country_code"` |
| 12 | CreatedAt time.Time `json:"created_at"` | 12 | CreatedAt time.Time `json:"created_at"` |
| 13 | UpdatedAt time.Time `json:"updated_at"` | 13 | UpdatedAt time.Time `json:"updated_at"` |
| 14 | Titles []string `json:"titles"` | ||
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | type UserShort struct { | 17 | type UserShort struct { |
diff --git a/backend/models/requests.go b/backend/models/requests.go index 49b2d75..e95eab6 100644 --- a/backend/models/requests.go +++ b/backend/models/requests.go | |||
| @@ -1,8 +1,29 @@ | |||
| 1 | package models | 1 | package models |
| 2 | 2 | ||
| 3 | import ( | ||
| 4 | "mime/multipart" | ||
| 5 | "time" | ||
| 6 | ) | ||
| 7 | |||
| 8 | type EditMapSummaryRequest struct { | ||
| 9 | RouteID int `json:"route_id" binding:"required"` | ||
| 10 | Description string `json:"description" binding:"required"` | ||
| 11 | Showcase string `json:"showcase" binding:"required"` | ||
| 12 | UserName string `json:"user_name" binding:"required"` | ||
| 13 | ScoreCount int `json:"score_count" binding:"required"` | ||
| 14 | RecordDate time.Time `json:"record_date" binding:"required"` | ||
| 15 | } | ||
| 16 | |||
| 17 | type CreateMapHistoryRequest struct { | ||
| 18 | CategoryID int `json:"category_id" binding:"required"` | ||
| 19 | UserName string `json:"user_name" binding:"required"` | ||
| 20 | ScoreCount int `json:"score_count" binding:"required"` | ||
| 21 | RecordDate time.Time `json:"record_date" binding:"required"` | ||
| 22 | } | ||
| 23 | |||
| 3 | type RecordRequest struct { | 24 | type RecordRequest struct { |
| 4 | ScoreCount int `json:"score_count" form:"score_count" binding:"required"` | 25 | HostDemo *multipart.FileHeader `json:"host_demo" form:"host_demo" binding:"required"` |
| 5 | ScoreTime int `json:"score_time" form:"score_time" binding:"required"` | 26 | PartnerDemo *multipart.FileHeader `json:"partner_demo" form:"partner_demo"` |
| 6 | PartnerID string `json:"partner_id" form:"partner_id" binding:"required"` | 27 | IsPartnerOrange bool `json:"is_partner_orange" form:"is_partner_orange"` |
| 7 | IsPartnerOrange bool `json:"is_partner_orange" form:"is_partner_orange" binding:"required"` | 28 | PartnerID string `json:"partner_id" form:"partner_id"` |
| 8 | } | 29 | } |
diff --git a/backend/routes/routes.go b/backend/routes/routes.go index bf8a995..93dc1dd 100644 --- a/backend/routes/routes.go +++ b/backend/routes/routes.go | |||
| @@ -26,6 +26,7 @@ func InitRoutes(router *gin.Engine) { | |||
| 26 | v1.GET("/users/:id", middleware.CheckAuth, controllers.FetchUser) | 26 | v1.GET("/users/:id", middleware.CheckAuth, controllers.FetchUser) |
| 27 | v1.GET("/demos", controllers.DownloadDemoWithID) | 27 | v1.GET("/demos", controllers.DownloadDemoWithID) |
| 28 | v1.GET("/maps/:id/summary", middleware.CheckAuth, controllers.FetchMapSummary) | 28 | v1.GET("/maps/:id/summary", middleware.CheckAuth, controllers.FetchMapSummary) |
| 29 | v1.PUT("/maps/:id/summary", middleware.CheckAuth, controllers.EditMapSummary) | ||
| 29 | v1.GET("/maps/:id/leaderboards", middleware.CheckAuth, controllers.FetchMapLeaderboards) | 30 | v1.GET("/maps/:id/leaderboards", middleware.CheckAuth, controllers.FetchMapLeaderboards) |
| 30 | v1.POST("/maps/:id/record", middleware.CheckAuth, controllers.CreateRecordWithDemo) | 31 | v1.POST("/maps/:id/record", middleware.CheckAuth, controllers.CreateRecordWithDemo) |
| 31 | v1.GET("/rankings", middleware.CheckAuth, controllers.Rankings) | 32 | v1.GET("/rankings", middleware.CheckAuth, controllers.Rankings) |