diff --git a/backend/handlers/handle_auth.go b/backend/handlers/handle_auth.go index d43974b..cd729a7 100644 --- a/backend/handlers/handle_auth.go +++ b/backend/handlers/handle_auth.go @@ -5,6 +5,7 @@ import ( "adam-french.co.uk/backend/models" "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" ) @@ -26,6 +27,28 @@ func (store *Store) AuthMiddlewear(ctx *gin.Context) { ctx.Next() } +func (store *Store) AdminMiddleware(ctx *gin.Context) { + claims, exists := ctx.Get("userClaims") + if !exists { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) + return + } + + mapClaims, ok := claims.(*jwt.MapClaims) + if !ok { + ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid claims"}) + return + } + + admin, ok := (*mapClaims)["admin"].(bool) + if !ok || !admin { + ctx.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "admin access required"}) + return + } + + ctx.Next() +} + func (store *Store) CheckToken(ctx *gin.Context) { access_token, err := ctx.Cookie("access_token") if err != nil { diff --git a/backend/handlers/handle_post.go b/backend/handlers/handle_post.go index 283ea51..d660400 100644 --- a/backend/handlers/handle_post.go +++ b/backend/handlers/handle_post.go @@ -67,11 +67,6 @@ func (store *Store) CreatePost(ctx *gin.Context) { } userID := uint(userIDF) - if !(*claims)["admin"].(bool) { - ctx.JSON(http.StatusForbidden, gin.H{"error": "you are not admin :("}) - return - } - // Create post post := models.Post{Title: input.Title, Content: input.Content, AuthorID: userID} tx := store.DB.Create(&post) diff --git a/backend/handlers/handle_user.go b/backend/handlers/handle_user.go index 27b53b4..99a1eba 100644 --- a/backend/handlers/handle_user.go +++ b/backend/handlers/handle_user.go @@ -19,21 +19,6 @@ type SetAdminInput struct { } func (store *Store) CreateUser(ctx *gin.Context) { - claimsVal, ok := ctx.Get("userClaims") - if !ok { - ctx.JSON(http.StatusUnauthorized, gin.H{"error": "user claims could not be found"}) - return - } - claims, ok := claimsVal.(*jwt.MapClaims) - if !ok { - ctx.JSON(http.StatusInternalServerError, gin.H{"error": "invalid claims"}) - return - } - if !(*claims)["admin"].(bool) { - ctx.JSON(http.StatusForbidden, gin.H{"error": "admin access required"}) - return - } - var input UserCredentials if err := ctx.ShouldBindBodyWithJSON(&input); err != nil { ctx.JSON(http.StatusBadRequest, err.Error()) @@ -116,11 +101,6 @@ func (store *Store) SetUserAdmin(ctx *gin.Context) { ctx.JSON(http.StatusInternalServerError, gin.H{"error": "invalid claims"}) return } - if !(*claims)["admin"].(bool) { - ctx.JSON(http.StatusForbidden, gin.H{"error": "admin access required"}) - return - } - callerIDF, ok := (*claims)["id"].(float64) if !ok { ctx.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user id in claims"}) diff --git a/backend/main.go b/backend/main.go index fb038bd..a7bd4e7 100644 --- a/backend/main.go +++ b/backend/main.go @@ -71,33 +71,34 @@ func main() { store := handlers.Store{DB: db, SpotifyAuth: spotifyAuth, SpotifyClient: spotifyClient, ClaudeClient: claudeClient, Auth: auth, Notes: notes} protected := r.Group("/", store.AuthMiddlewear) + admin := r.Group("/", store.AuthMiddlewear, store.AdminMiddleware) // FAVORITES r.GET("/favorites", store.GetFavorites) - protected.POST("/favorites", store.CreateFavorite) + admin.POST("/favorites", store.CreateFavorite) // ROWING r.GET("/rowing", store.GetRowing) - protected.POST("/rowing", store.CreateRowing) + admin.POST("/rowing", store.CreateRowing) // ACTIVITIES r.GET("/activity", store.GetActivity) - protected.POST("/activity", store.CreateActivity) + admin.POST("/activity", store.CreateActivity) // POSTS r.GET("/posts", store.GetPosts) - protected.POST("/posts", store.CreatePost) + admin.POST("/posts", store.CreatePost) r.GET("/posts/:id", store.GetPost) - protected.PUT("/posts/:id", store.UpdatePost) - protected.DELETE("/posts/:id", store.DeletePost) + admin.PUT("/posts/:id", store.UpdatePost) + admin.DELETE("/posts/:id", store.DeletePost) // USERS r.GET("/user/:id", store.GetUser) - protected.PUT("/user/:id", store.UpdateUser) - protected.DELETE("/user/:id", store.DeleteUser) + admin.PUT("/user/:id", store.UpdateUser) + admin.DELETE("/user/:id", store.DeleteUser) r.GET("/user", store.GetUsers) - protected.POST("/user", store.CreateUser) - protected.PATCH("/user/:id/admin", store.SetUserAdmin) + admin.POST("/user", store.CreateUser) + admin.PATCH("/user/:id/admin", store.SetUserAdmin) // AUTH r.POST("/auth/login", store.Login)