Freitag, 22. August 2014

Check if CurrentUser belongs to a SharpeointGroup due to AD-Groups

Recently I had to check if a User belongs to specific SharePoint-Groups. While SPUser.Groups worked well as long as the user was directyl added to the Groups, it did not work when an Active-Directory Group that the user belongs to was added to a SharePoint-Group.

I first tried by resolving the AD-Groups iteratively, however that was obviously quite slow and expensive. There had to be a better solution and I found it:

As SharePoint uses Claims-Authentication (by Default in 2013) all the AD-Groups (at least their SIDs) are alredy in the users Claims, including their complete hirarchy.

So all you have to do is something like:

var claims = ((Microsoft.IdentityModel.Claims.ClaimsIdentity) testuser.Identity).Claims;
to get the current Users Claims. In this Claims collection you have besides others the current users Groups, represented by their SIDs. You have to reference Microsoft.IdentityModel, which is usually located in GAC on a SP2013 Server.

To check if the user or one of it´s Groups belongs to a specific SharePoint-Group, you simply have to do:
SPSecurity.RunWithElevatedPrivileges(delegate{
   using (var elevatedSite = new SPSite(SPContext.Current.Site.ID))
{
   var web = elevatedSite.RootWeb;
var group = web.SiteGroups.GetByName(groupName);
foreach (SPUser user in group.Users)
{
   if (user.IsDomainGroup)
{
   //var users = new List();
var sid = user.LoginName.Split('|')[1];
if (claims.Any(c => String.Equals(c.Value, sid, StringComparison.CurrentCultureIgnoreCase)))
{
   returnValue = true;
break;
}
} 
   else if (user.LoginName == userName)
{
returnValue = true;
break;
}
}
}
});

Maybe there is a simple way to get all SharePoint-Groups, where one of the SIDs belong to, too. I did not try that yet.

Show only 5 Days in Default-Calendar View (Mo-Fr)

I just had the requirement to Show only Monday to Friday in the Calendar View. The Environment was SharePoint 2010, I only had rights to edit the User Interface.

So I added a CEWP, which is linked to a Textfile located in a doc-Library, containing the following Script. The Script is overwriting some Default-Functions, which are responsible for Rendering. Besides some specific Appointments, starting with a specified String are rendered with additional attributes and it is showing all appointments (no expand/collapse anymore)

The Script is using some functions of (an old verions) of JQuery, because it is already loaded on the site. However, it might not be very difficult, to replace that functions into a native-way, if you don´t have JQuery.

The Content of my script-File:

<script language="javascript">
ExecuteOrDelayUntilScriptLoaded(function() {
//Removing Weekend and adjusting the calculated width of appointments
$('th.ms-acal-week-top').css('width', '20%');
$('th.ms-acal-month-top').css('width', '20%');
$('table.ms-acal-month tr').each(function(index) {$(this).find('td:gt(4), th:gt(5)').remove()});
SP.UI.ApplicationPages.CalendarTableBase.prototype.$3T = function(c,d){
        ULSvSp:;
        for(var b=0,a=0;
        a<d && a < 5;
        a++)b+=this.$1o(c+a);
        return b;
    }

SP.UI.ApplicationPages.CalendarTableBase.prototype.get_$2f = function(){
        ULSvSp:;
        return 5;
};

SP.UI.ApplicationPages.CalendarStateHandler.prototype.onTableSucceed =function(a){
        ULSvSp:;
        this.$D_1.$4V();
        this.$3H_1=false;
        a.Options&2&&this.$D_1.$7s(a.Table);
 $('table.ms-acal-detail tr').each(function(index) {$(this).find('td:gt(4), th:gt(5)').remove()});
        a.Options&8&&a.Options&32&&this.$D_1.$86(a.Dates,a.RangeJDay);
        this.$D_1.$7Z(this.$a_1.get_$2C());
        this.$2c_1=false;
        0===(a.Options&1)&&this.$2A_1()
};
//set all days to "Expanded"
SP.UI.ApplicationPages.CalendarInfoGrid.prototype.$38_0 = true;
//Applying specific background-color for all appointments starting with "Absenz"
SP.UI.ApplicationPages.ItemBuilder.prototype.$4P = function($p0, $p1, $p2, $p3, $p4, $p5, $p6, $p7) {
        var $v_0 = $p1.$c;
        $p0.append('<div class=\"ms-acal-item');
        if (!$v_0.$N.primary) {
            $p0.append(' ms-acal-color');
            $p0.append($v_0.$N.color);
        }
        $p0.append('\" style=\"');
        this.$3j_0($p0, $p2, $p3, $p4, $p5);
        $p0.append('border-width:');
        $p0.append($p6);
 if ($v_0.$3R.match(/^absenz/i))
 {
  $p0.append(';background-color: pink');
 } 
        $p0.append(';\" title=\"');
        this.$4X_0($p0, $v_0);
        $p0.append('\"');
        this.$4D_0($p0, $p1.$2K);
        $p0.append('\">');
        $p0.append('<div class=\"ms-acal-mdiv\">');
        if ($p7) {
            this.$5Q_0($p0, $v_0);
        }
        this.$3N_0($p0, $v_0);
        if (!this.$5_0($v_0.$1G)) {
            $p0.append(' (');
            $p0.append($v_0.$1G);
            $p0.append(')');
        }
        $p0.append('</div></div>');
    }
}, "SP.UI.ApplicationPages.Calendar.js");
</script>

Don´t really know, if it works in SP 2013 too, but as SP2013 is doing the rendering also in JS, it might be not very different to the SP2010 solution

Regards