Need to enable/disable Commands depending on user identity/role/credentials? I present a practical solution that simplifies this common task.
The implementation takes advantage of the ObjectBuilder and is based on the use of a custom attribute -the CommandAuthorization attribute- in adition to a custom ObjectBuilder strategy. This strategy will ensure that during the initialization of the work item, all the commands that the user is not authorized to use will be disabled/made unavailable.
To check authorization on a command, the custom strategy uses a user-provided service which has to implement the interface ICommandAuthorizationService. This interface contains only one method:
that returns true if the current user is authorized to use the command, or false if it is not.
- Download the file CompositeUIExtensions.Security.zip and extract it to a desired folder.
- Open the solution named CompositeUIExtensions.Security.sln and build it. If you experience problems, check that the references to the CAB assemblies are correct.
- In your shell project and in any other project you want to add command-level security, add a reference to CompositeUIExtensions.Security.dll located in [folder] CompositeUIExtensions.SecuritybinDebug.
- In your shell application (e.g: FormShellApplication) override the AddBuilderStrategies method and insert the following code:protected override void AddBuilderStrategies(Microsoft.Practices.ObjectBuilder.Builder builder)
where CommandAuthorizationService is any class that implements ICommandAuthorizationService (you can use, of course, the services I provide as examples).
- Decorate work items declarations with the CommandAuthorization attribute where needed (use root work item for global command-level security). This attribute can be used in two different ways: with explicit command names or without them. If no command names are explicitly defined, the user must provide a service that enumerates the commands that require authorization.Using the attribute with explicit command names
Only the commands specified will be checked for authorization. The attribute supports the following parameters:
- string commandName: name of the command to check authorization for.
- bool hide: when authorization fails, if hide is set to true the invokers will be hidden, otherwise they will be disabled. The default value is false. Important: see Disabling/Hiding Invokers section below for this feature to work.
- Single command, do not hide invokers if authorization fails:[CommandAuthorization(“CommandName”)]
- Three commands, hide invokers if authorization fails:[CommandAuthorization(true, “CommandName1″, “CommandName2″,“CommandName3″)]
- Three commands, hide invokers only for the first one:[CommandAuthorization(“CommandName1″, true)]
Using the attribute without command names
If no command names are defined, the ICommandAuthorizationService provided by user has to also implement the ICommandsProvider interface which has the following method:
IDictionary<string, bool> GetCommands()
where the key of the IDictionary is the command name and the value is the hide flag.
Tip: Using the CommandAuthorization attribute in the root work item will enable authorization checking for all the commands in the application, in any module. This is a great option if you want to add command-level security to all modules in your application.
In order to disable/hide invokers (not just commands) when authorization fails, you have to override the BindCommand method of the command adapter you use. This cannot be done by the CommandAuthorizationStrategy because at the moment of building a work item, invokers are not yet added to commands.
Here I provide the method implementation for the ToolStripMenuItem adapter included in CAB. Open the CAB solution, get the file named ToolStripItemCommandAdapter.cs located in [CAB Source Folder] CompositeUI.WinForms and add the following code:
/// Called when the is registered with a .
/// The the adapter is being added to.
public override void BindCommand(Command command)
if (command.Status != CommandStatus.Enabled)
foreach (KeyValuePair<ToolStripItem, List<string>> invoker in Invokers)
invoker.Key.Enabled = (command.Status == CommandStatus.Enabled);
invoker.Key.Visible = (command.Status != CommandStatus.Unavailable);
Finally, rebuild the project.
If you are using other control rather than ToolStripMenuItem, you should override the BindCommand method of the corresponding command adapter.
|Picture 1: The sample application run by an administrator.||Picture 2: The same application run by an user.|
Inside the download package, I included two sample applications that show the benefits of using this solution: one that implements the ICommandAuthorizationService interface with a service based on a custom authentication/authorization system and another one that implements the interface with a service that takes advantage of Authorization Manager (AzMan). The solution files are Commands QuickStart.sln and Commands QuickStart AzMan.sln respectively.
Both applications are based on the CAB Commands Quickstart. Check them out!
Note 1: For the AzMan based solution, please copy the file AzManStore.xml to C:.
Note 2: To see a detail of the AzMan solution design and implementation, please check this post.
Was this solution useful to you? Any suggestions? Feel free to post a comment on this topic.