Open Closed

Permission checker #10088


User avatar
0
yazilim.ithinka created
  • Template: microservice
  • Created ABP Studio Version: 1.3.3
  • Current ABP Studio Version: 1.4.2
  • Multi-Tenancy: Yes
  • UI Framework: angular
  • Theme: leptonx
  • Theme Style: system
  • Theme Menu Placement: side
  • Run Install Libs: Yes
  • Database Provider: ef
  • Database Management System: postgresql
  • Mobile Framework: react-native
  • Public Website: Yes
  • Social Login: Yes
  • Include Tests: Yes
  • Dynamic Localization: Yes
  • Kubernetes Configuration: Yes
  • Grafana Dashboard: Yes
  • Use Local References: No
  • Aspire: Yes
  • Optional Modules:
    • GDPR
    • FileManagement
    • TextTemplateManagement
    • AuditLogging
    • OpenIddictAdmin
  • Selected Languages: English, Turkish
  • Default Language: English
  • Create Command: abp new CarbonAI -t microservice --ui-framework angular --mobile react-native --database-provider ef --database-management-system postgresql --theme leptonx --skip-migrator --public-website --without-cms-kit --aspire --dont-run-bundling -no-language-management -file-management

Hello,

When RequireFeatures is added to permissions; Host admin does not see the Management Service menu at all

Management Service pages where the customer is included in the package and visible

  • A package was created.
  • Category and CategoryType properties were added to the package.
  • A tenant was created.
  • A package was assigned to the tenant.
  • A tenant logged in. The menus assigned to the package were displayed in the Management Service menu.
  • A tenant was logged out.
  • A host admin was logged in.
  • A Management Service was not visible in the menu.

Is there a way for the Host admin to view the Management Service section in this scenario?

When we tried our checks with StateCheckers instead of RequireFeatures;

The code structure below appears to be for Categories, but it is managed with the same coding in the CategoryType structure, but the naming is different.

When we log in with Host Admin, we see two pages and can view data.

However, when we log in with a tenant;

You can access the Category page included in the package without any problems, but when you click on it, the CategoryType page appears even though there is no CategoryType in the package assigned to the tenant. The page is visible, but we do not want this page, which is not included in the package, to appear in the menu at all.

  • A package was created.
  • A category was added to the package.
  • A tenant was created.
  • A package was assigned to the tenant.
  • A tenant was logged in. All pages included and excluded from the package were visible. However, clicking on a page not included in the package resulted in a 403 permission-free page. The tenant should not have been able to view pages outside of the package. Note: Here, we saw that when the permissions related to the tenant's CategoryType were manually removed from the PermissionGrant table, the tenant was unable to view the page.
  • A tenant was logged out.
  • A host admin was logged in.
  • All pages under the Management Service were visible, and access was unproblematic.

In this scenario, it needs to be configured so that the Tenant cannot see pages that are not included in the package. Is there a way to do this?


2 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    1. Solution
    • Background

      • RequireFeatures on a permission definition hides that permission when the required feature is disabled for the current tenant. Host has no tenant context; if the feature you reference is not enabled for the Host side, all children (menu items bound to those permissions) disappear for Host admins.
      • StateCheckers allow custom enable/disable logic per permission (e.g., “bypass for host, check feature for tenants”), but they only affect the permission state. If your Angular menus are not also filtered by permission/feature, a menu item can still render and then fail with 403 when navigated.
      • In microservice + Angular, menu visibility depends on:
        • The permission attached to the menu item (requiredPolicy in Angular).
        • Feature checks (optional) you apply in the menu contributor.
        • The actual grant rows in PermissionGrants for the current user/role/tenant.
    • Part A: Host admin can still see “Management Service” when RequireFeatures is used

      1. Ensure features are enabled for Host if you want Host to see these permissions.
        • In the Feature Management UI, switch to Host side and enable the features required by your permissions (e.g., CarbonFeatures.Categories, CarbonFeatures.CategoryTypes, etc.). If you manage features programmatically, set default values for the host:
    public class CarbonFeatureDefinitionProvider : FeatureDefinitionProvider
         {
             public override void Define(IFeatureDefinitionContext context)
             {
                 var group = context.AddGroup("CarbonFeatures");
                 group.AddFeature("CarbonFeatures.Categories", defaultValue: "true"); // host-default
                 group.AddFeature("CarbonFeatures.Categories.Create", defaultValue: "true");
                 group.AddFeature("CarbonFeatures.Categories.Edit", defaultValue: "true");
                 group.AddFeature("CarbonFeatures.Categories.Delete", defaultValue: "true");
    
                 group.AddFeature("CarbonFeatures.CategoryTypes", defaultValue: "true");
                 group.AddFeature("CarbonFeatures.CategoryTypes.Create", defaultValue: "true");
                 group.AddFeature("CarbonFeatures.CategoryTypes.Edit", defaultValue: "true");
                 group.AddFeature("CarbonFeatures.CategoryTypes.Delete", defaultValue: "true");
             }
         }
    
    1. Alternatively, keep RequireFeatures for tenants, but bypass feature checks for host via StateCheckers:
    public sealed class HostBypassFeatureChecker : ISimpleStateChecker<PermissionDefinition>
         {
             public async Task<bool> IsEnabledAsync(SimpleStateCheckerContext<PermissionDefinition> context)
             {
                 var currentTenant = context.ServiceProvider.GetRequiredService<ICurrentTenant>();
                 if (!currentTenant.IsAvailable) // Host
                     return true;
    
                 var featureChecker = context.ServiceProvider.GetRequiredService<IFeatureChecker>();
                 // Map permission name to feature name as you need
                 var featureName = MapPermissionToFeature(context.State.Name);
                 return await featureChecker.IsEnabledAsync(featureName);
             }
    
             private static string MapPermissionToFeature(string permissionName)
             {
                 // Example mapping: adjust to your permission constants
                 if (permissionName.StartsWith(ManagementServicePermissions.Categories.Default))
                     return "CarbonFeatures.Categories";
                 if (permissionName.StartsWith(ManagementServicePermissions.CategoryTypes.Default))
                     return "CarbonFeatures.CategoryTypes";
                 return permissionName; // fallback
             }
         }
         // Apply to your permission definitions:
         var category = myGroup.AddPermission(ManagementServicePermissions.Categories.Default, L("Permission:Categories"));
         category.StateCheckers.Add(new HostBypassFeatureChecker());
    
     This approach keeps the Host menu visible without requiring Host features to be explicitly enabled.
    
    • Part B: Prevent tenants from seeing menu pages that are not included in their package
      • Root cause in your scenario: the Angular menu item appears because the permission used by the menu item is granted (or no permission was bound to the menu item). Clicking leads to 403 because the page or API requires a different permission that is not granted.
      • Fixes:
        1. Ensure each Angular route/menu item uses a permission that exactly matches your backend permission for that page. Do not use a “broader” parent permission if you want to hide the page when a sub-feature is disabled.
          • Angular route guard:
    {
               path: 'category-types',
               component: CategoryTypesComponent,
               canActivate: [PermissionGuard],
               data: { requiredPolicy: 'ManagementService.CategoryTypes' }
             }
    
       - Menu item:
    
    this.context.addItem({
               id: 'ManagementService.CategoryTypes',
               text: 'Category Types',
               icon: 'fa fa-list',
               order: 10,
               requiredPolicy: 'ManagementService.CategoryTypes'
             }, MANAGEMENT_MENU_NAME);
    
       - If you need feature-level hiding too, add a feature check in the menu contributor and skip adding the item when feature is disabled for the current tenant.
    2) Do not grant the permission in the tenant’s package if the page must be hidden. If you are generating grants dynamically, verify PermissionGrant table has no rows for the excluded pages. Your observation is correct: once the grants are removed, the menu is hidden provided you use requiredPolicy on the menu item.
    3) If you keep using StateCheckers (bypass for host, check feature for tenant), keep menu items bound to those exact permissions. Since ABP UI reads permission states, menu entries disappear for tenants when the feature is disabled.
    4) For microservice solutions with dynamic permissions: verify the PermissionDefinition names you bind in Angular match the definitions pushed by that microservice. A mismatch leads to menu items always visible due to missing policy binding.
    
    • Part C: Known edge cases and recommendations

      • Use RequireFeatures on permission definitions only if you also want menus and API access to follow the same feature switches. If host must always see, either enable those features for Host or switch to StateCheckers that bypass for host.
      • In Angular, always set both:
        • canActivate PermissionGuard on routes.
        • requiredPolicy on menu items. This guarantees no “visible but 403 on click” inconsistency.
      • If you need a package concept: treat the package assignment flow as feature/permission provisioning. When a package is assigned to a tenant, grant only the permissions of included pages. When a package excludes a page, ensure those permissions are not granted. Use your provisioning service to synchronize PermissionGrant records accordingly.
    • Minimal example putting all together

      • Permission definitions:
    public class ManagementServicePermissionDefinitionProvider : PermissionDefinitionProvider
      {
          public override void Define(IPermissionDefinitionContext context)
          {
              var group = context.AddGroup("ManagementService");
    
              var categories = group.AddPermission("ManagementService.Categories", L("Permission:Categories"));
              categories.StateCheckers.Add(new HostBypassFeatureChecker()); // host bypass
              categories.RequireFeatures("CarbonFeatures.Categories");      // tenant feature
    
              var categoryTypes = group.AddPermission("ManagementService.CategoryTypes", L("Permission:CategoryTypes"));
              categoryTypes.StateCheckers.Add(new HostBypassFeatureChecker());
              categoryTypes.RequireFeatures("CarbonFeatures.CategoryTypes");
          }
      }
    
    • Angular route and menu:
    // route
      { path: 'categories', component: CategoriesComponent, canActivate: [PermissionGuard], data: { requiredPolicy: 'ManagementService.Categories' } }
      { path: 'category-types', component: CategoryTypesComponent, canActivate: [PermissionGuard], data: { requiredPolicy: 'ManagementService.CategoryTypes' } }
    
      // menu
      this.context.addItem({
        id: 'ManagementService',
        text: 'ManagementService',
        icon: 'fa fa-book',
        order: 30
      });
    
      this.context.addItem({
        id: 'ManagementService.Categories',
        text: 'Categories',
        parentId: 'ManagementService',
        requiredPolicy: 'ManagementService.Categories'
      });
    
      this.context.addItem({
        id: 'ManagementService.CategoryTypes',
        text: 'Category Types',
        parentId: 'ManagementService',
        requiredPolicy: 'ManagementService.CategoryTypes'
      });
    
    • Feature defaults for host (optional) if you prefer RequireFeatures without StateChecker bypass:
    public class CarbonFeatureDefinitionProvider : FeatureDefinitionProvider
      {
          public override void Define(IFeatureDefinitionContext context)
          {
              var g = context.AddGroup("CarbonFeatures");
              g.AddFeature("CarbonFeatures.Categories", defaultValue: "true");
              g.AddFeature("CarbonFeatures.CategoryTypes", defaultValue: "true");
          }
      }
    

    This approach will:

    • Make Host admin always see and access Management Service (via host-bypass or enabling host features).
    • Make tenants see only the pages included in the package because only those permissions will be granted and the menu items require those permissions; excluded pages won’t appear at all, avoiding the 403-on-click experience.
    1. Sources
    • ABP permissions and multi-tenancy concepts (permission side, feature checks, state checkers, Angular requiredPolicy) are explained in the official docs:
      • No verified source available for direct links due to current site accessibility. The approach aligns with ABP’s documented Permission System, Feature System, Permission State Checkers, Angular PermissionGuard, and Multi-Tenancy conventions.

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    The features may not be enabled by default, depending on your definition code.

    Please enable them for the host in the Settings => Feature management page.

    Thanks.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on November 07, 2025, 08:20