Getting AspNet Users RoleId for Comparison In permissions

只谈情不闲聊 提交于 2020-03-05 00:24:28

问题


I have a area where the RoleId is kept as a string in the permissions table. I am doing a comparison on the Id to pull all permissions for the Role. I am getting the current Logged in user RoleId like this.

 var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
 string roleid = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);

It does not like the usage of string. I am getting

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<string>' to 'string'

Here is where i am doing the comparison, Note the permission can have either UserId or RoleId, I do not have a problem for the UserId with this setup.

var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));

Is there a different way to get the RoleId or maybe different verbiage to do the compare?

Thanks

Update: Added Controller below. Sorry it is long..

   protected override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        try
        {
            //int roleid = int.Parse(Env.GetUserInfo("roleid"));
            //int userid = int.Parse(Env.GetUserInfo("userid"));
            string userid = User.Identity.GetUserId();
            //string userid = Env.GetUserInfo("userid");
            //string roleid = Env.GetUserInfo("roleid");
            var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            // Select will return collection as opposed to scalar/single value. Pay attention to datatype here. 
            IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
            //string roleid = roles;
            var descriptor = context.ActionDescriptor;
            var actionName = descriptor.ActionName.ToLower();
            var controllerName = descriptor.ControllerDescriptor.ControllerName.ToLower();
            var controller = descriptor.ControllerDescriptor.ControllerName;

            var GetOrPost = context.HttpContext.Request.HttpMethod.ToString();
            var checkAreaName = context.HttpContext.Request.RequestContext.RouteData.DataTokens["area"];
            string AreaName = "";
            if (checkAreaName != null)
            {
                AreaName = checkAreaName.ToString().ToLower() + "/";
            }

            var cacheItemKey = "AllMenuBar";

            var global = HttpRuntime.Cache.Get(cacheItemKey);

            if (GetOrPost == "POST")
            {
                // Added index to string 02/03/2020
                // Added add to actonName settings 02/08/2020
                ///if menupermission create,edit,delete then update value "true" in IsMenuChange file
                if (controllerName == "menupermission" && (actionName == "add" || actionName == "index" || actionName == "create" || actionName == "edit" || actionName == "delete" || actionName == "multiviewindex"))
                {
                    global = MenuBarCache(cacheItemKey, global, "shortcache");
                }
            }

            if (global == null)//if cashe is null
            {
                global = MenuBarCache(cacheItemKey, global, "60mincache");//make cache from db
            }


            var menuaccess = (MenuOfRole[])global;

            if (GetOrPost == "GET")
            {
                if (actionName == "add" || actionName == "index" || actionName == "create" || actionName == "edit" || actionName == "delete" || actionName == "multiviewindex")
                {
                    // Old Impementation May be removed at Cleanup if not used - 02/10/2020
                    //ViewBag.Add = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsAdd));
                    //ViewBag.Read = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsRead));
                    //ViewBag.Create = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsCreate));
                    //ViewBag.Edit = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsUpdate));
                    //ViewBag.Delete = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsDelete))();

                    // Stack Overflow corrections - 02/10/2020
                    ViewBag.Add = menuaccess.Any(i => i.MenuURL == controllerName && i.IsAdd);
                    ViewBag.Read = menuaccess.Any(i => i.MenuURL == controllerName && i.IsRead);
                    ViewBag.Create = menuaccess.Any(i => i.MenuURL == controllerName && i.IsCreate);                        
                    ViewBag.Edit = menuaccess.Any(i => i.MenuURL == controllerName && i.IsUpdate);
                    ViewBag.Delete = menuaccess.Any(i => i.MenuURL == controllerName && i.IsDelete);
                    ViewBag.Visable = menuaccess.Any(i => i.MenuURL == controllerName && i.IsVisable);
                }
            }

            string menuUrl = AreaName + controllerName + "/" + actionName;

            if (IsActionNameEqualToCrudPageName(actionName))
            {
                menuUrl = AreaName + controllerName;
            }


            var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);
            ///checkUrl: check if menu url Exists in MenuPermission if not exists then will be run
            if (checkUrl != null)
            {
                // Changed below line to use string instead of int..  01/26/2020
                //var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));
                // Added change to use roles as collection.
                var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
                ///check menu  && roleid && userid
                if (checkControllerActionRoleUserId != null)
                {
                    if (IsActionNameEqualToCrudPageName(actionName))
                    {
                        CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
                    }
                    else
                    {
                    if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
                        {
                            UnAuthoRedirect(context);

                        }
                    }
                }
                else
                {

                    var checkControllerActionRole = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == null);
                    if (checkControllerActionRole != null)
                    {

                        if (IsActionNameEqualToCrudPageName(actionName))
                        {
                            CheckAccessOfPageAction(context, actionName, checkControllerActionRole);
                        }
                        else
                        {
                            if (checkControllerActionRole.IsRead == false || checkControllerActionRole.IsDelete == false || checkControllerActionRole.IsCreate == false || checkControllerActionRole.IsUpdate == false)//if userid !=null && Check Crud
                            {
                                UnAuthoRedirect(context);
                            }
                        }
                    }
                    else
                    {
                        if (IsThisAjaxRequest() == false)//if userid !=null && Check Crud
                        {
                            UnAuthoRedirect(context);
                        }

                    }


                }


            }


        }
        catch (Exception)
        { }
    }

UPDATE: After implementing What @Sam suggested below I also needed to find a way to not give access to users that are not in the permissions table. To avoid redundancy. If a user does not have access to something then i shouldn't need to add it to permissions to make sure they do not have access. I added to a section of below code to redirect to the Dashboard if a user lands on a page they do not have access to.

var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId)
&& (i.UserId == userid || i.UserId == null) || controllerName == "dashboard"// @Sam: This is how we can combine
    );
    ///check menu  && roleid && userid
    if (checkControllerActionRoleUserId != null)
      {
        if (IsActionNameEqualToCrudPageName(actionName))
          {
            CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
          }
          else
          {
            if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
             {
                UnAuthoRedirect(context);

             }
         }
      } 
      else
      {
        UnAuthorizedArea(context);
      }   

回答1:


There are couple of issues in your code. After fixing the current error you will get more errors:

  1. You are assigning collection of strings to string (via string roleid). Currently you are getting this error. After fixing this error below errors will come.

The reason why you are getting error is because:

  • The below statement returns collection of roles (roleId collection to be precise) of logged in user as opposed to single role id.

    string roleid = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);`
    
  • And then you are trying to assign this roleid collection to scalar property i.RoleId (via i.RoleId = roleid) in the next statement

    var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl &&  String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));`
    
    1. Using assignment operator = instead of == for comparison. So, you are trying to assign roleid to i.RoleId which is not allowed.

    2. Using assignment operator = instead of == for comparison. So, you are trying to assign userid to i.UserId which is not allowed.

Fix: Please modify your roleId section as below:

var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
// Select will return collection as opposed to scalar/single value. Pay attention to datatype here. 
IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId); 

(OR)

//You can use var in case you do not know the data types of result.
var currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId); 

currentUserRoles will contain all the roles of current logged in user. Now use that collection as below (please notice the condition currentUserRoles.Contains(i.RoleId). I also fixed condition around userid.):

var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl 
      && currentUserRoles.Contains(i.RoleId) && i.UserId == userid);

Alternatively, above statement can be split using Where and FirstOrDefault as follows:

// Where statement returns collection of menuaccess items meeting all three conditions
var filteredMenuAccessCollection = menuaccess.Where(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
// FirstOrDefault will return the first menuaccess item from filteredMenuAccessCollection
var checkControllerActionRoleUserId = filteredMenuAccessCollection.FirstOrDefault();

The above can further be re-written as follows:

var mathingMenuUrlMenuAccessCollection = menuaccess.Where(i => i.MenuURL == menuUrl); // return menuaccess items matching given menuurl
var mathingMenuUrlAndRolesMenuAccessCollection = mathingMenuUrlMenuAccessCollection.Where(i => currentUserRoles.Contains(i.RoleId)); // return menuaccess items matching roles in currentUserRoles
var filteredMenuAccessCollection = mathingMenuUrlAndRolesMenuAccessCollection.Where(i => i.UserId == userid); // return menuaccess items matching given userid
// FirstOrDefault will return the first menuaccess item from filteredMenuAccessCollection
var checkControllerActionRoleUserId = filteredMenuAccessCollection.FirstOrDefault();

To summarize, All 3 condition have to be satisfied to get item from menuaccess collection otherwise null will be returning. The order of conditions evaluation is

  • first it tries to find matching menuUrl items from menuaccess collection.
  • Then tries to find a menuaccess item where RoleId is contained in currentUserRoles collection.
  • Then it tries to find matching userid items from menuaccess collection.

If there are multiple menuaccess items meeting the above 3 conditions then it will return the First item from the menuaccess colletion since we are using FirstOrDefault.

Update: Simplified version of OnActionExecuting:

protected override void OnActionExecuting(ActionExecutingContext context)
{
    base.OnActionExecuting(context);
    try
    {
        //int roleid = int.Parse(Env.GetUserInfo("roleid"));
        //int userid = int.Parse(Env.GetUserInfo("userid"));
        string userid = User.Identity.GetUserId();
        //string userid = Env.GetUserInfo("userid");
        //string roleid = Env.GetUserInfo("roleid");
        var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        // Select will return collection as opposed to scalar/single value. Pay attention to datatype here. 
        IEnumerable<string> currentUserRoles = userManager.FindById(User.Identity.GetUserId()).Roles.Select(r => r.RoleId);
        //string roleid = roles;
        // @Sam: Added this variable
        var actionNamesToCompare = new List<string>{"add", "index", "create", "edit", "delete", "multiviewindex"};
        var descriptor = context.ActionDescriptor;
        var actionName = descriptor.ActionName.ToLower();
        var controllerName = descriptor.ControllerDescriptor.ControllerName.ToLower();
        var controller = descriptor.ControllerDescriptor.ControllerName;

        var GetOrPost = context.HttpContext.Request.HttpMethod.ToString();
        var checkAreaName = context.HttpContext.Request.RequestContext.RouteData.DataTokens["area"];
        string AreaName = "";
        if (checkAreaName != null)
        {
            AreaName = checkAreaName.ToString().ToLower() + "/";
        }

        var cacheItemKey = "AllMenuBar";

        var global = HttpRuntime.Cache.Get(cacheItemKey);

        if (GetOrPost == "POST")
        {
            // Added index to string 02/03/2020
            // Added add to actonName settings 02/08/2020
            ///if menupermission create,edit,delete then update value "true" in IsMenuChange file
            if (controllerName == "menupermission" && actionNamesToCompare.Contains(actionName))
            {
                global = MenuBarCache(cacheItemKey, global, "shortcache");
            }
        }

        if (global == null)//if cashe is null
        {
            global = MenuBarCache(cacheItemKey, global, "60mincache");//make cache from db
        }


        var menuaccess = (MenuOfRole[])global;

        if (GetOrPost == "GET")
        {
            if (actionNamesToCompare.Contains(actionName))
            {
                // Old Impementation May be removed at Cleanup if not used - 02/10/2020
                //ViewBag.Add = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsAdd));
                //ViewBag.Read = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsRead));
                //ViewBag.Create = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsCreate));
                //ViewBag.Edit = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsUpdate));
                //ViewBag.Delete = menuaccess.Where(i => i.MenuURL == controllerName).Select(i => (i.IsDelete))();

                // Stack Overflow corrections - 02/10/2020
                ViewBag.Add = menuaccess.Any(i => i.MenuURL == controllerName && i.IsAdd);
                ViewBag.Read = menuaccess.Any(i => i.MenuURL == controllerName && i.IsRead);
                ViewBag.Create = menuaccess.Any(i => i.MenuURL == controllerName && i.IsCreate);                        
                ViewBag.Edit = menuaccess.Any(i => i.MenuURL == controllerName && i.IsUpdate);
                ViewBag.Delete = menuaccess.Any(i => i.MenuURL == controllerName && i.IsDelete);
                ViewBag.Visable = menuaccess.Any(i => i.MenuURL == controllerName && i.IsVisable);
            }
        }

        // @sam: you can combine menuUrl evaluation like this using ternary operator.
        var menuUrl = IsActionNameEqualToCrudPageName(actionName) ? AreaName + controllerName
                      : AreaName + controllerName + "/" + actionName;

        // var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);

        // @sam: No need of this if statement
        // var checkUrl = menuaccess.FirstOrDefault(i => (i.MenuURL == AreaName + controllerName + "/" + actionName) || i.MenuURL == menuUrl);
        ///checkUrl: check if menu url Exists in MenuPermission if not exists then will be run
        /*if (checkUrl != null)
        {
            // Changed below line to use string instead of int..  01/26/2020
            //var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && String.IsNullOrEmpty(i.RoleId = roleid) && String.IsNullOrEmpty(i.UserId = userid));
            // Added change to use roles as collection.
            // @Sam: Since both if and else are doing same of operations, 
            //       the below if-else can be comibined as follows:

            /*var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl  &&currentUserRoles.Contains(i.RoleId) && i.UserId == userid);
            ///check menu  && roleid && userid
            if (checkControllerActionRoleUserId != null)
            {
                if (IsActionNameEqualToCrudPageName(actionName))
                {
                    CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
                }
                else
                {
                if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
                    {
                        UnAuthoRedirect(context);

                    }
                }
            }
            else
            {
                var checkControllerActionRole = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl && currentUserRoles.Contains(i.RoleId) && i.UserId == null);
                if (checkControllerActionRole != null)
                {

                    if (IsActionNameEqualToCrudPageName(actionName))
                    {
                        CheckAccessOfPageAction(context, actionName, checkControllerActionRole);
                    }
                    else
                    {
                        if (checkControllerActionRole.IsRead == false || checkControllerActionRole.IsDelete == false || checkControllerActionRole.IsCreate == false || checkControllerActionRole.IsUpdate == false)//if userid !=null && Check Crud
                        {
                            UnAuthoRedirect(context);
                        }
                    }
                }
                else
                {
                    if (IsThisAjaxRequest() == false)//if userid !=null && Check Crud
                    {
                        UnAuthoRedirect(context);
                    }

                }
            }//
        } */
        var checkControllerActionRoleUserId = menuaccess.FirstOrDefault(i => i.MenuURL == menuUrl  &&currentUserRoles.Contains(i.RoleId) 
         && (i.UserId == userid || i.UserId == null) // @Sam: This is how we can combine
         );
        ///check menu  && roleid && userid
        if (checkControllerActionRoleUserId != null)
        {
            if (IsActionNameEqualToCrudPageName(actionName))
            {
                CheckAccessOfPageAction(context, actionName, checkControllerActionRoleUserId);
            }
            else
            {
            if (checkControllerActionRoleUserId.IsRead == false || checkControllerActionRoleUserId.IsDelete == false || checkControllerActionRoleUserId.IsCreate == false || checkControllerActionRoleUserId.IsUpdate == false)//if userid !=null && Check Crud
                {
                    UnAuthoRedirect(context);

                }
            }
        }
    }
    catch (Exception)
    { }
}

You can test with your data for different users.



来源:https://stackoverflow.com/questions/60173428/getting-aspnet-users-roleid-for-comparison-in-permissions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!