Merge pull request #8899 from abpframework/maliming/state-checker-document

Add Simple State Checker document.
pull/9048/head
Halil İbrahim Kalkan 4 years ago committed by GitHub
commit 49981e02f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -265,37 +265,7 @@ myGroup.AddPermission("Book_Creation")
#### Creating a Custom Permission Dependency #### Creating a Custom Permission Dependency
Any class implements the `IPermissionStateProvider` interface can disable a permission based on a custom condition. `PermissionDefinition` supports state check, Please refer to [Simple State Checker's documentation](SimpleStateChecker.md)
**Example:**
````csharp
public class MyCustomPermissionStateProvider : IPermissionStateProvider
{
public Task<bool> 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<AbpPermissionOptions>(options =>
{
options.GlobalStateProviders.Add<MyCustomPermissionStateProvider>();
});
````
## IAuthorizationService ## IAuthorizationService

@ -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<MyObject>
{
public int Id { get; set; }
public List<ISimpleStateChecker<MyObject>> SimpleStateCheckers { get; }
public MyObject()
{
SimpleStateCheckers = new List<ISimpleStateChecker<MyObject>>();
}
}
````
The `MyObject` class contains a collection of state checkers, you can add your custom checkers to it.
````csharp
public class MyObjectStateChecker : ISimpleStateChecker<MyObject>
{
public Task<bool> IsEnabledAsync(SimpleStateCheckerContext<MyObject> context)
{
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>();
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<AbpSimpleStateCheckerOptions<MyObject>>(options =>
{
options.GlobalSimpleStateCheckers.Add<MyGlobalObjectStateChecker>();
//options.GlobalSimpleStateCheckers.Add<>(); //Add more global state checkers
});
````
> Write this inside the `ConfigureServices` method of your module.
## Check the state
You can inject `ISimpleStateCheckerManager<MyObject>` 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<MyObject>
{
public override Task<SimpleStateCheckerResult<MyObject>> IsEnabledAsync(SimpleBatchStateCheckerContext<MyObject> context)
{
var result = new SimpleStateCheckerResult<MyObject>(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<MyObject> 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);
````

@ -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. * `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. * `elementId` (`string`): Can be used to render the element with a specific HTML `id` attribute.
* `cssClass` (`string`): Additional string classes for the menu item. * `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 ### 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 ````csharp
context.Menu.AddItem( context.Menu.AddItem(
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"]) new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"])
.AddItem(new ApplicationMenuItem( .AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Customers", name: "MyProject.Crm.Customers",
displayName: l["Menu:Customers"], displayName: l["Menu:Customers"],
url: "/crm/customers", url: "/crm/customers")
requiredPermissionName: "MyProject.Crm.Customers") .RequirePermissions("MyProject.Crm.Customers")
).AddItem(new ApplicationMenuItem( ).AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Orders", name: "MyProject.Crm.Orders",
displayName: l["Menu:Orders"], displayName: l["Menu:Orders"],
url: "/crm/orders", url: "/crm/orders")
requiredPermissionName: "MyProject.Crm.Orders") .RequirePermissions("MyProject.Crm.Orders")
) )
); );
```` ````

@ -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 ````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. This class adds the `NotificationViewComponent` as the first item in the `Main` toolbar.

@ -393,6 +393,10 @@
{ {
"text": "Cancellation Token Provider", "text": "Cancellation Token Provider",
"path": "Cancellation-Token-Provider.md" "path": "Cancellation-Token-Provider.md"
},
{
"text": "Simple State Checker",
"path": "SimpleStateChecker.md"
} }
] ]
}, },

Loading…
Cancel
Save