package middleware import ( "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" ) func performRBACRequest(t *testing.T, setup func(*gin.Context), middleware gin.HandlerFunc) *httptest.ResponseRecorder { t.Helper() gin.SetMode(gin.TestMode) recorder := httptest.NewRecorder() router := gin.New() if setup != nil { router.Use(setup) } router.Use(middleware) router.GET("/protected", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"code": 0}) }) req := httptest.NewRequest(http.MethodGet, "/protected", nil) router.ServeHTTP(recorder, req) return recorder } func TestRequirePermissionRejectsMissingPermission(t *testing.T) { recorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyPermissionCodes, []string{"users:read"}) c.Next() }, RequirePermission("users:write")) if recorder.Code != http.StatusForbidden { t.Fatalf("expected 403, got %d", recorder.Code) } } func TestRequirePermissionAllowsMatchingPermission(t *testing.T) { recorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyPermissionCodes, []string{"users:read"}) c.Next() }, RequirePermission("users:read")) if recorder.Code != http.StatusOK { t.Fatalf("expected 200, got %d", recorder.Code) } } func TestRequireAllPermissionsRequiresEveryCode(t *testing.T) { recorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyPermissionCodes, []string{"users:read"}) c.Next() }, RequireAllPermissions("users:read", "users:write")) if recorder.Code != http.StatusForbidden { t.Fatalf("expected 403, got %d", recorder.Code) } } func TestRequireAnyPermissionIsAliasOfRequirePermission(t *testing.T) { recorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyPermissionCodes, []string{"users:write"}) c.Next() }, RequireAnyPermission("users:read", "users:write")) if recorder.Code != http.StatusOK { t.Fatalf("expected 200, got %d", recorder.Code) } } func TestRequireRoleAndAdminOnly(t *testing.T) { roleRecorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyRoleCodes, []string{"auditor"}) c.Next() }, RequireRole("admin")) if roleRecorder.Code != http.StatusForbidden { t.Fatalf("expected role check to return 403, got %d", roleRecorder.Code) } adminRecorder := performRBACRequest(t, func(c *gin.Context) { c.Set(ContextKeyRoleCodes, []string{"admin"}) c.Next() }, AdminOnly()) if adminRecorder.Code != http.StatusOK { t.Fatalf("expected admin check to return 200, got %d", adminRecorder.Code) } } func TestRBACHelpersHandleMissingContextValues(t *testing.T) { gin.SetMode(gin.TestMode) recorder := httptest.NewRecorder() c, _ := gin.CreateTestContext(recorder) c.Request = httptest.NewRequest(http.MethodGet, "/protected", nil) if got := GetRoleCodes(c); got != nil { t.Fatalf("GetRoleCodes() = %#v, want nil", got) } if got := GetPermissionCodes(c); got != nil { t.Fatalf("GetPermissionCodes() = %#v, want nil", got) } if IsAdmin(c) { t.Fatal("IsAdmin() = true, want false") } c.Set(ContextKeyRoleCodes, []string{"admin"}) c.Set(ContextKeyPermissionCodes, []string{"users:read"}) if !IsAdmin(c) { t.Fatal("IsAdmin() = false, want true") } }