aboutsummaryrefslogtreecommitdiff
path: root/backend/handlers/mod.go
diff options
context:
space:
mode:
Diffstat (limited to 'backend/handlers/mod.go')
-rw-r--r--backend/handlers/mod.go334
1 files changed, 334 insertions, 0 deletions
diff --git a/backend/handlers/mod.go b/backend/handlers/mod.go
new file mode 100644
index 0000000..e47cb3f
--- /dev/null
+++ b/backend/handlers/mod.go
@@ -0,0 +1,334 @@
1package handlers
2
3import (
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
13type CreateMapSummaryRequest struct {
14 CategoryID int `json:"category_id" binding:"required"`
15 Description string `json:"description" binding:"required"`
16 Showcase string `json:"showcase"`
17 UserName string `json:"user_name" binding:"required"`
18 ScoreCount *int `json:"score_count" binding:"required"`
19 RecordDate time.Time `json:"record_date" binding:"required"`
20}
21
22type EditMapSummaryRequest struct {
23 RouteID int `json:"route_id" binding:"required"`
24 Description string `json:"description" binding:"required"`
25 Showcase string `json:"showcase"`
26 UserName string `json:"user_name" binding:"required"`
27 ScoreCount *int `json:"score_count" binding:"required"`
28 RecordDate time.Time `json:"record_date" binding:"required"`
29}
30
31type DeleteMapSummaryRequest struct {
32 RouteID int `json:"route_id" binding:"required"`
33}
34
35type EditMapImageRequest struct {
36 Image string `json:"image" binding:"required"`
37}
38
39// POST Map Summary
40//
41// @Description Create map summary with specified map id.
42// @Tags maps
43// @Produce json
44// @Param Authorization header string true "JWT Token"
45// @Param id path int true "Map ID"
46// @Param request body CreateMapSummaryRequest true "Body"
47// @Success 200 {object} models.Response{data=CreateMapSummaryRequest}
48// @Failure 400 {object} models.Response
49// @Router /maps/{id}/summary [post]
50func CreateMapSummary(c *gin.Context) {
51 // Check if user exists
52 _, exists := c.Get("user")
53 if !exists {
54 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
55 return
56 }
57 mod, exists := c.Get("mod")
58 if !exists || !mod.(bool) {
59 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
60 return
61 }
62 // Bind parameter and body
63 id := c.Param("id")
64 mapID, err := strconv.Atoi(id)
65 if err != nil {
66 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
67 return
68 }
69 var request CreateMapSummaryRequest
70 if err := c.BindJSON(&request); err != nil {
71 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
72 return
73 }
74 // Start database transaction
75 tx, err := database.DB.Begin()
76 if err != nil {
77 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
78 return
79 }
80 defer tx.Rollback()
81 // Fetch route category and score count
82 var checkMapID int
83 sql := `SELECT m.id FROM maps m WHERE m.id = $1`
84 err = database.DB.QueryRow(sql, mapID).Scan(&checkMapID)
85 if err != nil {
86 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
87 return
88 }
89 if mapID != checkMapID {
90 c.JSON(http.StatusBadRequest, models.ErrorResponse("Map ID does not exist."))
91 return
92 }
93 // Update database with new data
94 sql = `INSERT INTO map_routes (map_id,category_id,score_count,description,showcase)
95 VALUES ($1,$2,$3,$4,$5)`
96 _, err = tx.Exec(sql, mapID, request.CategoryID, request.ScoreCount, request.Description, request.Showcase)
97 if err != nil {
98 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
99 return
100 }
101 sql = `INSERT INTO map_history (map_id,category_id,user_name,score_count,record_date)
102 VALUES ($1,$2,$3,$4,$5)`
103 _, err = tx.Exec(sql, mapID, request.CategoryID, request.UserName, request.ScoreCount, request.RecordDate)
104 if err != nil {
105 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
106 return
107 }
108 if err = tx.Commit(); err != nil {
109 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
110 return
111 }
112 // Return response
113 c.JSON(http.StatusOK, models.Response{
114 Success: true,
115 Message: "Successfully created map summary.",
116 Data: request,
117 })
118}
119
120// PUT Map Summary
121//
122// @Description Edit map summary with specified map id.
123// @Tags maps
124// @Produce json
125// @Param Authorization header string true "JWT Token"
126// @Param id path int true "Map ID"
127// @Param request body EditMapSummaryRequest true "Body"
128// @Success 200 {object} models.Response{data=EditMapSummaryRequest}
129// @Failure 400 {object} models.Response
130// @Router /maps/{id}/summary [put]
131func EditMapSummary(c *gin.Context) {
132 // Check if user exists
133 _, exists := c.Get("user")
134 if !exists {
135 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
136 return
137 }
138 mod, exists := c.Get("mod")
139 if !exists || !mod.(bool) {
140 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
141 return
142 }
143 // Bind parameter and body
144 id := c.Param("id")
145 mapID, err := strconv.Atoi(id)
146 if err != nil {
147 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
148 return
149 }
150 var request EditMapSummaryRequest
151 if err := c.BindJSON(&request); err != nil {
152 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
153 return
154 }
155 // Start database transaction
156 tx, err := database.DB.Begin()
157 if err != nil {
158 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
159 return
160 }
161 defer tx.Rollback()
162 // Fetch route category and score count
163 var categoryID, scoreCount, historyID int
164 sql := `SELECT mr.category_id, mr.score_count FROM map_routes mr INNER JOIN maps m ON m.id = mr.map_id WHERE m.id = $1 AND mr.id = $2`
165 err = database.DB.QueryRow(sql, mapID, request.RouteID).Scan(&categoryID, &scoreCount)
166 if err != nil {
167 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
168 return
169 }
170 sql = `SELECT mh.id FROM map_history mh WHERE mh.score_count = $1 AND mh.category_id = $2 AND mh.map_id = $3`
171 err = database.DB.QueryRow(sql, scoreCount, categoryID, mapID).Scan(&historyID)
172 if err != nil {
173 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
174 return
175 }
176 // Update database with new data
177 sql = `UPDATE map_routes SET score_count = $2, description = $3, showcase = $4 WHERE id = $1`
178 _, err = tx.Exec(sql, request.RouteID, request.ScoreCount, request.Description, request.Showcase)
179 if err != nil {
180 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
181 return
182 }
183 sql = `UPDATE map_history SET user_name = $2, score_count = $3, record_date = $4 WHERE id = $1`
184 _, err = tx.Exec(sql, historyID, request.UserName, request.ScoreCount, request.RecordDate)
185 if err != nil {
186 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
187 return
188 }
189 if err = tx.Commit(); err != nil {
190 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
191 return
192 }
193 // Return response
194 c.JSON(http.StatusOK, models.Response{
195 Success: true,
196 Message: "Successfully updated map summary.",
197 Data: request,
198 })
199}
200
201// DELETE Map Summary
202//
203// @Description Delete map summary with specified map id.
204// @Tags maps
205// @Produce json
206// @Param Authorization header string true "JWT Token"
207// @Param id path int true "Map ID"
208// @Param request body DeleteMapSummaryRequest true "Body"
209// @Success 200 {object} models.Response{data=DeleteMapSummaryRequest}
210// @Failure 400 {object} models.Response
211// @Router /maps/{id}/summary [delete]
212func DeleteMapSummary(c *gin.Context) {
213 // Check if user exists
214 _, exists := c.Get("user")
215 if !exists {
216 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
217 return
218 }
219 mod, exists := c.Get("mod")
220 if !exists || !mod.(bool) {
221 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
222 return
223 }
224 // Bind parameter and body
225 id := c.Param("id")
226 mapID, err := strconv.Atoi(id)
227 if err != nil {
228 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
229 return
230 }
231 var request DeleteMapSummaryRequest
232 if err := c.BindJSON(&request); err != nil {
233 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
234 return
235 }
236 // Start database transaction
237 tx, err := database.DB.Begin()
238 if err != nil {
239 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
240 return
241 }
242 defer tx.Rollback()
243 // Fetch route category and score count
244 var checkMapID, scoreCount, mapHistoryID int
245 sql := `SELECT m.id, mr.score_count FROM maps m INNER JOIN map_routes mr ON m.id=mr.map_id WHERE m.id = $1 AND mr.id = $2`
246 err = database.DB.QueryRow(sql, mapID, request.RouteID).Scan(&checkMapID, &scoreCount)
247 if err != nil {
248 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
249 return
250 }
251 if mapID != checkMapID {
252 c.JSON(http.StatusBadRequest, models.ErrorResponse("Map ID does not exist."))
253 return
254 }
255 sql = `SELECT mh.id FROM maps m INNER JOIN map_routes mr ON m.id=mr.map_id INNER JOIN map_history mh ON m.id=mh.map_id WHERE m.id = $1 AND mr.id = $2 AND mh.score_count = $3`
256 err = database.DB.QueryRow(sql, mapID, request.RouteID, scoreCount).Scan(&mapHistoryID)
257 if err != nil {
258 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
259 return
260 }
261 // Update database with new data
262 sql = `DELETE FROM map_routes mr WHERE mr.id = $1 `
263 _, err = tx.Exec(sql, request.RouteID)
264 if err != nil {
265 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
266 return
267 }
268 sql = `DELETE FROM map_history mh WHERE mh.id = $1`
269 _, err = tx.Exec(sql, mapHistoryID)
270 if err != nil {
271 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
272 return
273 }
274 if err = tx.Commit(); err != nil {
275 c.JSON(http.StatusInternalServerError, models.ErrorResponse(err.Error()))
276 return
277 }
278 // Return response
279 c.JSON(http.StatusOK, models.Response{
280 Success: true,
281 Message: "Successfully delete map summary.",
282 Data: request,
283 })
284}
285
286// PUT Map Image
287//
288// @Description Edit map image with specified map id.
289// @Tags maps
290// @Produce json
291// @Param Authorization header string true "JWT Token"
292// @Param id path int true "Map ID"
293// @Param request body EditMapImageRequest true "Body"
294// @Success 200 {object} models.Response{data=EditMapImageRequest}
295// @Failure 400 {object} models.Response
296// @Router /maps/{id}/image [put]
297func EditMapImage(c *gin.Context) {
298 // Check if user exists
299 _, exists := c.Get("user")
300 if !exists {
301 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
302 return
303 }
304 mod, exists := c.Get("mod")
305 if !exists || !mod.(bool) {
306 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
307 return
308 }
309 // Bind parameter and body
310 id := c.Param("id")
311 mapID, err := strconv.Atoi(id)
312 if err != nil {
313 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
314 return
315 }
316 var request EditMapImageRequest
317 if err := c.BindJSON(&request); err != nil {
318 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
319 return
320 }
321 // Update database with new data
322 sql := `UPDATE maps SET image = $2 WHERE id = $1`
323 _, err = database.DB.Exec(sql, mapID, request.Image)
324 if err != nil {
325 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
326 return
327 }
328 // Return response
329 c.JSON(http.StatusOK, models.Response{
330 Success: true,
331 Message: "Successfully updated map image.",
332 Data: request,
333 })
334}