Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Rob Watkins 369 posts 701 karma points
    Jul 17, 2012 @ 16:30
    Rob Watkins
    0

    Displaying menu items depending on user roles

    Been doing a lot of member provider implementations recently, and a common requirement is to hide menu items that the user has no permissions for. I haven't found a particularly great way of doing this, but this works - really my questions is "is there a better way?". Specifically, is there a better way of getting the page role array, and is there a built-in way of checking multiple roles (why on Earth MS don't have a Roles.IsUserInRole*s*() method I don't know.

    This is a quick debug script to highlight rather than hide disallowed menu items. I just find it ugly, too much embedded code.

    Note: This is about my 3rd Razor script, I'm an XSLT geek as you can probably tell from the code...

    <ul class="menu main_menu">
        <li>  
            <a href="/">Home</a>
        </li>
        @foreach(var n in Model.XPath("ancestor-or-self::root/Home//*[@level = 2][not(umbracoNaviHide = '1')]")) 
        {
            var pageroles = umbraco.library.IsProtected(n.Id, n.Path) ? umbraco.cms.businesslogic.web.Access.GetAccessingMembershipRoles(n.Id, n.Path) : new String[0];
            var allowed = AppUtils.IsUserInRoles(pageroles));
    
            <li>
                <a class="allowed_@(allowed)" href="@umbraco.library.NiceUrl(n.Id)">@n.nodeName</a>
            </li>
        }
    </ul>
    
  • Rob Watkins 369 posts 701 karma points
    Jul 17, 2012 @ 16:33
    Rob Watkins
    0

    ...There is an extra closing bracket on the IsUserInRoles line, but editing the post is driving me too insane so it will have to stay there.

    Actually, it doesn't work, but now I can't edit or delete the original post for some reason. working version below:

    <ul class="menu main_menu">
        <li>  
            <a href="/">Home</a>
        </li>
        @foreach(var n in Model.XPath("ancestor-or-self::root/Home//*[@level = 2][not(umbracoNaviHide = '1')]")) 
        {
            var pageroles = umbraco.library.IsProtected(n.Id, n.Path) ? umbraco.cms.businesslogic.web.Access.GetAccessingMembershipRoles(n.Id, n.Path) : null;
            var allowed = pageroles == null || AppUtils.IsUserInRoles(pageroles);
    
            <li>
                <a class="allowed_@(allowed)" href="@umbraco.library.NiceUrl(n.Id)">@n.nodeName</a>
            </li>
        }
    </ul>
    
  • Douglas Ludlow 210 posts 366 karma points
    Jul 17, 2012 @ 16:41
    Douglas Ludlow
    2

    You can use the IsProtected and HasAccess methods. Here is your script revised:

    <ul class="menu main_menu">
    <li>
    <a href="/">Home</a>
    </li>
    @foreach(var n in Model.AncestorOrSelf().Children.Where("Visible"))
    {
    bool allowed = n.HasAccess();

    <li>
    <a class="allowed_@(allowed)" href="@n.NiceUrl">@n.Name</a>
    </li>
    }
    </ul>

    (I "razorized" it a bit;)

  • Rob Watkins 369 posts 701 karma points
    Jul 17, 2012 @ 16:44
    Rob Watkins
    0

    Ooh, excellent, that's a million times better, thanks Douglas.

    How have I not come across HasAccess before? Is there a simple "everything members" guide out there with all of this in one place that I've missed? If not, maybe I'll write one :o)

  • Douglas Ludlow 210 posts 366 karma points
    Jul 17, 2012 @ 16:55
    Douglas Ludlow
    0

    I believe HasAccess is a helper method provided by the DynamicNode class and therefore is only used for Razor. Check out the Razor DynamicNode Cheat Sheet for a comprehensive list of the available properties and methods available to DynamicNode.

  • Rob Watkins 369 posts 701 karma points
    Jul 17, 2012 @ 16:56
    Rob Watkins
    0

    One final question; My structure is like this:

    Content
    -- Home
    -- -- Page 1
    -- -- Page 2
    -- Shared Library
    -- -- Library Object 1 
    -- -- Library Object 2

     ...so in my original XPath you can see I'm getting pages rather than library objects with this: root/Home//*

    However your Razor code correctly displays just the pages without such a check - could you explain why please? Does Razor treat level 1 nodes as the root? If so, how would I get my library objects?

     

     

     

  • Douglas Ludlow 210 posts 366 karma points
    Jul 17, 2012 @ 17:03
    Douglas Ludlow
    1

    The AncestorOrSelf method will get you to level one, the Home node. To go beyond that I typically get the root node by id (-1), as in this example:

    @{
    var root = Library.NodeById(-1);

    dynamic library;

    //Then you can get at your shared library several ways:

    library = root.Children[1];

    library = root.Children.Skip(1).Take(1);

    library = root.Children.Where("Name == @0", "Shared Library").First();

    library = root.Children.Where("NodeTypeAlias == @0", "SharedLibrary").First();

    //etc...
    }

     

  • Rob Watkins 369 posts 701 karma points
    Jul 17, 2012 @ 17:08
    Rob Watkins
    0

    Fantastic, thanks. Just printing off the cheat sheet now :o)

  • Douglas Ludlow 210 posts 366 karma points
    Jul 17, 2012 @ 17:11
    Douglas Ludlow
    0

    Yeah, I keep a copy of it posted to the wall by my desk ;)

Please Sign in or register to post replies

Write your reply to:

Draft