# Role-based toolbox filtering using IToolboxFilter interface

## Overview

This tutorial demonstrates how to implement a toolbox filter that allows only Administrators to the use of the *News* widget. To do this, you first implement `IToolboxFilter` interface and then, you replace the default implementation.

## Implement the IToolboxFilter interface

The `IToolboxFilter` interface provides an extension point for filtering toolbox sections and toolbox items.

1. In Visual Studio, open the context menu of your project and click *Add* » *Class*.
2. Name the class file `RoleToolboxFilter.cs` and click *Add*.
3. Make the `RoleToolboxFilter` implement the `IToolboxFilter` interface.
4. Create a constructor that accepts an `IToolboxFilter` object.\
   The constructor forms a chain of responsibility, where each toolbox filter points to an instance of the next filter in line.
5. Implement the `IsSectionVisible()` method from the `IToolboxFilter` interface.

   The code checks whether a toolbox section complies with the specified conditions to be visible. It also calls the `IsSectionVisible()` method of the next filter in line. The method accepts the toolbox section and an `IToolboxFilterContext` context as parameters.

   Optionally, since Sitefinity CMS version 12.0 you can implement additional filtering logic using the `IToolboxFilterContext`. It provides the following information:

   * `MediaType` - the media type indicates whether the toolbox is loaded in the context of the Pages, Templates, Forms, or Email campaigns modules screens. If you want your filtering to be applied only to some of these modules you can implement conditional logic based on this property.
   * `ContainerId` - the container Id property can help you distinguish in your code, whether you are working with the widgets toolbox or the layout controls toolbox. The possible values are `LayoutToolboxContainer` and `ControlToolboxContainer` respectively.
6. Implement the `IsToolVisible()` method from the `IToolboxFilter` interface.

   The code checks whether a widget complies with the specified conditions to be visible. It also calls the `IsToolVisible()` method of the next filter in line.
7. Implement the role filtering logic, by passing a set of tags, representing the roles that can view a section or a tool, on method call.\
   Using the `ClaimsManager` class, the code retrieves the current user identity and compares the set of tags with the current user's roles. It returns a result that indicates if any of them overlap.

Use the following code sample:

```C#
using System;
using System.Collections.Generic;
using System.Linq;
using Telerik.Sitefinity.DesignerToolbox;
using Telerik.Sitefinity.Security.Claims;

namespace SitefinityWebApp
{
    public class RoleToolboxFilter : IToolboxFilter
    {
        public RoleToolboxFilter(IToolboxFilter next)
        {
            this.next = next;
        }

        private readonly IToolboxFilter next;
        public bool IsSectionVisible(IToolboxSection section, IToolboxFilterContext context)
        {
            bool isVisible = true;

            if (next != null)
            {
                isVisible = next.IsSectionVisible(section, context);
            }
            
            //Optional: Uncomment this line to apply additional filtering to ensure only the widgets toolboix is filtered and only on the Pages and Templates editing screens
            //isVisible = (context.ContainerId == "ControlToolboxContainer" && (context.MediaType == DesignMediaType.Page || context.MediaType == DesignMediaType.Template));
            
            //apply custom logic for role-based filtering
            isVisible = isVisible && ApplyRoleFilter(section.Tags);

            return isVisible;
        }
        public bool IsToolVisible(IToolboxItem tool)
        {
            bool isVisisble = (next == null) || next.IsToolVisible(tool);
            isVisisble &= ApplyRoleFilter(tool.Tags);

            return isVisisble;
        }
        private bool ApplyRoleFilter(ISet<string> tags)
        {
            var currentUser = ClaimsManager.GetCurrentIdentity();
            if (currentUser == null)
            {
                return true;
            }

            IEnumerable<string> taggedRoles = tags
                .Where(t => t.StartsWith("role:", StringComparison.InvariantCultureIgnoreCase))
                .Select(t => t.Substring(t.IndexOf(":") + 1));

            if (!taggedRoles.Any())
            {
                return true;
            }

            ISet<string> taggedRoleSet = new HashSet<string>(taggedRoles, StringComparer.InvariantCultureIgnoreCase);
            return taggedRoleSet.Overlaps(currentUser.Roles.Select(r => r.Name));
        }

    }
}
```

## Register the IToolboxFilter in the ObjectFactory

To apply the filtering that you created when implementing `IToolboxFilter` interface, you need to replace the default filter. Sitefinity's default `IToolboxFilter` implementation is the `DefaultToolboxFilter` class. This class reports as visible only sections and items that are enabled. In addition, it also implements the logic for displaying backend section and items when editing a backend page.

You can replace the default filter by registering a custom instance in the `ObjectFactory`.\
Perform the following:

1. In Visual Studio, open your project's `Global.asax` file.

   > info **NOTE**: If you do not have a `Global.asax` file, create a new `Global.asax` file and add it to your project. In the context menu of your project, click *Add*»*New Item…* » *Visual C#* » *Web*» *Global Application Class*.
2. Add the following code inside the `Application_Start` method and hook to the `ObjectFactory_Initialized` event:

   ```C#
   using System;
   using Telerik.Microsoft.Practices.Unity;
   using Telerik.Sitefinity.Abstractions;
   using Telerik.Sitefinity.DesignerToolbox;

   namespace SitefinityWebApp
   {
       public class Global : System.Web.HttpApplication
       {
           protected void Application_Start(object sender, EventArgs e)
           {
               ObjectFactory.Initialized += ObjectFactory_Initialized;
           }

           void ObjectFactory_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
           {
               if (e.CommandName != "RegisterCommonTypes")
                   return;

               IToolboxFilter currentFilter = ObjectFactory.Resolve<IToolboxFilter>("Telerik.Sitefinity.DesignerToolbox.DefaultToolboxFilter");
               IToolboxFilter newFilter = new RoleToolboxFilter(currentFilter);
               ObjectFactory.Container.RegisterInstance<IToolboxFilter>(typeof(RoleToolboxFilter).FullName, newFilter);
           }
       }
   }
   ```

   As a result, the `DefaultToolboxFilter` is replaced with your custom `RoleToolboxFilter`.

To test your newly registered filter that allows only users in the Administrator role to use the *News* widget, perform the following:

1. Navigate to *Administration* » *Settings* »*Advanced* » *Toolboxes* » *Toolboxes* » *PageControls* » *Sections* » *ContentToolboxSection* » *Tools* » *NewsView*.
2. In the *Tags* field, enter `role:Administrators`.
3. Click *Save changes*.
