Extending a MembershipUser

 

You are creating a blogging application where users each have a blog.  Blogs are clustered into categories of blogs.  A user can have roles in more than 1 blog.

 

Category A

    Blog A

        User 1 **

    Blog B

        User 2

Category B

    Blog C

        User 1 **

    Blog D

        User 3

 

** Note that User 1 has 2 blogs.

 

At runtime you want to be able to determine the following information about a user:

 

  •     Their username
  •     Their user id
  •     Whether they are a member of a given blog
  •     What role(s) they have in a particular blog

 

There's a complex issue here dealing with row-level security on data and, at runtime, being able to programmatically determine the permissions at that level.  At runtime, you want to have code which looks similar to this to determine whether to grant or deny access to a particular item:

 

    if( PermissionAPI.UserCanEdit( blogId ) ) {

        // access granted

    }

 

The question here is "where to hang your permission data so that you have access to it at runtime". 

 

Is there anything baked into the Roles API that you can override so that it handles not only an array of string roleNames but also complex type permissions or, is the intended usage in this scenario to implement your own custom MembershipUser class to add the rights to?

 

A workaround for using the Roles API by dynamically creating roles

 

The Roles API in ASP.NET 2.0 works with a string[] of roles.  For example, John Doe might have the following roles: "Administrator", "Editor", etc&

 

But, what if John has different roles on a per category or per group basis?  Like, John is an "Administrator" in Group A but is only an "Editor" in Group B.

 

The quick-n-dirty way around this might be to dynamically create custom role strings at the time that you are managing that users permissions.  In the previous example, you might dynamically create the following 2 role strings:

 

    GroupA$Administrator

    GroupB$Editor

 

Using this method would allow you to leverage the built in Roles.IsUserInRole(roleName) API logic to determine whether access should be denied or granted.

 

Sample implementation code for this method:

 

static bool UserCanEditBlog( blogId ) {

    return (Roles.IsUserInRole( blogId.ToString() + "$Editor" ) ||

        Roles.IsUserInRole( blogId.ToString() + "$Administrator" ) ;

}

 

 

Another method might be to extend the current user so that the permissions can be queried directly via the current Identity.  To do this you may have to create a custom MembershipProvider which will allow you to return custom MembershipUsers with the custom permission data tagged as an array of permissions to that user.

 

Using the Membership API to extend the user

 

// Create a class for the new custom user and extend it with our custom permission data

class BlogUser : MembershipUser {

 

       // this is a convenience thing because the SqlMembershipProvider uses MembershipUsers

      .ctor( MembershipUser baseUser )

      .ctor( MembershipUser baseUser, Dictionary<int, BlogPermission> permissions )  

     

      // the new custom property

      Dictionary<int, BlogPermission> _permissions ;

      public Dictionary<int, BlogPermission> Permissions { get{ return _permissions ; } }

}

 

 

 

// override each method to populate Permissions on the BlogUser class

class BlogSqlMembershipProvider : SqlMembershipProvider {

 

            public override MembershipUser CreateUser() {

 

          MembershipUser baseUser = base.CreateUser(...) ;

         

          // do stuff to get permission details

          BlogPermission[] perms = GetBlogPermissions() ;

 

          BlogMembershipUser blogUser = new BlogMembershipUser( baseUser, perms ) ;

          return blogUser ; 

     } 

}

 

Where BlogPermissions looks like this:

 

class BlogPermission {

    int BlogId

    string[] Roles

}

 

 

Sample implementation code for this method:

 

static bool UserCanEditBlog( blogId ) {

   BlogPermission perms = ((BlogUser)User).Permissions[blogId] as BlogPermission ;

 

   if( perms != null ) {

            return perms.Roles.Contains("Editor") ;

   }  

 

     return false ;

}

 

NOTE: I have a working prototype of this here:  http://projectdistributor.net/Projects/Project.aspx?projectId=73

4 Comments

Comments have been disabled for this content.