Author Archives: bexgordon

SharePoint Add-in Client Side check if current user is in a group

Wanted to add some client side validation for my SharePoint hosted add-in (app, addin) to check whether a user was in an HR group. If the user is in the group then the proper interface will show, otherwise a message will display. Obviously you should do server side validation on your API calls or server side code as well if it's sensitive information. I've only tested this with side loading an app, it will probably require a certain level of permissions on app install.. Will update when I get that far 🙂 

var context;
var currentUser = null;
var userGroups;
var permissionsToView = false;

$(document).ready(function () {
    getCurrentUser();
});

function getCurrentUser() {
    var context = new SP.ClientContext.get_current();
    var website = context.get_web();
    currentUser = website.get_currentUser();
    userGroups = currentUser.get_groups();
    context.load(currentUser);
    context.load(userGroups);
    context.executeQueryAsync(Function.createDelegate(null, onQuerySucceeded), Function.createDelegate(null, onQueryFailed));
}

function onQuerySucceeded(sender, args) {
    var groupsEnum = userGroups.getEnumerator();
    while (groupsEnum.moveNext()) {
        var group = groupsEnum.get_current();
        if (group.get_title() == "My Group Name") {
            permissionsToView = true;
        }
    }

    if (permissionsToView) {
        // yay can see!
    }
    else {
        $('.no-permissions').show(); // show some sort of no permissions message
    }
}

function onQueryFailed(sender, args) {
    $(".error").html('Request failed ' + args.get_message() + '\n' + args.get_stackTrace());
    $(".error").show();
}

 

Dynamically create subscribe to alert link JavaScript SharePoint

Code for creating an alert for a list dynamically on a page. I have created the following HTML file, upload it somewhere in your site collection and link to it from a content editor web part, change the title of the list you want people to subscribe to and the message 🙂 

Note that this is sitting on a discussion site home page therefore is looking for /sitepages – if you want it to look for /pages change this, or if you want to hard code the link to a root level list for subscription change it even more 😛 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
</head>

<body>
<script type="text/javascript">
	$().ready(function () {
	    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () { });
	    SP.SOD.executeOrDelayUntilScriptLoaded(initiateDiscussionsAlerts, "sp.js", "SP.ClientContext");
	})

	var discussionList;
	var discussionWeb;
	function initiateDiscussionsAlerts() {
		// load web
		clientContext = new SP.ClientContext.get_current();                    
	    discussionWeb = clientContext.get_web();
	    clientContext.load(discussionWeb);
	    
	    // load discussions list and ID
	    discussionList = discussionWeb.get_lists().getByTitle("Discussions List");
	 	clientContext.load(discussionList); 
	
		clientContext.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded), Function.createDelegate(this, onQueryFailed));
	}
	  
	function onQuerySucceeded() {
		var webUrl = window.location.href;
		if (webUrl.toLowerCase().indexOf('/sitepages') != -1) {
			var listGuid = discussionList.get_id();
		    webUrl = webUrl.substr(0, webUrl.toLowerCase().indexOf('/sitepages'));
		    
		    $('.discussion-alert > a').attr('href', webUrl + '/_layouts/SubNew.aspx?List=' + listGuid + '&Source=' + webUrl);
		}
	}
	             
	function onQueryFailed(sender, args) {
		alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
	}
</script>

	<div class="discussion-alert"><a href="">Subscribe to Alerts for this Discussion Board</a></div>
</body>

</html>

 

Reporting Services SSRS in SharePoint Error ‘New Document’ requires a Microsoft SharePoint Foundation-compatible application and web browser…..

Adding SSRS content types seems to be a bit flaky.. We couldn't get the content types automatically added by activating the feature in one web application – so we manually added the content types into the site collection as specified in here (http://sharepoint.stackexchange.com/questions/111619/sharepoint-2013-sp1-installation-issue-ssrs-content-type-missing-for-new-sc) – this post also had some other good suggestions.

So we add another web app for another purpose – again same issue with the content types not adding, so we add them manually again and get the following error when trying to create an item in the document library for "Report Data Source", "Report Builder Report" and "Report Builder Model" – 'New Document' requires a Microsoft SharePoint Foundation-compatible application and web browser. To add a document to this document library, click the "Upload Document" button."

We had added them manually correctly and obviously it was installed correctly as another web app was working..

We came across this post which worked for us! https://chrishattonnzlsp.wordpress.com/2015/07/21/reporting-services-new-document-requires-a-microsoft-sharepoint-foundation-compatible-application-and-web-browser/

Running rsSharePoint.msi fixed the issue. We had to delete the content types from lists and the site collection and then deactivated and reactivated the reporting services feature, the content types were there this time and we could add the proper ones into the libraries.

Tenant Administration Delete Root Site Collection and Re-Create Doesn’t Properly Delete From Recycle Bin

I came across a strange issue when re-creating the root level tenant site collection from the interface. It's like it wasn't actually deleting the site collection – the wiki page content was on my new home page and the features activated was all wrong. Here's the steps I followed in the interface to replicate the issue:

We need to remove the root level site collection

  • Navigate to the site collections screen adminurl.sharepoint.com/_layouts/15/online/SiteCollections.aspx
  • Check the root level site site.sharepoint.com
  • Click Delete
  • Select “I understand that nobody can access SharePoint until I create a new site collection at https://site.sharepoint.com.”
  • Click Delete
  • Wait until the site is removed before continuing the release.

Create site collection

  • Click on create new private site collection in admin adminurl.sharepoint.com/_layouts/15/online/SiteCollections.aspx
  • Enter the following details:

    • Title: Title
    • Web Site Address: this should default to the root level site
    • Template Selection: Publishing -> Publishing Portal
    • Time Zone: (UTC + 12:00) Auckland, Wellington
    • Administrator: admin username
    • Server Resource Quote: leave at 300
    • Click OK
  • You will get a warning "Permanently delete the site collection from the recycle bin and continue."
  • Check the box and click OK

It obviously doesn't actually properly delete the site collection from the recycle bin. 

So I contacted Microsoft as this was annoying the hell outa me and I couldn't deploy my site into the test environment. They gave me the following instructions to get PowerShell to do the job, which is cool but slightly annoying as the release didn't require any installation of extra software and now it does, but in saying that I guess anyone who works with SharePoint should have this installed anyway :P. M$ didn't give any indications of fixing and ignored my comments regarding fixing the interface to work. 

Access Denied deploying files to SharePoint Online as Global Administrator

So I went to deploy to test and for some reason kept getting access denied errors, but I'm global admin!! and Site collection admin!! What. It died on the code where I am uploading to the master page gallery. 

The problem was I had been deploying to /sites/site and not to the root web in other tests. The root web has a setting on it called DenyAddAndCustomizePagesStatus which is set to true but on the /sites/site sites, it's set to falce :|. Even more annoying, I had alsom deployed to a demo tenant under the root web and this works, so I can only assume since it's a demo tenant with content that Microsofts code actually does this for you… https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f?ui=en-US&rs=en-US&ad=US

Here's the code for deactivating on your site collection. Thanks to Ronny Lewandowski and SPMeta2 for helping me to solve this issue :). 

static void Main(string[] args)
{
            string siteUrl = ConfigurationManager.AppSettings["SiteUrl"];
            string adminUrl = ConfigurationManager.AppSettings["AdminUrl"];
            string userName = ConfigurationManager.AppSettings["AdministratorUserName"];
            string password = ConfigurationManager.AppSettings["AdministratorPassword"];
            var securePassword = new SecureString();
            foreach (var c in password) { securePassword.AppendChar(c); }

           Console.WriteLine("Start: Allow customisations...");
           DisableDenyAddAndCustomizePages(adminUrl, siteUrl, userName, securePassword);
            Console.WriteLine("End: Allow customisations... \n");
}

public static void DisableDenyAddAndCustomizePages(string adminUrl, string siteUrl, string userName, SecureString securePassword)
        {
            using (var ctx = new ClientContext(adminUrl))
            {
                ctx.Credentials = new SharePointOnlineCredentials(userName, securePassword);

                Tenant tenant = new Tenant(ctx);
                var siteProperties = tenant.GetSitePropertiesByUrl(siteUrl, true);
                ctx.Load(siteProperties);
                ctx.ExecuteQuery();

                siteProperties.DenyAddAndCustomizePages = DenyAddAndCustomizePagesStatus.Disabled;
                var result = siteProperties.Update();
                ctx.Load(result);
                ctx.ExecuteQuery();
                while (!result.IsComplete)
                {
                    Thread.Sleep(result.PollingInterval);
                    ctx.Load(result);
                    ctx.ExecuteQuery();
                }
            }
 }

ALSO, here is the code in PowerShell if you just want to quickly run it once:

Clear-Host
$spOnlineUser = ''
$spOnlinePassword = ''
$spOnlineSiteAdminUrl = ''
$spOnlineSiteUrl = ''
 
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $spOnlineUser, $(convertto-securestring $spOnlinePassword -asplaintext -force)
Connect-SPOService -Url $spOnlineSiteAdminUrl -Credential $cred
Write-Host "Connecting to " $spOnlineSiteUrl
 
$site = Get-SPOSite -Identity $spOnlineSiteUrl
Write-Host "Connection Successful!!" -ForegroundColor "Green"

Set-SPOSite -Identity $spOnlineSiteUrl -DenyAddAndCustomizePages 0

Write-Host "Finished!!" -ForegroundColor "Green"

 

SharePoint JavaScript Multi Select Choice Field – return nice format

Getting some event items from SharePoint in JavaScript? Have a multiselect choice field for caragories? Here's some handy JavaScript for cleaning out the rubbish ';#' and returning a nice comma delimited list

function cleanArray(actual){
  var newArray = new Array();
  for(var i = 0; i<actual.length; i++){
      if (actual[i]){
        newArray.push(actual[i]);
    }
  }
  return newArray;
}

function getEventCategory(inCategoriesString)
{
        var eventCateory = '';
        var eventCategories = inCategoriesString.split(';#');
        eventCategories = cleanArray(eventCategories);
        
        if (eventCategories.length == 1)
        {
        	eventCateory = eventCategories[0];
        }
        else
        {
        	for (i = 0; i < eventCategories.length; i++)
        	{
        		if (i == eventCategories.length - 1)
        		{
        			eventCateory += eventCategories[i];
        		}
        		else
        		{
        			eventCateory += eventCategories[i] + ', ';
        		}
        	}
        }

        return eventCateory;
}

 

ContentByQuery not working with OrderBy

I had some issues where I put a content by query web part in a page and when I added the OrderBy clause, it just stopped showing anything with no errors. I ended up putting the whole query on one line with no spaces and it started working. Not that it worked with spaces and line breaks as a normal where query, but only stopped working when I added the orderby. Also if your data isn't showing, check the data mapping view fields :).  

 

<Publishing:ContentByQueryWebPart runat="server" 
            	        ChromeType="TitleOnly" 
            	        Title="Executive Team Update"
				        ItemXslLink="{{SITE_COLLECTION_URL}}/Style Library/site/stylesheets/itemstyle.xsl"
				        ItemStyle="ExecutiveUpdate"
                        ItemLimit="1"
                        DataMappingViewFields="{94f89715-e097-4e8b-ba79-ea02aa8b7adb},Lookup;{108fed99-9aa6-4776-9065-23c19a63b787},Image;{fa564e0f-0c70-4ab9-b863-0177e6ddd247},Text;{f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8},HTML;{f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8},HTML;{8c06beca-0777-48f7-91c7-6da68bc07b69},DateTime;{446b839b-6220-4c3d-8444-9041faf31257},Choice;"
				        DataMappings="TeamMember:{446b839b-6220-4c3d-8444-9041faf31257},ExecutiveTeamMember,Choice;|PublishingPageContent:{f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8},PublishingPageContent,HTML;|Description:{f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8},PublishingPageContent,HTML;|Title:{fa564e0f-0c70-4ab9-b863-0177e6ddd247},Title,Text;|LinkUrl:{94f89715-e097-4e8b-ba79-ea02aa8b7adb},FileRef,Lookup;|Created:{8c06beca-0777-48f7-91c7-6da68bc07b69},Created,DateTime;|ImageUrl:{108fed99-9aa6-4776-9065-23c19a63b787},FeaturedImage,Image;|"
                        QueryOverride="<OrderBy><FieldRef Name='Modified' Ascending='False' /></OrderBy><Where><Eq><FieldRef Name='ContentType' /><Value Type='Computed'>Executive Team Update Page</Value></Eq></Where>" />

 

Check if user is in a group in JavaScript

Useful if you want to show/hide buttons or html/controls on a page layout or in masterpage. Details from http://stackoverflow.com/questions/8841985/sharepoint-10-lists-want-to-limit-form-fields-per-user-groups/8847834#8847834

Link jquery 11 and spservices into your masterpage through script links or custom actions

function:

function IsGroupMember(GroupName)
{
    var isGroupMember = false;
    $().SPServices({
        operation: "GetGroupCollectionFromUser",
        userLoginName: $().SPServices.SPGetCurrentUser(),
        async: false,
        completefunc: function(xData, Status) {
            if($(xData.responseXML).find("Group[Name='" + GroupName + "']").length == 1)                
            {
                isGroupMember = true;
            }
        }
    });
    return isGroupMember;
}

Call function

Admin_Group = "Owners";
if (IsGroupMember(Admin_Group))
    $('.div').show;
else
    $('.div').hide();

 

Create a link in JavaScript to create a new page in pages library with custom content type

The following code should go in a page layout. This is useful for landing pages where users want to be able to quickly create pages.

Replace the content type id and url information. To find out the content type id you can navigate to the create page for your content page and look at the url. Note that this only works if you are deploying your content types with the same id every time. 

var siteCollectionUrl = window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl;
                var returnURL = siteCollectionUrl + "/newsandevents/Pages";
                var url = '/newsandevents/_layouts/15/CreatePage.aspx?List=Pages&ContentTypeId=0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900DBB9F5D2AD4B436592E51AF81B2B2560007821B1F1235E524B982C1512AFCF515C' + returnURL;
                $('.jsCreateUpdate').html('<a href="' + siteCollectionUrl + url + '">+ Create Update</a>');

 

html:

<div class="create-update jsCreateUpdate">

</div>