Separate admin protected endpoints from non-admin endpoints

This commit is contained in:
2026-03-10 12:32:47 +00:00
parent 0b256863d6
commit bad44a6ddd
4 changed files with 34 additions and 35 deletions

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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"})

View File

@@ -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)