views:

336

answers:

2

Hi all,

I would really appreciate some feedback on what I am trying to achieve:

The problem:

  1. I would like to authorize a user of my application to a single action on the controller. For e.g.: a user can perform the "save" action on my controller class if he has the required authorization.
  2. In the project I am working on, the creation of roles & their authorization is done by the client deployment team & not in my control. So, I program to a "control point" which can be assigned to role/user, while my application needs to only check that control point.
  3. How do I get a control point concept into ASP.Net MVC? More specifically, how do I enable/disable buttons on the View based on the user permission on the controller?

My solution:

  1. Ref.: http://weblogs.asp.net/fredriknormen/archive/2008/03/12/asp-net-mvc-framework-2-interception-and-creating-a-role-action-filter.aspx - as a starting point
  2. Instead of creating a role filter as explained in the link above, I would have a ControlPointFilter class which would get the model & do the authorization check.
  3. The trouble I have is in the View class & I am currently passing the control point collection to which the user has access in the ViewData[] collection.
  4. In the View class, I am checking if the related control point is present in the ViewData collection (which I don't like - want to keep the code to a minimum in the View class)
  5. The other issue is - while the actual control point name is being set in the attribute to the controller class, where/how can I pass these attributes to the view & yet keep the view clean?

Hope that helps & appreciate your time/effort to answer this!

Sunny

A: 

Hmm, could you not simply create a templating system, to assign roles to users? I.e. create a user template "Power User" that has the roles "CustomerService" and "ConfigurationEditor", and then use the role system as pr usual (i.e. Roles.IsUserInRole(username, rolename))?

For actions, you then use

[Authorized(Roles="CustomerService,CustomerServiceAdmin")]
public ActionResult Edit(...)
{
}

For views, you use

<% if (Roles.IsUserInRole(Context.User.Name, "CustomerService")) %>
Soraz
Sunny
+1  A: 

One possible solution to this is to translate control points into view attributes in your controller actions (perhaps these are the same things, though, it's not clear from your question). The idea would be that your control point would translate into meaningful view directions such as "AllowEdit", "AllowSave", "AllowDetailedView", etc. These would become entries in ViewData.

Use a base controller class to extend Controller and give it a ControlPoint collection. Have your filter populate this collection in the controller. Have the base controller OnActionExecuted method use this collection and, in the case of a ViewResult, populate the ViewData with the appropriate values for the collection of view directives. Individual controller actions could also use the ControlPoint collection to determine whether they need to provide data for individual views based on whether the view will render extra data or not.

In your view, rely not on the control points themselves but the view directions determined by the base controller. This way you've decoupled the views from the control point logic. Views only operate on view data in ways that are meaningful to the view, not on permission-based data that have meaning in the context of the application. The view won't care how or why the particular directive gets set, it only needs to render appropriately based on the value of the directive.

tvanfosson
Hi tvanfosson - this solution looks good while the same would already have been put in as attribute to the action method (or should I NOT be using an attribute in this case?)Sunny
Sunny
If you derive from AuthorizeAttribute, the AuthorizationContext that's a parameter to the OnAuthorize method will contain a reference to the Controller. Cast it to the base controller class (using "as" and check for null) and then you can access it's properties. Your collection will need to be public.
tvanfosson