diff --git a/docs/en/Authorization.md b/docs/en/Authorization.md index bd607b716e..6b906fe194 100644 --- a/docs/en/Authorization.md +++ b/docs/en/Authorization.md @@ -265,37 +265,7 @@ myGroup.AddPermission("Book_Creation") #### Creating a Custom Permission Dependency -Any class implements the `IPermissionStateProvider` interface can disable a permission based on a custom condition. - -**Example:** - -````csharp -public class MyCustomPermissionStateProvider : IPermissionStateProvider -{ - public Task IsEnabledAsync(PermissionStateContext context) - { - // You can implement your own logic here. - return Task.FromResult( - context.Permission.Name.StartsWith("Acme.BookStore")); - } -} -```` - -Then you can add `MyCustomPermissionStateProvider` to any permission definition, using the `AddStateProviders` extension method: - -````csharp -myGroup.AddPermission("Book_Creation") - .AddStateProviders(new MyCustomPermissionStateProvider()); -```` - -Or you can globally add your custom provider to make it working for all permissions: - -````csharp -Configure(options => -{ - options.GlobalStateProviders.Add(); -}); -```` +`PermissionDefinition` supports state check, Please refer to [Simple State Checker's documentation](SimpleStateChecker.md) ## IAuthorizationService diff --git a/docs/en/SimpleStateChecker.md b/docs/en/SimpleStateChecker.md new file mode 100644 index 0000000000..584fef1592 --- /dev/null +++ b/docs/en/SimpleStateChecker.md @@ -0,0 +1,125 @@ +# Simple State Checker + +The simple state checking system can be used to enable/disable an object based on some dynamic conditions. For example, you can disable a menu item on the user interface, if the current user has not granted for a given permission. The simple state checking system provides a generic way to define and check such conditions. + +## Definition state checker. + +Any class can inherit `IHasSimpleStateCheckers` to support state checks. + +````csharp +public class MyObject : IHasSimpleStateCheckers +{ + public int Id { get; set; } + + public List> SimpleStateCheckers { get; } + + public MyObject() + { + SimpleStateCheckers = new List>(); + } +} +```` + +The `MyObject` class contains a collection of state checkers, you can add your custom checkers to it. + +````csharp +public class MyObjectStateChecker : ISimpleStateChecker +{ + public Task IsEnabledAsync(SimpleStateCheckerContext context) + { + var currentUser = context.ServiceProvider.GetRequiredService(); + return Task.FromResult(currentUser.IsInRole("Admin")); + } +} +```` + +````csharp +var myobj = new MyObject() +{ + Id = 100 +}; + +myobj.SimpleStateCheckers.Add(new MyObjectStateChecker()); +```` + +## Definition Global State Checkers + +`AbpSimpleStateCheckerOptions` is the options class that used to set the global state checkers for specific object. + +Example: Add global state for `MyObject`: + +````csharp +services.Configure>(options => +{ + options.GlobalSimpleStateCheckers.Add(); + //options.GlobalSimpleStateCheckers.Add<>(); //Add more global state checkers +}); +```` + +> Write this inside the `ConfigureServices` method of your module. + +## Check the state + +You can inject `ISimpleStateCheckerManager` service to check state. + +````csharp +bool enabled = await stateCheckerManager.IsEnabledAsync(myobj); +```` + +### Batch check the states + +If there are many instance items that require state checking, there may be performance problems. + +In this case, you can implement `ISimpleBatchStateChecker`. It can check multiple items at once. +You need to make sure that the same `ISimpleBatchStateChecker` instance is added to the `SimpleStateCheckers` of multiple instances. + +> `SimpleBatchStateCheckerBase` inherits the `ISimpleBatchStateChecker` interface and implements the `IsEnabledAsync` method of a single object by default. + +````csharp +public class MyObjectBatchStateChecker : SimpleBatchStateCheckerBase +{ + public override Task> IsEnabledAsync(SimpleBatchStateCheckerContext context) + { + var result = new SimpleStateCheckerResult(context.States); + + foreach (var myObject in context.States) + { + if (myObject.Id > 100) + { + result[myObject] = true; + } + } + + return Task.FromResult(result); + } +} +```` + +````csharp +var myobj1 = new MyObject() +{ + Id = 100 +}; +var myobj2 = new MyObject() +{ + Id = 99 +}; + +var myObjectBatchStateChecker = new MyObjectBatchStateChecker(); + +myobj1.SimpleStateCheckers.Add(myObjectBatchStateChecker); +myobj2.SimpleStateCheckers.Add(myObjectBatchStateChecker); + +SimpleStateCheckerResult stateCheckerResult = await stateCheckerManager.IsEnabledAsync(new []{ myobj1, myobj2 }); +```` + +## Built-in State Checkers + +The `PermissionDefinition`, `ApplicationMenuItem` and `ToolbarItem` objects have implemented state checks and have built-in general state checkers, you can directly use their extension methods. + +````csharp +RequireAuthenticated(); +RequirePermissions(bool requiresAll, params string[] permissions); +RequireFeatures(bool requiresAll, params string[] features); +RequireGlobalFeatures(bool requiresAll, params Type[] globalFeatures); +```` diff --git a/docs/en/UI/AspNetCore/Navigation-Menu.md b/docs/en/UI/AspNetCore/Navigation-Menu.md index 8480590f50..97e3d1a47d 100644 --- a/docs/en/UI/AspNetCore/Navigation-Menu.md +++ b/docs/en/UI/AspNetCore/Navigation-Menu.md @@ -104,7 +104,6 @@ There are more options of a menu item (the constructor of the `ApplicationMenuIt * `target` (`string`): Target of the menu item. Can be `null` (default), "\_*blank*", "\_*self*", "\_*parent*", "\_*top*" or a frame name for web applications. * `elementId` (`string`): Can be used to render the element with a specific HTML `id` attribute. * `cssClass` (`string`): Additional string classes for the menu item. -* `RequiredPermissionName` (`string`): The required permission name, this menu item will be removed if this permission is not granted. ### Authorization @@ -121,21 +120,21 @@ if (await context.IsGrantedAsync("MyPermissionName")) } ```` -For the authorization, you can use `RequiredPermissionName` as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. +For the authorization, you can use `RequirePermissions` extension method as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. ````csharp context.Menu.AddItem( new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"]) .AddItem(new ApplicationMenuItem( - name: "MyProject.Crm.Customers", - displayName: l["Menu:Customers"], - url: "/crm/customers", - requiredPermissionName: "MyProject.Crm.Customers") + name: "MyProject.Crm.Customers", + displayName: l["Menu:Customers"], + url: "/crm/customers") + .RequirePermissions("MyProject.Crm.Customers") ).AddItem(new ApplicationMenuItem( - name: "MyProject.Crm.Orders", - displayName: l["Menu:Orders"], - url: "/crm/orders", - requiredPermissionName: "MyProject.Crm.Orders") + name: "MyProject.Crm.Orders", + displayName: l["Menu:Orders"], + url: "/crm/orders") + .RequirePermissions("MyProject.Crm.Orders") ) ); ```` diff --git a/docs/en/UI/AspNetCore/Toolbars.md b/docs/en/UI/AspNetCore/Toolbars.md index 66ec7519b8..d82150b47e 100644 --- a/docs/en/UI/AspNetCore/Toolbars.md +++ b/docs/en/UI/AspNetCore/Toolbars.md @@ -61,10 +61,10 @@ if (await context.IsGrantedAsync("MyPermissionName")) } ```` -You can use `RequiredPermissionName` as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. +You can use `RequirePermissions` extension method as a shortcut. It is also more performant, ABP optimizes the permission check for all the items. ````csharp -context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(NotificationViewComponent), requiredPermissionName: "MyPermissionName")); +context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(NotificationViewComponent)).RequirePermissions("MyPermissionName")); ```` This class adds the `NotificationViewComponent` as the first item in the `Main` toolbar. diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8aae7ac96b..fe2de7ce3c 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -393,6 +393,10 @@ { "text": "Cancellation Token Provider", "path": "Cancellation-Token-Provider.md" + }, + { + "text": "Simple State Checker", + "path": "SimpleStateChecker.md" } ] },