aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-08-24 22:34:05 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-08-24 22:34:05 +0300
commitca973edc28b5fe543c583217896590f4a2e98897 (patch)
tree7f37713ac587ef80fb3a17d869d01520a1d94dca /backend
parentMerge branch 'main' of https://github.com/pektezol/LeastPortalsHub (diff)
downloadlphub-ca973edc28b5fe543c583217896590f4a2e98897.tar.gz
lphub-ca973edc28b5fe543c583217896590f4a2e98897.tar.bz2
lphub-ca973edc28b5fe543c583217896590f4a2e98897.zip
fix: mod flag for easy check (#49)
Former-commit-id: 06ee23ee9659834252d3cb5c3c255797e9f93b62
Diffstat (limited to 'backend')
-rw-r--r--backend/controllers/modController.go44
-rw-r--r--backend/controllers/userController.go95
-rw-r--r--backend/database/init.sql15
-rw-r--r--backend/middleware/auth.go13
-rw-r--r--backend/models/models.go14
5 files changed, 93 insertions, 88 deletions
diff --git a/backend/controllers/modController.go b/backend/controllers/modController.go
index 7ce5cb4..7acdb5d 100644
--- a/backend/controllers/modController.go
+++ b/backend/controllers/modController.go
@@ -49,18 +49,13 @@ type EditMapImageRequest struct {
49// @Router /maps/{id}/summary [post] 49// @Router /maps/{id}/summary [post]
50func CreateMapSummary(c *gin.Context) { 50func CreateMapSummary(c *gin.Context) {
51 // Check if user exists 51 // Check if user exists
52 user, exists := c.Get("user") 52 _, exists := c.Get("user")
53 if !exists { 53 if !exists {
54 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) 54 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
55 return 55 return
56 } 56 }
57 var moderator bool 57 mod, exists := c.Get("mod")
58 for _, title := range user.(models.User).Titles { 58 if !exists || !mod.(bool) {
59 if title == "Moderator" {
60 moderator = true
61 }
62 }
63 if !moderator {
64 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions.")) 59 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
65 return 60 return
66 } 61 }
@@ -135,18 +130,13 @@ func CreateMapSummary(c *gin.Context) {
135// @Router /maps/{id}/summary [put] 130// @Router /maps/{id}/summary [put]
136func EditMapSummary(c *gin.Context) { 131func EditMapSummary(c *gin.Context) {
137 // Check if user exists 132 // Check if user exists
138 user, exists := c.Get("user") 133 _, exists := c.Get("user")
139 if !exists { 134 if !exists {
140 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) 135 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
141 return 136 return
142 } 137 }
143 var moderator bool 138 mod, exists := c.Get("mod")
144 for _, title := range user.(models.User).Titles { 139 if !exists || !mod.(bool) {
145 if title == "Moderator" {
146 moderator = true
147 }
148 }
149 if !moderator {
150 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions.")) 140 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
151 return 141 return
152 } 142 }
@@ -221,18 +211,13 @@ func EditMapSummary(c *gin.Context) {
221// @Router /maps/{id}/summary [delete] 211// @Router /maps/{id}/summary [delete]
222func DeleteMapSummary(c *gin.Context) { 212func DeleteMapSummary(c *gin.Context) {
223 // Check if user exists 213 // Check if user exists
224 user, exists := c.Get("user") 214 _, exists := c.Get("user")
225 if !exists { 215 if !exists {
226 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) 216 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
227 return 217 return
228 } 218 }
229 var moderator bool 219 mod, exists := c.Get("mod")
230 for _, title := range user.(models.User).Titles { 220 if !exists || !mod.(bool) {
231 if title == "Moderator" {
232 moderator = true
233 }
234 }
235 if !moderator {
236 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions.")) 221 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
237 return 222 return
238 } 223 }
@@ -311,18 +296,13 @@ func DeleteMapSummary(c *gin.Context) {
311// @Router /maps/{id}/image [put] 296// @Router /maps/{id}/image [put]
312func EditMapImage(c *gin.Context) { 297func EditMapImage(c *gin.Context) {
313 // Check if user exists 298 // Check if user exists
314 user, exists := c.Get("user") 299 _, exists := c.Get("user")
315 if !exists { 300 if !exists {
316 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) 301 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
317 return 302 return
318 } 303 }
319 var moderator bool 304 mod, exists := c.Get("mod")
320 for _, title := range user.(models.User).Titles { 305 if !exists || !mod.(bool) {
321 if title == "Moderator" {
322 moderator = true
323 }
324 }
325 if !moderator {
326 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions.")) 306 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
327 return 307 return
328 } 308 }
diff --git a/backend/controllers/userController.go b/backend/controllers/userController.go
index 0dae155..64f144a 100644
--- a/backend/controllers/userController.go
+++ b/backend/controllers/userController.go
@@ -17,8 +17,39 @@ type ProfileResponse struct {
17 UserName string `json:"user_name"` 17 UserName string `json:"user_name"`
18 AvatarLink string `json:"avatar_link"` 18 AvatarLink string `json:"avatar_link"`
19 CountryCode string `json:"country_code"` 19 CountryCode string `json:"country_code"`
20 ScoresSP []ScoreResponse `json:"scores_sp"` 20 Titles []models.Title `json:"titles"`
21 ScoresMP []ScoreResponse `json:"scores_mp"` 21 Links models.Links `json:"links"`
22 Rankings ProfileRankings `json:"rankings"`
23 Records ProfileRecords `json:"records"`
24}
25
26type ProfileRankings struct {
27 Overall ProfileRankingsDetails `json:"overall"`
28 Singleplayer ProfileRankingsDetails `json:"singleplayer"`
29 Cooperative ProfileRankingsDetails `json:"cooperative"`
30}
31
32type ProfileRankingsDetails struct {
33 Rank int `json:"rank"`
34 CompletionCount int `json:"completion_count"`
35 CompletionTotal int `json:"completion_total"`
36}
37
38type ProfileRecords struct {
39 P2Singleplayer ProfileRecordsDetails `json:"portal2_singleplayer"`
40 P2Cooperative ProfileRecordsDetails `json:"portal2_cooperative"`
41}
42
43type ProfileRecordsDetails struct {
44 MapID int `json:"map_id"`
45 Scores []ProfileScores `json:"scores"`
46}
47
48type ProfileScores struct {
49 DemoID string `json:"demo_id"`
50 ScoreCount int `json:"score_count"`
51 ScoreTime int `json:"score_time"`
52 Date time.Time `json:"date"`
22} 53}
23 54
24type ScoreResponse struct { 55type ScoreResponse struct {
@@ -44,58 +75,22 @@ func Profile(c *gin.Context) {
44 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) 75 c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in."))
45 return 76 return
46 } 77 }
47 // Retrieve singleplayer records 78 // Get user titles
48 var scoresSP []ScoreResponse 79 titles := []models.Title{}
49 sql := `SELECT id, map_id, score_count, score_time, demo_id, record_date FROM records_sp WHERE user_id = $1 ORDER BY map_id` 80 sql := `SELECT t.title_name, t.title_color FROM titles t
81 INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1`
50 rows, err := database.DB.Query(sql, user.(models.User).SteamID) 82 rows, err := database.DB.Query(sql, user.(models.User).SteamID)
51 if err != nil { 83 if err != nil {
52 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 84 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
53 return 85 return
54 } 86 }
55 var recordsSP []models.RecordSP
56 for rows.Next() {
57 var mapID int
58 var record models.RecordSP
59 rows.Scan(&record.RecordID, &mapID, &record.ScoreCount, &record.ScoreTime, &record.DemoID, &record.RecordDate)
60 // More than one record in one map
61 if len(scoresSP) != 0 && mapID == scoresSP[len(scoresSP)-1].MapID {
62 scoresSP[len(scoresSP)-1].Records = append(scoresSP[len(scoresSP)-1].Records.([]models.RecordSP), record)
63 continue
64 }
65 // New map
66 recordsSP = []models.RecordSP{}
67 recordsSP = append(recordsSP, record)
68 scoresSP = append(scoresSP, ScoreResponse{
69 MapID: mapID,
70 Records: recordsSP,
71 })
72 }
73 // Retrieve multiplayer records
74 var scoresMP []ScoreResponse
75 sql = `SELECT id, map_id, host_id, partner_id, score_count, score_time, host_demo_id, partner_demo_id, record_date FROM records_mp
76 WHERE host_id = $1 OR partner_id = $2 ORDER BY map_id`
77 rows, err = database.DB.Query(sql, user.(models.User).SteamID, user.(models.User).SteamID)
78 if err != nil {
79 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
80 return
81 }
82 var recordsMP []models.RecordMP
83 for rows.Next() { 87 for rows.Next() {
84 var mapID int 88 var title models.Title
85 var record models.RecordMP 89 if err := rows.Scan(&title.Name, &title.Color); err != nil {
86 rows.Scan(&record.RecordID, &mapID, &record.HostID, &record.PartnerID, &record.ScoreCount, &record.ScoreTime, &record.HostDemoID, &record.PartnerDemoID, &record.RecordDate) 90 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
87 // More than one record in one map 91 return
88 if len(scoresMP) != 0 && mapID == scoresMP[len(scoresMP)-1].MapID {
89 scoresMP[len(scoresMP)-1].Records = append(scoresMP[len(scoresMP)-1].Records.([]models.RecordMP), record)
90 continue
91 } 92 }
92 // New map 93 titles = append(titles, title)
93 recordsMP = []models.RecordMP{}
94 recordsMP = append(recordsMP, record)
95 scoresMP = append(scoresMP, ScoreResponse{
96 MapID: mapID,
97 Records: recordsMP,
98 })
99 } 94 }
100 c.JSON(http.StatusOK, models.Response{ 95 c.JSON(http.StatusOK, models.Response{
101 Success: true, 96 Success: true,
@@ -106,8 +101,10 @@ func Profile(c *gin.Context) {
106 UserName: user.(models.User).UserName, 101 UserName: user.(models.User).UserName,
107 AvatarLink: user.(models.User).AvatarLink, 102 AvatarLink: user.(models.User).AvatarLink,
108 CountryCode: user.(models.User).CountryCode, 103 CountryCode: user.(models.User).CountryCode,
109 ScoresSP: scoresSP, 104 Titles: user.(models.User).Titles,
110 ScoresMP: scoresMP, 105 Links: models.Links{},
106 Rankings: ProfileRankings{},
107 Records: ProfileRecords{},
111 }, 108 },
112 }) 109 })
113 return 110 return
diff --git a/backend/database/init.sql b/backend/database/init.sql
index 11d4944..25de872 100644
--- a/backend/database/init.sql
+++ b/backend/database/init.sql
@@ -3,6 +3,10 @@ CREATE TABLE users (
3 user_name TEXT NOT NULL, 3 user_name TEXT NOT NULL,
4 avatar_link TEXT NOT NULL, 4 avatar_link TEXT NOT NULL,
5 country_code CHAR(2) NOT NULL, 5 country_code CHAR(2) NOT NULL,
6 p2sr TEXT NOT NULL DEFAULT '-',
7 steam TEXT NOT NULL DEFAULT '-',
8 youtube TEXT NOT NULL DEFAULT '-',
9 twitch TEXT NOT NULL DEFAULT '-',
6 created_at TIMESTAMP NOT NULL DEFAULT now(), 10 created_at TIMESTAMP NOT NULL DEFAULT now(),
7 updated_at TIMESTAMP NOT NULL DEFAULT now(), 11 updated_at TIMESTAMP NOT NULL DEFAULT now(),
8 PRIMARY KEY (steam_id) 12 PRIMARY KEY (steam_id)
@@ -117,9 +121,16 @@ CREATE TABLE records_mp (
117); 121);
118 122
119CREATE TABLE titles ( 123CREATE TABLE titles (
120 user_id TEXT, 124 id SERIAL,
121 title_name TEXT NOT NULL, 125 title_name TEXT NOT NULL,
122 PRIMARY KEY (user_id), 126 title_color CHAR(6) NOT NULL,
127 PRIMARY KEY (id)
128);
129
130CREATE TABLE user_titles (
131 title_id INT NOT NULL,
132 user_id TEXT NOT NULL,
133 FOREIGN KEY (title_id) REFERENCES titles(id),
123 FOREIGN KEY (user_id) REFERENCES users(steam_id) 134 FOREIGN KEY (user_id) REFERENCES users(steam_id)
124); 135);
125 136
diff --git a/backend/middleware/auth.go b/backend/middleware/auth.go
index 6a057da..e2c84fa 100644
--- a/backend/middleware/auth.go
+++ b/backend/middleware/auth.go
@@ -44,14 +44,19 @@ func CheckAuth(c *gin.Context) {
44 return 44 return
45 } 45 }
46 // Get user titles from DB 46 // Get user titles from DB
47 user.Titles = []string{} 47 var moderator bool
48 rows, _ := database.DB.Query(`SELECT title_name FROM titles t INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1`, user.SteamID) 48 user.Titles = []models.Title{}
49 rows, _ := database.DB.Query(`SELECT t.title_name, t.title_color FROM titles t INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1`, user.SteamID)
49 for rows.Next() { 50 for rows.Next() {
50 var title string 51 var title models.Title
51 rows.Scan(&title) 52 rows.Scan(&title.Name, &title.Color)
53 if title.Name == "Moderator" {
54 moderator = true
55 }
52 user.Titles = append(user.Titles, title) 56 user.Titles = append(user.Titles, title)
53 } 57 }
54 c.Set("user", user) 58 c.Set("user", user)
59 c.Set("mod", moderator)
55 c.Next() 60 c.Next()
56 } else { 61 } else {
57 c.Next() 62 c.Next()
diff --git a/backend/models/models.go b/backend/models/models.go
index e21ba6a..f124db5 100644
--- a/backend/models/models.go
+++ b/backend/models/models.go
@@ -25,7 +25,7 @@ type User struct {
25 CountryCode string `json:"country_code"` 25 CountryCode string `json:"country_code"`
26 CreatedAt time.Time `json:"created_at"` 26 CreatedAt time.Time `json:"created_at"`
27 UpdatedAt time.Time `json:"updated_at"` 27 UpdatedAt time.Time `json:"updated_at"`
28 Titles []string `json:"titles"` 28 Titles []Title `json:"titles"`
29} 29}
30 30
31type UserShort struct { 31type UserShort struct {
@@ -92,6 +92,18 @@ type Category struct {
92 Name string `json:"name"` 92 Name string `json:"name"`
93} 93}
94 94
95type Title struct {
96 Name string `json:"name"`
97 Color string `json:"color"`
98}
99
100type Links struct {
101 P2SR string `json:"p2sr"`
102 Steam string `json:"stream"`
103 YouTube string `json:"youtube"`
104 Twitch string `json:"twitch"`
105}
106
95type RecordSP struct { 107type RecordSP struct {
96 RecordID int `json:"record_id"` 108 RecordID int `json:"record_id"`
97 Placement int `json:"placement"` 109 Placement int `json:"placement"`