views:

42

answers:

1

Background: Completely new to MVC2. Has C# experience, but limited web experience.

I need more fine grained access than simply assigning a Role to a user. The user may have the role at 0+ points in a tree.

/
  /Europe
    /England
    /France
  /USA

For example, a user might be moderator of all forums under "Europe" and have access to posting news in France.

The two example controllers have actions as these:

ForumController:

public ActionResult DeletePost(int id) { ... }

NewsController:

[HttpPost]
public ActionResult Post(int treeID, ...) { ... }

How should I approach this? From what I gather Membership+RoleProvider cannot do this level of fine-grained control. Previously I have written custom user/role/auth system which supported all this, but it was incompatible with "the standard" controls such as LoginView.

The goal would be to have roles allowing access like so:

NewsAdmin

  • Add news

  • Edit news

  • Delete news

NewsPoster

  • Add news

Therefore, the Post action of News controler should check: Does user have "Add news"-access where he is trying to post?

I would really like to somehow specify this using attributes, so the actual action code could be cleaner and just assume that the caller has appropirate access.

Hope the question makes sense, and I can get some pointers on where to read.

(Oh, and I'm sure this question has been answered in some variant before. I just can't seem to find it. I won't mind single-link replies, if you feel they might be helpful to read)

A: 

I think you're being too quick to dismiss the role provider. If a user had a role called NewsAdmin_Europe_AddNews that would pretty much answer the question, wouldn't it?

Once you've made your authentication scheme work with the role provider, you need to tie that into MVC. Subtype AuthorizeAttribute and override AuthorizeCore. Warning: Your code here must be thread-safe and re-entrant. Call base.AuthorizeCore and then test for the specific role based on the URI/query (you won't get route values since this can be served from cache, bypassing MVC altogether).

This is some work, but will be more secure in the end than trying to reinvent membership.

Craig Stuntz
I considered using something similar to NewsAdmin_Europe_AddNews but that would prevent me from easily adding "DeleteComments" access to the NewsAdmin role. I'd need to create NewsAdmin_%s_DeleteComments in stead.
Thomas
They are different roles. Use one role per permission. The Role provider is built around this idea. To clarify: To you, "NewsAdmin" is a role. That's fine, but it's a different role than "NewsAdmin_Europe_DeleteComments", which is important to the provider. The provider's concept of a role includes both what you consider roles and what you consider "permissions".
Craig Stuntz
You are completely right. To me NewsAdmin is the role, and "add, edit, etc" are separate permissions that make up that role. Conceptually the Role provider concept seems, well, unsalable and unmaintainable. (I'm hopefully wrong, though). In a real-world application, how would one add "NewsAdmin_Europe_DeleteComments" role to all users who have a "NewsAdmin_Europe_*" role ?Another issue is, that it would clutter a UI to have those 4 roles for each leaf under Europe aswell, rather than just having "NewsAdmin" in X, Y and Z.Thanks for your time. I'll head off to read some
Thomas
I would probably use AzMan to map a hierarchy of roles+permissions onto role provider roles and then use the AzMan role provider in my app. It does exactly what you're asking.
Craig Stuntz