package middleware import ( "net/http" "project-dashboard/api/utils" "project-dashboard/models" "strings" "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" ) type Claims struct { UserID uint `json:"user_id"` Email string `json:"email"` Role string `json:"role"` jwt.StandardClaims } var jwtSecret = []byte("your-secret-key") // In production, use environment variable // GenerateToken generates a JWT token for the user func GenerateToken(user *models.User) (string, error) { claims := Claims{ UserID: user.ID, Email: user.Email, Role: user.Role, StandardClaims: jwt.StandardClaims{ ExpiresAt: 15000, // 24 hours Issuer: "project-dashboard", }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(jwtSecret) } // AuthMiddleware validates JWT token func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { utils.ErrorResponse(c, http.StatusUnauthorized, "Authorization header required") c.Abort() return } tokenString := strings.TrimPrefix(authHeader, "Bearer ") if tokenString == authHeader { utils.ErrorResponse(c, http.StatusUnauthorized, "Invalid authorization header format") c.Abort() return } claims := &Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return jwtSecret, nil }) if err != nil || !token.Valid { utils.ErrorResponse(c, http.StatusUnauthorized, "Invalid token") c.Abort() return } // Get user from database var user models.User if err := models.GetDB().First(&user, claims.UserID).Error; err != nil { utils.ErrorResponse(c, http.StatusUnauthorized, "User not found") c.Abort() return } c.Set("user", &user) c.Set("user_id", user.ID) c.Next() } } // AdminMiddleware ensures user has admin role func AdminMiddleware() gin.HandlerFunc { return func(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") c.Abort() return } userObj := user.(*models.User) if !userObj.IsAdmin() { utils.ErrorResponse(c, http.StatusForbidden, "Admin access required") c.Abort() return } c.Next() } } // ManagerMiddleware ensures user has manager role or higher func ManagerMiddleware() gin.HandlerFunc { return func(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") c.Abort() return } userObj := user.(*models.User) if !userObj.IsManager() { utils.ErrorResponse(c, http.StatusForbidden, "Manager access required") c.Abort() return } c.Next() } } // ProjectAccessMiddleware ensures user has access to the project func ProjectAccessMiddleware() gin.HandlerFunc { return func(c *gin.Context) { user, exists := c.Get("user") if !exists { utils.ErrorResponse(c, http.StatusUnauthorized, "User not authenticated") c.Abort() return } userObj := user.(*models.User) projectID := c.Param("project_id") if projectID == "" { utils.ErrorResponse(c, http.StatusBadRequest, "Project ID required") c.Abort() return } var project models.Project if err := models.GetDB().Preload("Members").First(&project, projectID).Error; err != nil { utils.ErrorResponse(c, http.StatusNotFound, "Project not found") c.Abort() return } // Check if user is owner or member if !project.IsOwner(userObj.ID) && !project.HasMember(userObj.ID) { utils.ErrorResponse(c, http.StatusForbidden, "Access denied to project") c.Abort() return } c.Set("project", &project) c.Next() } }