Reports section is available by default to all users who are members of the WebEditors group as the authorization policy of that MenuItem is set to AuthorizationPolicy = CmsPolicyNames.CmsEdit
So basically Reports section comes always together with the Edit Mode. However, I can imagine that sometimes reports are only useful to only a few specific editors and can be hidden from all others.
Unfortunately it is not possible to configure this anywhere but thanks to Optimizely's great and powerful extensibility it is possible to accomplish that requirement with just a few lines of code:
public class CustomMenuAssembler : MenuAssembler
{
private readonly IPrincipalAccessor _principalAccessor;
public CustomMenuAssembler(IEnumerable<IMenuProvider> menuProviders, IHttpContextAccessor httpContextAccessor, IPrincipalAccessor principalAccessor) : base(menuProviders, httpContextAccessor)
{
_principalAccessor = principalAccessor;
}
public override IEnumerable<MenuItem> GetMenuItems(string parentPath, int relativeDepth)
{
var menuItems = base.GetMenuItems(parentPath, relativeDepth).ToList();
if (_principalAccessor.Principal.IsInRole("HasAccessToReportsGroup") == false)
{
return menuItems;
}
var reportItem = menuItems.SingleOrDefault(x => x.Path.Equals("/global/cms/report", StringComparison.Ordinal));
if (reportItem == null)
{
return menuItems;
}
// Add user group check here
menuItems.Remove(reportItem);
return menuItems;
}
}
So we create a new MenuAssembler which inherits from the default one, and we pass the additional IPrincipalAccessor reference to it.
In my example I created a custom user group called HasAccessToReportsGroup . If an editor does not belong to this group then he/she will not see the Reports menu item.
Last we need to register this custom menu assembler, and we need to make sure we do it after the built-in cms initialization modules are finished. Let's add a custom initializable module:
[InitializableModule]
[ModuleDependency(typeof(InitializableModule))]
public class DependencyResolverInitialization : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.ConfigurationComplete += (_, _) =>
{
context.Services.AddSingleton<MenuAssembler, CustomMenuAssembler>();
};
}
public void Initialize(InitializationEngine context)
{
}
public void Uninitialize(InitializationEngine context)
{
}
}
The same approach can be used to conditionally hide all other menu items, you just need to change the path.
Please find the list of other paths:
- /global/cms/report
- /global/cms/dashboard
- /global/cms/visitorgroups