Implementing access control in controller commands

When creating a new controller command, the implementation class for the new command should extend the com.ibm.commerce.commands.ControllerCommandImpl class and its interface should extend the com.ibm.commerce.command.ControllerCommand interface.

About this task

For command-level access control policies for controller commands, the interface name of the command is specified as a resource. In order for a resource to be protected, it must implement the Protectable interface. According to the HCL Commerce programming model, this is accomplished by having the command's interface extend from com.ibm.commerce.command.ControllerCommand interface, and the command's implementation extend from com.ibm.commerce.command.ControllerCommandImpl. The ControllerCommand interface extends com.ibm.commerce.command.AccCommand interface, which in turn extends Protectable. The AccCommand interface is the minimum interface that a command should implement in order to be protected by command level access control.

If the command accesses resources that should be protected, create a private instance variable of type AccessVector to hold the resources. Then override the getResources method since the default implementation of this method returns a null value and therefore, no resource checking occurs.

In the new getResources method, you should return an array of resources or of resource-action pairs upon which the command can act. When an action is not explicitly specified, the action defaults to the interface name of the command being executed.

The action only needs to be specified when a command is doing both a read and write operation on different instances of the same resource class. For example, in the OrderCopy command, it can read from a source order and write to a destination order. In this case, a differentiation must be made between the two actions. This is accomplished by specifying the "-Read" action for the source order, and the "-Write" action for the destination order. When the access control framework detects these actions, it automatically prepends them with the interface name of the command before searching for applicable policies. In this case, the actions that will ultimately be used in the policies are the "com.ibm.commerce.order.commands.OrderCopyCmd-Read" and "com.ibm.commerce.order.commands.OrderCopyCmd-Write" actions.

Additionally, it is recommended that the method determines if it must instantiate the resource or if it can use the existing instance variable holding the reference to the resource. Checking to see if the resource object already exists can help to improve system performance. You can then use the same instance variable, if required, in the performExecute method of the new controller command.

To determine if you must override the getResources method, consider the following:

  • If you derive the resource based upon a predefined source of information, such as the command context, you would not need to override the getResources method. For example, the HCL Commerce UserRegistrationUpdate command derives the user's ID from the command context. In this case, the user is already authorized to act upon their own registration information, so the getResources method does not need to be overridden.
  • If your command is arbitrarily specifying a new resource (and this resource is of a private nature), you must override the getResources method. As an example, the HCL Commerce OrderItemUpdate command takes an order ID as an input parameter. In this case, when the order resource is instantiated, you do not know if the user has authority to take action upon that particular resource. In this case, the getResources method is overridden.

The following is an example of the getResources method:


private AccessVector resources = null;

public AccessVector getResources() throws ECException { 

 if (resources == null) {
  OrderAccessBean orderAB = new OrderAccessBean(); 
  orderAB.setInitKey_orderId(getOrderId().toString()); 
  resources = new AccessVector(orderAB); 
  }
 return resources;
}

As an example, consider the OrderItemUpdate command. The getResources method of this command returns one or more Order objects (which are protectable), when it is updating existing orders. Since the action is not specified, the action defaults to the interface for the OrderItemUpdate command.

Multiple resources may be returned by the getResources method. When this occurs, a policy that gives the user access to all of the specified resources must be found if the action is to be carried out. If a user had access to two out of three resources, the action may not proceed (three out of three are required).

If you need to perform additional parameter checking or resolving of parameters in the controller command, you can use the validateParameters() method. Use of this method is optional.

Additional resource level checking

It is not always possible to determine all of the resources that need to be protected, at the time the getResources method of the controller command is called.

If necessary, a task command can also implement a getResources method to return a list of resources, upon which the command can act.

Another way to invoke resource level checking is to make direct calls to the access control policy manager, using the checkIsAllowed(Object resource, String action) method. This method is available to any class that extends from the com.ibm.commerce.command.AbstractECTargetableCommand class. For example, the following classes extend from the AbstractECTargetableCommand class:

  • com.ibm.commerce.command.ControllerCommandImpl
  • com.ibm.commerce.command.DataBeanCommandImpl

The checkIsAllowed method is also available to classes that extend the com.ibm.commerce.command.AbstractECCommand class. For example, the following class extends from the AbstractECCommand class:

  • com.ibm.commerce.command.TaskCommandImpl

The following shows the signature of the checkIsAllowed method:


void checkIsAllowed(Object resource, String action) 
 throws ECException

This method throws an ECApplicationException if the current user is not allowed to perform the specified action on the specified resource. If access is granted, then the method simply returns.

Access control for "create" commands

Since the getResources method is called before the performExecute method in a command, a different approach must be taken for access control for resources that are not yet created. For example, if you have a WidgetAddCmd, the getResources method cannot return the resource that is about to be created. In this case, the getResources method should return the container of the new resource. For example, if an order is being created, this is done within the store resource; and a new user is created within an organization resource.

Default implementations for command-level access control

For command-level access control, the default implementation of the getOwner() method returns the memberId of the store owner, if the storeId is specified. If the storeId is not specified, the memberId of the root organization is returned (memberId = -2001).

The default implementation of the getResources() method returns null.

The default implementation of the validateParameters() does nothing.