diff --git a/cmd/api/middleware.go b/cmd/api/middleware.go new file mode 100644 index 0000000..bd20148 --- /dev/null +++ b/cmd/api/middleware.go @@ -0,0 +1,70 @@ +package main + +import ( + "net/http" + "strings" + + "github.com/gin-gonic/gin" + "github.com/golang-jwt/jwt/v4" +) + +func (app *application) AuthMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + authHeader := c.GetHeader("Authorization") + if authHeader == "" { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Auth header is required"}) + c.Abort() + return + } + + tokenString := strings.TrimPrefix(authHeader, "Bearer ") + if tokenString == authHeader { + c.JSON(http.StatusUnauthorized, gin.H{"error": "Bearer token is required"}) + c.Abort() + return + } + + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, jwt.ErrSignatureInvalid + } + return []byte(app.jwtSecret), nil + }) + + if err != nil || !token.Valid { + c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) + c.Abort() + return + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"}) + c.Abort() + return + } + + userIdVal, exists := claims["UserId"] + if !exists { + c.JSON(http.StatusUnauthorized, gin.H{"error": "UserId not found in token"}) + c.Abort() + return + } + + userIdFloat, ok := userIdVal.(float64) + if !ok { + c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid userId type in token"}) + c.Abort() + return + } + user, err := app.models.Users.Get(int(userIdFloat)) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized access!"}) + c.Abort() + return + } + + c.Set("user", user) + c.Next() + } +} diff --git a/cmd/api/routes.go b/cmd/api/routes.go index f5cdbfb..c334ac6 100644 --- a/cmd/api/routes.go +++ b/cmd/api/routes.go @@ -11,18 +11,22 @@ func (app *application) routes() http.Handler { v1 := r.Group("/api/v1") { - v1.POST("/events", app.createEvent) // create event - v1.GET("/events", app.getAllEvent) // get all events - v1.GET("/events/:id", app.getEvent) // get event by id - v1.PUT("/events/:id", app.updateEvent) // update event by id - v1.DELETE("/events/:id", app.deleteEvent) //delete the event by id - v1.POST("/events/:id/attendees/:userId", app.addAttendeeToEvent) // get attendee to event - v1.GET("/events/:id/attendees/", app.getAttendeesForEvent) // add attendee to event - v1.DELETE("/events/:id/attendees/:userId", app.deleteAttendeeFromEvent) //delete attendee from event - v1.GET("/attendees/:id/events", app.getEventsByAttendee) //get attendees for event - v1.POST("/auth/register", app.registerUser) // register user + v1.GET("/events", app.getAllEvent) // get all events + v1.GET("/events/:id", app.getEvent) // get event by id + v1.GET("/events/:id/attendees/", app.getAttendeesForEvent) // add attendee to event + v1.GET("/attendees/:id/events", app.getEventsByAttendee) // get attendees for event + v1.POST("/auth/register", app.registerUser) // register user v1.POST("/auth/login", app.login) + } + auth := v1.Group("/") + auth.Use(app.AuthMiddleware()) + { + auth.POST("/events", app.createEvent) // create event + auth.PUT("/events/:id", app.updateEvent) // update event by id + auth.DELETE("/events/:id", app.deleteEvent) // delete the event by id + auth.POST("/events/:id/attendees/:userId", app.addAttendeeToEvent) // get attendee to event + auth.DELETE("/events/:id/attendees/:userId", app.deleteAttendeeFromEvent) // delete attendee from event } return r