diff options
Diffstat (limited to 'backend/api')
| -rw-r--r-- | backend/api/auth.go | 19 | ||||
| -rw-r--r-- | backend/api/routes.go | 98 |
2 files changed, 48 insertions, 69 deletions
diff --git a/backend/api/auth.go b/backend/api/auth.go index 621a68b..a1f859c 100644 --- a/backend/api/auth.go +++ b/backend/api/auth.go | |||
| @@ -2,6 +2,7 @@ package api | |||
| 2 | 2 | ||
| 3 | import ( | 3 | import ( |
| 4 | "fmt" | 4 | "fmt" |
| 5 | "net/http" | ||
| 5 | "os" | 6 | "os" |
| 6 | "time" | 7 | "time" |
| 7 | 8 | ||
| @@ -12,7 +13,7 @@ import ( | |||
| 12 | "github.com/golang-jwt/jwt/v4" | 13 | "github.com/golang-jwt/jwt/v4" |
| 13 | ) | 14 | ) |
| 14 | 15 | ||
| 15 | func CheckAuth(c *gin.Context) { | 16 | func IsAuthenticated(c *gin.Context) { |
| 16 | tokenString := c.GetHeader("Authorization") | 17 | tokenString := c.GetHeader("Authorization") |
| 17 | // Validate token | 18 | // Validate token |
| 18 | token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { | 19 | token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { |
| @@ -22,17 +23,17 @@ func CheckAuth(c *gin.Context) { | |||
| 22 | return []byte(os.Getenv("SECRET_KEY")), nil | 23 | return []byte(os.Getenv("SECRET_KEY")), nil |
| 23 | }) | 24 | }) |
| 24 | if token == nil { | 25 | if token == nil { |
| 25 | c.Next() | 26 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Token is nil.")) |
| 26 | return | 27 | return |
| 27 | } | 28 | } |
| 28 | if err != nil { | 29 | if err != nil { |
| 29 | c.Next() | 30 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Token is invalid.")) |
| 30 | return | 31 | return |
| 31 | } | 32 | } |
| 32 | if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { | 33 | if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { |
| 33 | // Check exp | 34 | // Check exp |
| 34 | if float64(time.Now().Unix()) > claims["exp"].(float64) { | 35 | if float64(time.Now().Unix()) > claims["exp"].(float64) { |
| 35 | c.Next() | 36 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Token expired.")) |
| 36 | return | 37 | return |
| 37 | } | 38 | } |
| 38 | // Get user from DB | 39 | // Get user from DB |
| @@ -41,7 +42,7 @@ func CheckAuth(c *gin.Context) { | |||
| 41 | &user.SteamID, &user.UserName, &user.AvatarLink, | 42 | &user.SteamID, &user.UserName, &user.AvatarLink, |
| 42 | &user.CountryCode, &user.CreatedAt, &user.UpdatedAt) | 43 | &user.CountryCode, &user.CreatedAt, &user.UpdatedAt) |
| 43 | if user.SteamID == "" { | 44 | if user.SteamID == "" { |
| 44 | c.Next() | 45 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Token does not match a user.")) |
| 45 | return | 46 | return |
| 46 | } | 47 | } |
| 47 | // Get user titles from DB | 48 | // Get user titles from DB |
| @@ -56,11 +57,17 @@ func CheckAuth(c *gin.Context) { | |||
| 56 | } | 57 | } |
| 57 | user.Titles = append(user.Titles, title) | 58 | user.Titles = append(user.Titles, title) |
| 58 | } | 59 | } |
| 60 | // Set user id variable in db session for audit logging | ||
| 61 | _, err = database.DB.Exec(fmt.Sprintf("SET app.user_id = '%s';", user.SteamID)) | ||
| 62 | if err != nil { | ||
| 63 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Session failed to start.")) | ||
| 64 | return | ||
| 65 | } | ||
| 59 | c.Set("user", user) | 66 | c.Set("user", user) |
| 60 | c.Set("mod", moderator) | 67 | c.Set("mod", moderator) |
| 61 | c.Next() | 68 | c.Next() |
| 62 | } else { | 69 | } else { |
| 63 | c.Next() | 70 | c.AbortWithStatusJSON(http.StatusOK, models.ErrorResponse("Token is invalid.")) |
| 64 | return | 71 | return |
| 65 | } | 72 | } |
| 66 | } | 73 | } |
diff --git a/backend/api/routes.go b/backend/api/routes.go index 81f1ec6..ecfb54b 100644 --- a/backend/api/routes.go +++ b/backend/api/routes.go | |||
| @@ -8,82 +8,54 @@ import ( | |||
| 8 | ginSwagger "github.com/swaggo/gin-swagger" | 8 | ginSwagger "github.com/swaggo/gin-swagger" |
| 9 | ) | 9 | ) |
| 10 | 10 | ||
| 11 | const ( | ||
| 12 | apiPath string = "/api" | ||
| 13 | v1Path string = "/v1" | ||
| 14 | swaggerPath string = "/swagger/*any" | ||
| 15 | indexPath string = "/" | ||
| 16 | tokenPath string = "/token" | ||
| 17 | loginPath string = "/login" | ||
| 18 | profilePath string = "/profile" | ||
| 19 | usersPath string = "/users/:userid" | ||
| 20 | demosPath string = "/demos" | ||
| 21 | mapSummaryPath string = "/maps/:mapid/summary" | ||
| 22 | mapImagePath string = "/maps/:mapid/image" | ||
| 23 | mapLeaderboardsPath string = "/maps/:mapid/leaderboards" | ||
| 24 | mapRecordPath string = "/maps/:mapid/record" | ||
| 25 | mapRecordIDPath string = "/maps/:mapid/record/:recordid" | ||
| 26 | mapDiscussionsPath string = "/maps/:mapid/discussions" | ||
| 27 | mapDiscussionIDPath string = "/maps/:mapid/discussions/:discussionid" | ||
| 28 | rankingsLPHUBPath string = "/rankings/lphub" | ||
| 29 | rankingsSteamPath string = "/rankings/steam" | ||
| 30 | searchPath string = "/search" | ||
| 31 | gamesPath string = "/games" | ||
| 32 | chaptersPath string = "/games/:gameid" | ||
| 33 | gameMapsPath string = "/games/:gameid/maps" | ||
| 34 | chapterMapsPath string = "/chapters/:chapterid" | ||
| 35 | scoreLogsPath string = "/logs/score" | ||
| 36 | modLogsPath string = "/logs/mod" | ||
| 37 | ) | ||
| 38 | |||
| 39 | func InitRoutes(router *gin.Engine) { | 11 | func InitRoutes(router *gin.Engine) { |
| 40 | api := router.Group(apiPath) | 12 | api := router.Group("/api") |
| 41 | { | 13 | { |
| 42 | v1 := api.Group(v1Path) | 14 | v1 := api.Group("/v1") |
| 43 | // Swagger | 15 | // Swagger |
| 44 | v1.GET(swaggerPath, ginSwagger.WrapHandler(swaggerfiles.Handler)) | 16 | v1.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler)) |
| 45 | v1.GET(indexPath, func(c *gin.Context) { | 17 | v1.GET("/", func(c *gin.Context) { |
| 46 | c.File("docs/index.html") | 18 | c.File("docs/index.html") |
| 47 | }) | 19 | }) |
| 48 | // Tokens, login | 20 | // Tokens, login |
| 49 | v1.GET(tokenPath, handlers.GetCookie) | 21 | v1.GET("/token", handlers.GetCookie) |
| 50 | v1.DELETE(tokenPath, handlers.DeleteCookie) | 22 | v1.DELETE("/token", handlers.DeleteCookie) |
| 51 | v1.GET(loginPath, handlers.Login) | 23 | v1.GET("/login", handlers.Login) |
| 52 | // Users, profiles | 24 | // Users, profiles |
| 53 | v1.GET(profilePath, CheckAuth, handlers.Profile) | 25 | v1.GET("/profile", IsAuthenticated, handlers.Profile) |
| 54 | v1.PUT(profilePath, CheckAuth, handlers.UpdateCountryCode) | 26 | v1.PUT("/profile", IsAuthenticated, handlers.UpdateCountryCode) |
| 55 | v1.POST(profilePath, CheckAuth, handlers.UpdateUser) | 27 | v1.POST("/profile", IsAuthenticated, handlers.UpdateUser) |
| 56 | v1.GET(usersPath, CheckAuth, handlers.FetchUser) | 28 | v1.GET("/users/:userid", IsAuthenticated, handlers.FetchUser) |
| 57 | // Maps | 29 | // Maps |
| 58 | // - Summary | 30 | // - Summary |
| 59 | v1.GET(mapSummaryPath, handlers.FetchMapSummary) | 31 | v1.GET("/maps/:mapid/summary", handlers.FetchMapSummary) |
| 60 | v1.POST(mapSummaryPath, CheckAuth, handlers.CreateMapSummary) | 32 | v1.POST("/maps/:mapid/summary", IsAuthenticated, handlers.CreateMapSummary) |
| 61 | v1.PUT(mapSummaryPath, CheckAuth, handlers.EditMapSummary) | 33 | v1.PUT("/maps/:mapid/summary", IsAuthenticated, handlers.EditMapSummary) |
| 62 | v1.DELETE(mapSummaryPath, CheckAuth, handlers.DeleteMapSummary) | 34 | v1.DELETE("/maps/:mapid/summary", IsAuthenticated, handlers.DeleteMapSummary) |
| 63 | v1.PUT(mapImagePath, CheckAuth, handlers.EditMapImage) | 35 | v1.PUT("/maps/:mapid/image", IsAuthenticated, handlers.EditMapImage) |
| 64 | // - Leaderboards | 36 | // - Leaderboards |
| 65 | v1.GET(mapLeaderboardsPath, handlers.FetchMapLeaderboards) | 37 | v1.GET("/maps/:mapid/leaderboards", handlers.FetchMapLeaderboards) |
| 66 | v1.POST(mapRecordPath, CheckAuth, handlers.CreateRecordWithDemo) | 38 | v1.POST("/maps/:mapid/record", IsAuthenticated, handlers.CreateRecordWithDemo) |
| 67 | v1.DELETE(mapRecordIDPath, CheckAuth, handlers.DeleteRecord) | 39 | v1.DELETE("/maps/:mapid/record/:recordid", IsAuthenticated, handlers.DeleteRecord) |
| 68 | v1.GET(demosPath, handlers.DownloadDemoWithID) | 40 | v1.GET("/demos", handlers.DownloadDemoWithID) |
| 69 | // - Discussions | 41 | // - Discussions |
| 70 | v1.GET(mapDiscussionsPath, handlers.FetchMapDiscussions) | 42 | v1.GET("/maps/:mapid/discussions", handlers.FetchMapDiscussions) |
| 71 | v1.GET(mapDiscussionIDPath, handlers.FetchMapDiscussion) | 43 | v1.GET("/maps/:mapid/discussions/:discussionid", handlers.FetchMapDiscussion) |
| 72 | v1.POST(mapDiscussionsPath, CheckAuth, handlers.CreateMapDiscussion) | 44 | v1.POST("/maps/:mapid/discussions", IsAuthenticated, handlers.CreateMapDiscussion) |
| 73 | v1.POST(mapDiscussionIDPath, CheckAuth, handlers.CreateMapDiscussionComment) | 45 | v1.POST("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.CreateMapDiscussionComment) |
| 74 | v1.PUT(mapDiscussionIDPath, CheckAuth, handlers.EditMapDiscussion) | 46 | v1.PUT("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.EditMapDiscussion) |
| 75 | v1.DELETE(mapDiscussionIDPath, CheckAuth, handlers.DeleteMapDiscussion) | 47 | v1.DELETE("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.DeleteMapDiscussion) |
| 76 | // Rankings, search | 48 | // Rankings, search |
| 77 | v1.GET(rankingsLPHUBPath, handlers.RankingsLPHUB) | 49 | v1.GET("/rankings/lphub", handlers.RankingsLPHUB) |
| 78 | v1.GET(rankingsSteamPath, handlers.RankingsSteam) | 50 | v1.GET("/rankings/steam", handlers.RankingsSteam) |
| 79 | v1.GET(searchPath, handlers.SearchWithQuery) | 51 | v1.GET("/search", handlers.SearchWithQuery) |
| 80 | // Games, chapters, maps | 52 | // Games, chapters, maps |
| 81 | v1.GET(gamesPath, handlers.FetchGames) | 53 | v1.GET("/games", handlers.FetchGames) |
| 82 | v1.GET(chaptersPath, handlers.FetchChapters) | 54 | v1.GET("/games/:gameid", handlers.FetchChapters) |
| 83 | v1.GET(chapterMapsPath, handlers.FetchChapterMaps) | 55 | v1.GET("/chapters/:chapterid", handlers.FetchChapterMaps) |
| 84 | v1.GET(gameMapsPath, handlers.FetchMaps) | 56 | v1.GET("/games/:gameid/maps", handlers.FetchMaps) |
| 85 | // Logs | 57 | // Logs |
| 86 | v1.GET(scoreLogsPath, handlers.ScoreLogs) | 58 | v1.GET("/logs/score", handlers.ScoreLogs) |
| 87 | v1.GET(modLogsPath, CheckAuth, handlers.ModLogs) | 59 | // v1.GET("/logs/mod", IsAuthenticated, handlers.ModLogs) |
| 88 | } | 60 | } |
| 89 | } | 61 | } |