Learning SharePoint the hard way...

Sunday, August 14, 2011

Extending the SharePoint Security Trimmed Control to support SharePoint Groups

14 comments :

We all know that (SPSecurityTrimmedControl) SharePoint Security Trimmed Control comes to our rescue when we need to show role/permission based data in SharePoint. It helps you Conditionally renders the contents of the control to the current user only if the current user has permissions defined in the PermissionString.

<Sharepoint:SPSecurityTrimmedControl runat=”server” Permissions=”ManageLists”>
      Place your control(s) here
</SharePoint:SPSecurityTrimmedControl>

All this is good and works fine for most of the scenarios, however you may seldom find a need to be able to add a “SharePoint Group” instead of a “PermissionString”

So, let’s tell you how…

The idea is to create your wrapper control to support this feature. Let’s get started

Create a custom Web Control and write down the required logic based on your requirements. This should inherit from SPSecurityTrimmedControl

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web;
using Microsoft.SharePoint;

namespace SPSecurityTrimmedControlExtender
{
public class SPUserGroupTrimmedControl : SPSecurityTrimmedControl
{
private List groups = new List();

public string GroupsString
{
get
{
return string.Join(",", groups.ToArray());
}
set
{
groups.AddRange(
value.Split(new char[] { ',' },
System.StringSplitOptions.RemoveEmptyEntries)
);
}
}

protected override void Render(HtmlTextWriter output)
{
if (!string.IsNullOrEmpty(GroupsString) && IsMember())
{
base.Render(output);
}
}

private bool IsMember()
{
using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
{
bool isMember = false;
foreach (string group in groups)
{
isMember = web.IsCurrentUserMemberOfGroup(web.Groups[group].ID);
}
return isMember;
}
}
}
}

Now, put this assembly in GAC and add a safe control entry in the web.config of you web application.



You are now ready to use this in your web page or master page by registering it.

<%@ Register TagPrefix="MyUserGroupExtender" Assembly="SPSecurityTrimmedControlExtender, Version=1.0.0.0, Culture=neutral, PublicKeyToken=121fae78165ba3d4" %>

//your control to show to the specified group only


And you are done!!!

14 comments :

  1. If I could buy you a beer I would! Awesome assembly - I was able to get this to work in my environment and it has now opened up more capabilities for our security. THANK YOU!!! :D

    Curious, ever think of taking it one more notch ahead and seeing if multiple groups can be used within the "groupsstring" attribute, just like how the built-in SPSecurityTrimmedControl works?

    Thanks,
    -Eric

    ReplyDelete
  2. Thanks Eric for the gesture :-) I am glad it helped you

    Definitely, would do that and update the code, good point though

    ReplyDelete
  3. Just to add, I played around with it some more and it looks like this assembly will take multiple groups, but its in the 'all' mode; meaning the user would have to be a member in all of the groups set. Cool, but I'm looking for 'any' if possible.

    Thanks,
    -Eric

    ReplyDelete
  4. Hi, thank you for your article, but the final assignment should be done with |= instead of =.
    Thank you, Damiano

    ReplyDelete
  5. Could you please explain this code if you do it in asc.x file in a class file and then as in the GAC and register it in the masterpage

    ReplyDelete
  6. thank you!
    I have been very useful your article

    ReplyDelete
  7. This is really great! Thanks.

    ReplyDelete
  8. Thanks for this. I tweaked it to check specific claims in my case.

    ReplyDelete
    Replies
    1. Could you please post your tweaked code?

      Delete
  9. Good article dude! Although your code has a leak as SPSite is not being disposed. Replace it with the code below to fix it.

    using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
    using (SPWeb web = siteCollection.OpenWeb())
    {
    // Perform operations on site.
    } // SPWeb object web.Dispose() automatically called; SPSite object
    // siteCollection.Dispose() automatically called.

    ReplyDelete
  10. Great Article.... It almost helped me completely.

    But there is a small catch, this code won't work if this code is accessed 'Anonymously'. Whenever this code is hit by anonymous user, it asks for prompt. After some research found out that

    web.Groups[group].ID

    This is where code stops and asks for credentials as anonymous user doesn't have access to find group in site collection. So i did a small walkaround and used SPSecurity.RunWithElevatedPrivileges instead. Following is my updated IsMember() function.

    private bool IsMember()
    {
    bool isMember = false;
    int groupID = -1;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
    foreach (string group in groups)
    {
    groupID = web.Groups[group].ID;
    }
    }
    });
    if (groupID != -1)
    isMember = SPContext.Current.Web.IsCurrentUserMemberOfGroup(groupID);
    return isMember;
    }

    Hoping it may help someone.

    ReplyDelete
  11. Hi Team,

    I am getting trouble to use this code...
    1) I use SharePoint Blank Project & Add one class file which i inherit from SPSecurityTrimmedControl & work the same code as written at above.
    2) I didn't do explicitly sign in it as SharePoint Blank Project itself is signed key with. Now, I add that in GAC & then add in web.cofig and one of MyTask.aspx page.

    But it gives me an error seems that it is not working the registration or something is wrong.. because it gives me yellow page with same line of code..

    ReplyDelete
  12. It is not working on Custom NewTask.aspx kind of form where we like to hide few rows in insert task form. In fact SPSecurityTrimmerCtrl is also not working..

    It gives an error message
    This Web Part does not have a valid XSLT stylesheet:
    Error: Reference to undeclared namespace prefix: myusergroupextender

    Please guide me if anyone has face such type of issue.

    ReplyDelete