How to control content fields and tabs visibility in Umbraco CMS

This post illustrates the idea of how you can control and restrict the visibility of content parts for Umbraco back-office users. Umbraco gives powerful API and events that give the flexibility to implement custom logic and show/hide properties or whole tabs in any way for specific user groups (roles). We will walk through the simple implementation that can be a good reference for your custom development and can be modified/extended to fit your needs.

You will learn the basics of how to:

  • Implement method making tab visible only for a specific role with given contentTypeAlias, propertyAlias, userGroup.
  • Implement method making field visible only for a specific role with given contentTypeAlias, tabAlias, userGroup.
  • Register the methods using composers so the changes affect the back-office.
  • Work with ContentItemDisplay object and its properties to render node based on business rules.

For the below implementation you need to include the following namespaces:

using Umbraco.Web.Editors;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.PublishedModels;
using Umbraco.Core.Composing;

Create Composer and component

First, we need to create a Umbraco composer and component to register the custom implementation and visibility restrictions.

Composer:

[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class HideContentPartsComposer : IUserComposer
{
    public void Compose(Composition composition)
    {
        composition.Components().Append<HideContentPartsComponent>();
    }
}

Component:

public class HideContentPartsComponent: IComponent
{
    public void Initialize()
    {
        throw new NotImplementedException();
    }

    public void Terminate()
    {
        throw new NotImplementedException();
    }
}

Register SendingContentModel event

Secondly, go to HideContentPartsComponent and set the SendingContentModel event for EditorModelEventManager as follows:

public void Initialize()
{
    EditorModelEventManager.SendingContentModel += EditorModelEventManager_SendingContentModel;
}

private void EditorModelEventManager_SendingContentModel(HttpActionExecutedContext sender, EditorModelEventArgs<ContentItemDisplay> e)
{
   //Restrict visibility here
}

Showing content fields only for role

private void ShowFieldOnlyForRole(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string propertyAlias, string userGroup)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !_currentUserGroupsAliasses.Contains(userGroup))
        {
            foreach (var tab in contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.ToList())
            {
                if (!tab.Properties.IsNullOfEmpty())
                {
                    tab.Properties = tab.Properties.Where(x => x.Alias != propertyAlias);
                }
            }
        }
    }
}

To show the google manager field only for admin execute the method as follows:

/* Show google manager field only for admin */
ShowFieldOnlyForRole(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
    propertyAlias: "googleTagManagerId", userGroup: "admin");

Umbraco Hide content field

Showing content tabs only for role

private void ShowTabOnlyForRole(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string tabAlias, string userGroup)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !_currentUserGroupsAliasses.Contains(userGroup))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> x.Alias != tabAlias);
            }
        }
    }
}

To show the 'SEO Settings' tab only for the admin role execute the method as follows:

/* Show 'SEO Settings' tab only for admin role */
ShowTabOnlyForRole(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
    tabAlias: "SEO Settings", userGroup: "admin");

Umbraco CMS hide content tab

Show content tab only for specific roles

To make 'SEO Settings' tab visible only for both admin and editor roles execute the method as follows:

ShowTabOnlyForRoles(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
     tabAlias: "SEO Settings", userGroups: new []{ "admin", "editor"  } );
private void ShowTabOnlyForRoles(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string tabAlias, string[] userGroups)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !userGroups.IsNullOfEmpty() && !_currentUserGroupsAliasses.Any(cug=> userGroups.Any(ug=>ug == cug)))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> !x.Alias.Equals(tabAlias));
            }
        }
    }
}

Show list of tabs only for specific roles 

To make 'SEO Settings' and "Content" tab visible only for both admin and editor user groups execute the method as follows:

ShowTabsOnlyForRoles(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
    tabAliases: new []{ "Content", "SEO Settings"} , userGroups: new []{ "admin", "editor"  } );
private void ShowTabsOnlyForRoles(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string[] tabAliases, string[] userGroups)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !userGroups.IsNullOfEmpty() && !_currentUserGroupsAliasses.Any(cug=> userGroups.Any(ug=>ug == cug)))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> !tabAliases.Contains(x.Alias));
            }
        }
    }
}

Wrapped code

To make the code leaner we'll use a custom extension method that checks whether the collection is empty: 

public static class CollectionsExtensions
{
   public static bool IsNullOfEmpty<T>(this IEnumerable<T> list)
   {
      if (list == null)
         return true;

      if (list.Any() == false)
         return true;

      return false;
   }
}

Working HideContentPartsComponent implementation:

public class HideContentPartsComponent: IComponent
{
    IList<string>  _currentUserGroupsAliasses;

    public void Initialize()
    {
        EditorModelEventManager.SendingContentModel += EditorModelEventManager_SendingContentModel;
    }
   
private void EditorModelEventManager_SendingContentModel(HttpActionExecutedContext sender, EditorModelEventArgs<ContentItemDisplay> e)
    {
        _currentUserGroupsAliasses = e.UmbracoContext.Security.CurrentUser?.Groups?.Select(userGroup => userGroup.Alias).ToList();
      
        /* Show google manager field only for admin */
        ShowFieldOnlyForRole(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
            propertyAlias: "googleTagManagerId", userGroup: "admin");
        
        /* Show 'SEO Settings' tab only for admin role */
        ShowTabOnlyForRole(contentItemDisplay: e.Model, contentTypeAlias: "globalSettings", 
            tabAlias: "SEO Settings", userGroup: "admin");
    }

private void ShowFieldOnlyForRole(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string propertyAlias, string userGroup)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !_currentUserGroupsAliasses.Contains(userGroup))
        {
            foreach (var tab in contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.ToList())
            {
                if (!tab.Properties.IsNullOfEmpty())
                {
                    tab.Properties = tab.Properties.Where(x => x.Alias != propertyAlias);
                }
            }
        }
    }
}

private void ShowTabOnlyForRole(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string tabAlias, string userGroup)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !_currentUserGroupsAliasses.Contains(userGroup))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> x.Alias != tabAlias);
            }
        }
    }
}

private void ShowTabOnlyForRoles(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string tabAlias, string[] userGroups)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !userGroups.IsNullOfEmpty() && !_currentUserGroupsAliasses.Any(cug=> userGroups.Any(ug=>ug == cug)))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> !x.Alias.Equals(tabAlias));
            }
        }
    }
}

private void ShowTabsOnlyForRoles(ContentItemDisplay contentItemDisplay, string contentTypeAlias, string[] tabAliases, string[] userGroups)
{
    if (contentItemDisplay.ContentTypeAlias.Equals(contentTypeAlias))
    {
        if (!_currentUserGroupsAliasses.IsNullOfEmpty() && !userGroups.IsNullOfEmpty() && !_currentUserGroupsAliasses.Any(cug=> userGroups.Any(ug=>ug == cug)))
        {
            if ((contentItemDisplay?.Variants?.FirstOrDefault()?.Tabs?.Any()).GetValueOrDefault(false))
            {
                contentItemDisplay.Variants.FirstOrDefault().Tabs =
                    contentItemDisplay.Variants.FirstOrDefault().Tabs.Where(x=> !tabAliases.Contains(x.Alias));
            }
        }
    }
}

    public void Terminate()
    {
        EditorModelEventManager.SendingContentModel -= EditorModelEventManager_SendingContentModel;
    }
}

Conclusion

Restricting Umbraco Content parts is easy and prevents users from mistakenly breaking the layout or losing data. Besides that, it makes the back-office cleaner and more user-friendly. If someone tries to make changes to the field before they have permission, then they won't be able to do that because it will be hidden from them on their screen.

We went through the simple example of how to implement custom logic and hide/show parts for specific roles. You can modify or extend the above code as needed and I recommend exploring the Umbraco events if you need more advanced back-office workflows. 

Comments
Leave a Comment