aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/api/routes.go2
-rw-r--r--backend/database/init.sql10
-rw-r--r--backend/handlers/login.go4
-rw-r--r--backend/handlers/logs.go114
4 files changed, 130 insertions, 0 deletions
diff --git a/backend/api/routes.go b/backend/api/routes.go
index 4dd8660..ac622d4 100644
--- a/backend/api/routes.go
+++ b/backend/api/routes.go
@@ -36,5 +36,7 @@ func InitRoutes(router *gin.Engine) {
36 v1.GET("/games", handlers.FetchGames) 36 v1.GET("/games", handlers.FetchGames)
37 v1.GET("/games/:id", handlers.FetchChapters) 37 v1.GET("/games/:id", handlers.FetchChapters)
38 v1.GET("/chapters/:id", handlers.FetchChapterMaps) 38 v1.GET("/chapters/:id", handlers.FetchChapterMaps)
39 v1.GET("/logs/score", handlers.ScoreLogs)
40 v1.GET("/logs/mod", CheckAuth, handlers.ModLogs)
39 } 41 }
40} 42}
diff --git a/backend/database/init.sql b/backend/database/init.sql
index 25de872..abace5c 100644
--- a/backend/database/init.sql
+++ b/backend/database/init.sql
@@ -139,3 +139,13 @@ CREATE TABLE countries (
139 country_name TEXT NOT NULL, 139 country_name TEXT NOT NULL,
140 PRIMARY KEY (country_code) 140 PRIMARY KEY (country_code)
141); 141);
142
143CREATE TABLE logs (
144 id SERIAL,
145 user_id TEXT NOT NULL,
146 type TEXT NOT NULL,
147 description TEXT NOT NULL,
148 date TIMESTAMP NOT NULL DEFAULT now(),
149 PRIMARY KEY (id),
150 FOREIGN KEY (user_id) REFERENCES users(steam_id)
151); \ No newline at end of file
diff --git a/backend/handlers/login.go b/backend/handlers/login.go
index 4b151c2..80f697e 100644
--- a/backend/handlers/login.go
+++ b/backend/handlers/login.go
@@ -38,6 +38,7 @@ func Login(c *gin.Context) {
38 default: 38 default:
39 steamID, err := openID.ValidateAndGetId() 39 steamID, err := openID.ValidateAndGetId()
40 if err != nil { 40 if err != nil {
41 CreateLog(steamID, LogTypeLogin, LogDescriptionLoginFailValidate)
41 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 42 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
42 return 43 return
43 } 44 }
@@ -48,6 +49,7 @@ func Login(c *gin.Context) {
48 if checkSteamID == 0 { 49 if checkSteamID == 0 {
49 user, err := GetPlayerSummaries(steamID, os.Getenv("API_KEY")) 50 user, err := GetPlayerSummaries(steamID, os.Getenv("API_KEY"))
50 if err != nil { 51 if err != nil {
52 CreateLog(steamID, LogTypeLogin, LogDescriptionLoginFailSummary)
51 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 53 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
52 return 54 return
53 } 55 }
@@ -77,10 +79,12 @@ func Login(c *gin.Context) {
77 // Sign and get the complete encoded token as a string using the secret 79 // Sign and get the complete encoded token as a string using the secret
78 tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY"))) 80 tokenString, err := token.SignedString([]byte(os.Getenv("SECRET_KEY")))
79 if err != nil { 81 if err != nil {
82 CreateLog(steamID, LogTypeLogin, LogDescriptionLoginFailToken)
80 c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token.")) 83 c.JSON(http.StatusBadRequest, models.ErrorResponse("Failed to generate token."))
81 return 84 return
82 } 85 }
83 c.SetCookie("token", tokenString, 3600*24*30, "/", "", true, true) 86 c.SetCookie("token", tokenString, 3600*24*30, "/", "", true, true)
87 CreateLog(steamID, LogTypeLogin, LogDescriptionLoginSuccess)
84 c.Redirect(http.StatusTemporaryRedirect, "/") 88 c.Redirect(http.StatusTemporaryRedirect, "/")
85 // c.JSON(http.StatusOK, models.Response{ 89 // c.JSON(http.StatusOK, models.Response{
86 // Success: true, 90 // Success: true,
diff --git a/backend/handlers/logs.go b/backend/handlers/logs.go
new file mode 100644
index 0000000..2b5713d
--- /dev/null
+++ b/backend/handlers/logs.go
@@ -0,0 +1,114 @@
1package handlers
2
3import (
4 "fmt"
5 "net/http"
6
7 "github.com/gin-gonic/gin"
8 "github.com/pektezol/leastportalshub/backend/database"
9 "github.com/pektezol/leastportalshub/backend/models"
10)
11
12const (
13 LogTypeMod string = "Mod"
14 LogTypeScore string = "Score"
15 LogTypeLogin string = "Login"
16
17 LogDescriptionLoginSuccess string = "Success"
18 LogDescriptionLoginFailToken string = "TokenFail"
19 LogDescriptionLoginFailValidate string = "ValidateFail"
20 LogDescriptionLoginFailSummary string = "SummaryFail"
21)
22
23type Log struct {
24 User models.UserShort `json:"user"`
25 Type string `json:"type"`
26 Description string `json:"description"`
27}
28
29type LogsResponse struct {
30 Logs []LogsResponseDetails `json:"logs"`
31}
32
33type LogsResponseDetails struct {
34 User models.UserShort `json:"user"`
35 Log string `json:"detail"`
36}
37
38func ModLogs(c *gin.Context) {
39 mod, exists := c.Get("mod")
40 if !exists || !mod.(bool) {
41 c.JSON(http.StatusUnauthorized, models.ErrorResponse("Insufficient permissions."))
42 return
43 }
44 response := LogsResponse{Logs: []LogsResponseDetails{}}
45 sql := `SELECT u.user_name, l.user_id, l.type, l.description
46 FROM logs l INNER JOIN users u ON l.user_id = u.steam_id WHERE type != 'Score'`
47 rows, err := database.DB.Query(sql)
48 if err != nil {
49 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
50 return
51 }
52 for rows.Next() {
53 log := Log{}
54 err = rows.Scan(log.User.UserName, log.User.SteamID, log.Type, log.Description)
55 if err != nil {
56 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
57 return
58 }
59 detail := fmt.Sprintf("%s.%s", log.Type, log.Description)
60 response.Logs = append(response.Logs, LogsResponseDetails{
61 User: models.UserShort{
62 SteamID: log.User.SteamID,
63 UserName: log.User.UserName,
64 },
65 Log: detail,
66 })
67 }
68 c.JSON(http.StatusOK, models.Response{
69 Success: true,
70 Message: "Successfully retrieved logs.",
71 Data: response,
72 })
73}
74
75func ScoreLogs(c *gin.Context) {
76 response := LogsResponse{Logs: []LogsResponseDetails{}}
77 sql := `SELECT u.user_name, l.user_id, l.type, l.description
78 FROM logs l INNER JOIN users u ON l.user_id = u.steam_id WHERE type = 'Score'`
79 rows, err := database.DB.Query(sql)
80 if err != nil {
81 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
82 return
83 }
84 for rows.Next() {
85 log := Log{}
86 err = rows.Scan(log.User.UserName, log.User.SteamID, log.Type, log.Description)
87 if err != nil {
88 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
89 return
90 }
91 detail := fmt.Sprintf("%s.%s", log.Type, log.Description)
92 response.Logs = append(response.Logs, LogsResponseDetails{
93 User: models.UserShort{
94 SteamID: log.User.SteamID,
95 UserName: log.User.UserName,
96 },
97 Log: detail,
98 })
99 }
100 c.JSON(http.StatusOK, models.Response{
101 Success: true,
102 Message: "Successfully retrieved score logs.",
103 Data: response,
104 })
105}
106
107func CreateLog(user_id string, log_type string, log_description string) (err error) {
108 sql := `INSERT INTO logs (user_id, "type", description) VALUES($1, $2, $3)`
109 _, err = database.DB.Exec(sql)
110 if err != nil {
111 return err
112 }
113 return nil
114}