Sidenav configuration and AuthorizationPolicies

I have been working on creating a custom sidenav setup for my UDsite, pulling some helpful code from others on the site (thanks!) and some of my own. I’ve got it about where I want it, with the exception of one thing.

I am using AD groups to specify what pages users will have the ability to access. When using the custom sidenav setup, everything for the site structure shows, which I’m ok with. However, if a user goes to a page which they do not have current authorization to, they just get “Page not found”

Has anyone worked through this particular scenario already? I would be ok with one of either of these options, if do-able.

  • A way to set new-udsidenavitems with authorization policy to show or not to show
  • A way to set a better message on the page when someone without permissions views it. Being able to specify “You don’t have access. Contact admin if you think this is in error” would be nice.

I use the code below to build my navigation dynamically based on Authorization and group memberships. The trade off is that Get-UdAuthorization takes a few seconds to run. So the navigation pane will be empty in a few seconds immediately following a refresh/page load.

I opened an enhancement issue on the speed, or lack thereof yesterday.

$Navigation = New-UDSideNav -Endpoint {
    $Policies = Get-UDAuthorizationPolicy
    New-UDSideNavItem -Text "Home" -PageName "Home" -Icon home
    New-UDSideNavItem -Text "Consultants Dashboard" -PageName "Consultants Dashboard" -Icon hourglass_half
    New-UDSideNavItem -Text "Departments" -PageName "Departments" -Icon sitemap
    New-UDSideNavItem -Text "Employees Dashboard" -PageName "Employees Dashboard" -Icon User
    New-UDSideNavItem -Text "Blue Collars" -PageName "BlueCollars" -Icon User
    if ($Policies -contains 'Manager'){
        New-UDSideNavItem -Divider
        New-UDSideNavItem -Text " Manager ->" -Icon sitemap -Children {
            New-UDSideNavItem -Text "Your Department" -PageName "Manager" -Icon User
        }
    }
    if ($Policies -contains 'AdminCollection'){
        New-UDSideNavItem -Divider
        New-UDSideNavItem -Text " Administration ->" -Icon tools -Children {
            if ($Policies -contains 'DepartmentsAdmin'){
                New-UDSideNavItem -Text "Administer Departments" -PageName "Admin - Departments" -Icon sitemap
            }
            if ($Policies -contains 'BlueCollarsAdmin'){
                New-UDSideNavItem -Text "Administer Blue Collars" -PageName "Admin - Blue Collars" -Icon users
            }
            if ($Policies -contains 'EmployeesAdmin'){
                New-UDSideNavItem -Text "Administer Employees" -PageName "Admin - Employees" -Icon users
            }
        }
    }
    if ($Policies -contains 'LogCollection'){
        New-UDSideNavItem -Divider
        New-UDSideNavItem -Text " Logs ->" -Icon list -Children {
            if ($Policies -contains 'LogViewerAll'){
                New-UDSideNavItem -Text "Log Viewer - ALL" -PageName "LogViewer - ALL" -Icon list
            }
            if ($Policies -contains 'LogViewerAllDetailed'){
                New-UDSideNavItem -Text "Log Viewer - ALL Detailed" -PageName "LogViewer - ALLDetailed" -Icon list
            }
        }
    }
}
1 Like

I like how you do this. Due to the speed issue, I think I’ll keep it in my back pocket. Curious to see if anyone else has a different take on it.

I think the speed is affected by how many auth policies you have.
I’d be thrilled if someone has a more efficient way.

You could put the result of Get-UDAuthorizationPolicy into a session variable so it get stored the first time around.

if ($session:Policies -eq $null) {
    $Session.Policies = Get-UDAuthorizationPolicy
}

You would still have a delay, but one time around instead of every page load.
Whenever your app pool is recycled though, it would reset the variable to null and get queried again.

You could also go further and store the udauthentication results into a database (or plain text file) so whenever the pool recycle, you’d get it from disk / db instead of querying it, increasing further the speed. Of course, as soon as you maintain a copy of the UDAuthorization, you’ll have to ensure you keep a sync in place so the policies on disk do not get outdated (Using a API endpoint queried every 4 hours for instane to update the cached policies results.)

Regarding $Session variable scope use though, It does not seems to be working well in 2.6.
2.5.3 is fine though.

3 Likes

That should do, great idea.

I took the $session idea and ran with it. Couple things I noticed when I did this setup.

  • I was using subheaders to denote sections. This stopped showing when they were put into the statements for checking permission levels. Not a big deal, it didn’t was completely cosmetic for my page.
  • Icon’s specified in the sidenav items were not showing up. When I set the icon in the new-udpage for each page file, they showed up no problem.
  • It might be because i currently only have about 4 Auth Policies, but i’ve not noticed any initial lag of the sidenav menu being occupied.

Further to this, I load my pages dynamically on my nav menu like this:
$Pagenames = (pages | ? {_.Dynamic -ne $true}).name
foreach($pagename in $Pagenames){
New-UDSideNavItem -Text $pagename -PageName $pagename -Icon Link
}

I’ve noticed that all i need to do is put ‘Get-UDAuthorizationPolicy’ on my nav page before this. With this in place, only the pages the user has access to are displayed, otherwise without it they’re all displayed. This must be refreshing the $pages variable when it runs, listing only the ones available to the applied auth policy, otherwise they’re all listed, not sure if this is intended or a bug?