Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic role providing in asp.net mvc (Roles are not fixed It is keep updating)

I am aware simple role provider in which if i need to restrict particular action i have to simply write Authorize(Roles = "Admin") or if i need to restrict particular part of view i nned to write @if(User.IsInRole("Admin")).

But my question is that what if my roles are not fixed and it is stored in database and my super admin can able to edit and delete them.

My requirement is that superadmin can add,update,delete roles and also create different users and maintain the roles of those users.

I have done lot of googling and found something as follows

    [AttributeUsage (AttributeTargets.Method|AttributeTargets.Class,Inherited = true,AllowMultiple=true) ]
    public class CustomRole : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase context)
        {
            Respository db = new Respository();
            if (db.UserMasters.Where(x => x.user_name == context.User.Identity.Name).Count() > 0)
            {
                return true;
            }
            else { return false; }
        }
    }

Here i can use this code to authorize action method as follows

    [CustomRole]
    public ActionResult Details(int id = 0)
    {
        Employee employee = db.Employees.Find(id);
        if (employee == null)
        {
            return HttpNotFound();
        }
        return View(employee);
    }

Here my this action method is protected but what if i want to protect some part of view by this custom method. How to use this functionality to achieve functionality as User.IsInRole("Admin")?

like image 445
Rushabh Shah Avatar asked Jun 02 '14 05:06

Rushabh Shah


3 Answers

your requirement will get in 3 steps

1- Create all default roles, store it in database.i.e- roleid,rolename 2- When creating new user map userid with roleid. 3- also make one table for all permission which you have to give. 4- make seperate ui for admin to change the roles of each user. database will be like below image. enter image description here

and ui will be like this.

enter image description here

try this yousrelf..

like image 120
banny Avatar answered Nov 19 '22 05:11

banny


Fully answering your question might be out of scope for StackOverflow, since it would basically require writing most of an application for you, but here's the general idea.

Write a helper class similar to this:

public class ModuleHelper
{
    public static bool UserCanAccessModule(string moduleIdentifier)
    {
        bool canAccess = false;

        /* 
            Call into your service with current User.Name and module identifier (integer, GUID, whatever).
            Return result of whether user has the required role for the specified module
        */
        try
        {
            canAccess = service.CanUserAccessModule(User.Identity.Name, moduleIdentifier);
        }
        catch
        {
            // catching all exceptions, since this is a UI helper
        }       

        return canAccess;
    }

    // etcetera...
}

I'd suggest wrapping it in the root namespace of your application; otherwise, add a reference to this class's namespace in the system.web.webPages.razor section of the web.config in the Views folder. Then, you can do something like:

<div class="col-sm-3 col-md-2 sidebar">
    @if (ModuleHelper.UserCanAccessModule("moduleXYZ"))
    {
        @Html.Action("moduleXYZ")
    }
</div>

This obviously assumes a lot, but the idea isn't new or all that complicated in practice. The logic of the service is relatively simple:

  1. Look up the user
  2. Look up the "action" or "module"
  3. Look for intersection (if any) between the roles assigned to each.

No intersection means user doesn't have the required role.

like image 42
Tieson T. Avatar answered Nov 19 '22 06:11

Tieson T.


Tieson T. has a great answer to your question already, so what I'll provide here is an alternative method if you wanted to keep all of your authorization steps all in controllers.

Consider separating the different aspects (or restricted parts) of your main view into a partial view (or views) that perform the restricted functionality. Then, instead of using: @Html.RenderPartial("ViewName", Model) you can set up your partials to be returned from controller actions decorated with the ChildActionOnly Attribute by using the RenderAction Html Helper.

For example:

<div class="col-sm-3 col-md-2 sidebar">
    @Html.RenderAction("RestrictedContent")
</div>

Then in your controller class

public class RestrictedController : Controller {

    public RestrictedController() : base() {

    }

    [ChildActionOnly()]
    [CustomRole()]
    public ActionResult RestrictedContent() {
        return PartialView("RestrictedPartial");
    } // end action RestrictedContent

} // end class

The only consideration with this approach will be in your custom attribute to interrogate the the IsChildAction property to avoid rendering a redirect or whatever your attribute does in the case the user is not authorized since you'll probably want to just not render anything.

For Example (in your custom attribute class):

public override void OnAuthorization(AuthorizationContext filterContext) {
    if(filterContext.IsChildAction) {
        filterContext.Result = new EmptyResult(); // return an empty result instead of performing a redirect.
    } else {
        base.OnAuthorization(filterContext); // continue with custom authorization if it is not a child action
    } // end if/else
} // end method OnAuthorization

Phil Haack has an article describing the usage of the RenderAction method here: http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx/

Also, see here for an interesting discussion on the differences between Action and RenderAction. The difference between Html.Action and Html.RenderAction

like image 33
xDaevax Avatar answered Nov 19 '22 05:11

xDaevax