package middleware // Reference: P2E §2.9 — SuperAdmin middleware // Middleware that verifies the user is a super_admin (platform-level administrator). // Corresponds to Chatwoot's SuperAdmin access control for platform management endpoints. import ( "net/http" "strings" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/auth" "github.com/gochat/gochat/pkg/response" ) // SuperAdmin creates a middleware that verifies the current user has super_admin type. // Super admins are platform-level administrators that can manage all accounts, // platform apps, and system configuration. // // This checks the signed platform user type (not the account-level role). // // Usage: // // router.GET("/platform/accounts", SuperAdmin(), listAllAccounts) // router.POST("/platform/apps", SuperAdmin(), createPlatformApp) // router.GET("/platform/analytics", SuperAdmin(), viewPlatformAnalytics) func SuperAdmin() gin.HandlerFunc { return func(c *gin.Context) { userType, exists := c.Get("user_type") if !exists || !isSuperAdminType(userType) { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "Super admin access required. Your account does not have platform administration privileges.") return } // Mark the context as super_admin for downstream handlers c.Set("is_super_admin", true) c.Next() } } // SuperAdminOrAdministrator creates a middleware that allows either super_admin // users or administrators within the current account context. // Useful for endpoints that should be accessible to account admins and platform admins. // // Usage: // // router.DELETE("/accounts/:id", SuperAdminOrAdministrator(), deleteAccount) func SuperAdminOrAdministrator() gin.HandlerFunc { return func(c *gin.Context) { // Check super_admin first userType, exists := c.Get("user_type") if exists { if isSuperAdminType(userType) { c.Set("is_super_admin", true) c.Next() return } } // Check administrator role in policy context pc, exists := c.Get("policy_context") if !exists { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "Super admin or administrator access required") return } policyCtx, ok := pc.(*auth.PolicyContext) if !ok { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "Invalid policy context") return } if !policyCtx.IsAdministrator() { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "Super admin or administrator access required") return } c.Next() } } func isSuperAdminType(value any) bool { typeStr, ok := value.(string) if !ok { return false } normalized := strings.ToLower(strings.ReplaceAll(strings.TrimSpace(typeStr), "_", "")) return normalized == "superadmin" }