Wednesday, August 4, 2010

Checking permission of SPUser who is member of an Active Directory Group which is added to an SPGroup

Consider the following scenario, an AD group is added to an SPGroup. We need to check the permission of a user which is a member of that ADgroup when he logs in to the sharepoint application. Basically the SPUser.Roles or SPGroup.Roles is accessible only if the logged in user is having permission to access the roles information. In this the user wont be an administrator so the Roles information cannot be accessed and it will throw an AccessDenied Exception. So one way to check current user's permission inside elevated code block is to Open the SPWeb, get all the SPGroups of web then check for the group member is an domain group or not, if domain group then recursively loop to find the user based on current user's login name and if found then check for group's role information. But the above code will definitely keep processor busy and too much coding is required and chances of unwanted recursive loop execution is also there. On thinking how to solve this in an effecient way, the SPGroup.ContainsCurrentUser property came into help. For this, firstly out side the elevation block gets the SPGroups of CurrentWeb and check whether current user is a member of each group, if member then add those group information into a temporary collection, I am using List<KeyValuePair>(int, string) to store the collection of SPGroup's ID and Title. And then inside the elevated code block, loop through the elevated SPWeb's groups and check whether the iterated group belongs in the collection of KeyValue which we loaded earlier. If the group is in temporary collection then check that SPGroup's Roles, since it is in elevated code block the Roles information can be fetched without any exception. The code block can be found below,

private bool CheckWhetherCurrentUserHaveFullControl()
{   
    bool hasFullControlPermission = false;
    ////Gets all the groups to which user is having access
    List<KeyValuePair<int, string>> groupsToWhichUserHasAccess = new List<KeyValuePair<int, string>>();
    foreach (SPGroup spGroup in SPContext.Current.Web.Groups)
    {
        if (spGroup.ContainsCurrentUser)
        {
            groupsToWhichUserHasAccess.Add(new KeyValuePair<int, string>(spGroup.ID, spGroup.Name));
        }
    }
    Guid spWebGuid = SPContext.Current.Web.ID;
    Guid spSiteGuid = SPContext.Current.Site.ID;
    int id = SPContext.Current.Web.CurrentUser.ID;
    SPSecurity.RunWithElevatedPrivileges(() =>
    {
        using (SPSite spSite = new SPSite(spSiteGuid))
        {
            using (SPWeb spWeb = spSite.OpenWeb(spWebGuid))
            {
                SPGroupCollection spGroupCollection = spWeb.Groups;

                foreach (SPGroup spGroup in spGroupCollection)
                {
                    var checkPermission = from groupToWhichUserHasAccess in groupsToWhichUserHasAccess
                                          where groupToWhichUserHasAccess.Key == spGroup.ID
                                          select groupToWhichUserHasAccess;

                    if (checkPermission.Any())
                    {
                        foreach (SPRole spRole in spGroup.Roles)
                        {
                            if (spRole.Name.ToUpper().Equals("FULL CONTROL"))
                            {
                                hasFullControlPermission = true;

                                break;
                            }
                        }
                    }
                }
            }
        }
    });
    return hasFullControlPermission;
}

By the above method we can meet the objective and without writing much lines of code and unwanted recursive call against Active Directory objects.

Cheers !!!

No comments: