0

Clone user permissions on SharePoint Online – Office 365

I had a request from one my clients to clone the permissions of one user to another for a SharePoint Online site.

I had created a simple PowerShell script that automates this process. It is a very common scenario when someone leaves the organization and somebody else takes that role or you want a backup for an employee and wants the same permissions to the backup person as well

It’s a simple task and I hope the following script comes in handy for you, Happy Scripting! You can also download the script from SPO_CloneUserPermissions.ps1


<#
.SYNOPSIS
Close user permissions of user to another in SharePoint Online

.AUTHOR
Susheel Dakoju

.DATE
04/21/2017

.DESCRIPTION
1. Fetch all the groups that the user is part of
2. Add ActualUser to the same groups

.Note
- This script requires admin privileges on the machine that is being executed on!
-
#>

#SharePoint online Admin site URL
$SPOAdmiURL = "https://yoursite-admin.sharepoint.com/"
$username = "username@onmicrosoft.com"
$password = "@@@@@@@@"

#Url of the SharePoint Online Site
$SPOSiteURL = 'https://yoursite.sharepoint.com/sites/test'

#User used as reference
$ReferenceUser = 'sdakoju@onmicrosoft.com'
#The actual user that needs to be added to Groups
$ActualUser = 'rkevin@onmicrosoft.com'

#Create a credential object
$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force)

#Connect to SharePoint Online using the credentials
Connect-SPOService -Url $SPOAdmiURL -Credential $cred

#Get the SharePoint Online Site Object
$site = Get-SPOSite $SPOSiteURL

#Get the user object of the reference user
$user = Get-SPOUser -Site $site -LoginName $ReferenceUser

#Loop through Groups and add the actual user
$user.Groups | Foreach-Object {

#Fetch Group Object that the reference user is part of
$group = Get-SPOSiteGroup -Site $site -Group $_

#Add 'ActualUser' to the same group that the reference user is part of
Add-SPOUser -Site $SPOSiteURL -LoginName $ActualUser -Group $group.LoginName

}

Note:

– It is assumed that you have SharePoint Online module installed on the machine you are running this script. If you do not have, please follow this link to download SharePoint Online Management Shell

– I had the following errors while running the script, I am jotting them here as they may be helpful for you.

Error 1:

  • Identity Client Runtime Library (IDCRL) could not look up the realm information for a federated sign-in. Or
  • The partner returned a bad sign-in name or password error. For more information, see Federation Error-handling Scenarios. Or
  • The ‘username’ argument is invalid. Or
  • The partner returned a bad sign-in name or password error. For more information, see Federation Error-handling Scenarios.

Solution:

  • I was using a wrong username. Please make sure you have right admin username and password for the SharePoint Online site that you are running against.

Error 2:

  • The site https://yoursite.sharepoint.com/sites/test/ is not properly formed

Solution:

  • There is a trailing slash at the end of the URL it should be ‘https://yoursite.sharepoint.com/sites/test’ and NOT ‘https://yoursite.sharepoint.com/sites/test/’
0

Using JavaScript Promises with SharePoint 2013 – Deferring executeQueryAsync to be a little Synchronous

If you have worked with Asynchronous programming, its no brainier that you might have enjoyed writing highly performing apps.

But I am sure you might have felt at some rare occasions that “Alas! I wish if this small portion of my code works synchronously and dammit wait for an action to complete!”. 

Most of the time its always fire-and-forget scenario with asynchronous calls, but there are certain scenarios where you want your code to return something. Especially this gets even tricky if you are working with asynchronous logic within loops. JavaScript Promise comes to your rescue!

This blog post is not meant to educate you on JQuery or JavaScript Promises, but just to give you an idea of something like this exists and how you can use it with SharePoint. I will not leave you disappointed, following are some good articles that will get you started.

Article 1: http://blog.qumsieh.ca/2013/10/31/using-jquery-promises-deferreds-with-sharepoint-2013-jsom/

Article 2: http://www.vasanthk.com/jquery-promises-and-deferred-objects/

Spread the word for your fellow developers

“JavaScript Promise 

I was working on a typical use-case of updating SharePoint list items for a SharePoint Online site. Let me explain the use case in detail, I have two SharePoint lists, one is a SharePoint Document Library and the other is a Custom list. Document library has to be updated based on certain values from the Custom list. Of course, the data has to be manipulated based on certain conditions and multiple business rules before updating the document library.

Initial thought process would be to use any of the tools at disposal or use out-of-the-box features to get this working, but after an exhaustive research over the internet, I could not find any way to accomplish this with no customization. So as a last resort, I decided to write some code.

NOTE: This is SharePoint online site, REST API or JSOM (Java Script Object Model) would be the default choices. I am using JavaScript for this example.

Following is the general thought process

Step 1: Get the list of items asynchronously  from Source List (i.e. SharePoint Custom List)

Step 2: Loop through the items and update the Destination List (i.e. SharePoint Document Library)

Ideally everything should work seamlessly, but Step 2 will fail with asynchronous way of programming. When you loop through the items that are fetched from Source List it works great, but any updates or actions that you perform with in a loop may not work.

Loop proceeds irrespective of action being complete or not. If you are dealing with one item and no-loop involved it works fine. But I am dealing with hundreds of items with too many of these loops.

Using JQuery Promise for SharePoint 2013

 

NOTE:

Following  code has clear and detailed inline comments. Everything should be self explanatory!

Following code has been developed for one-time use only and is meant for educational purposes only and not recommended for production use. I can say upfront that the naming conventions, error handling/logging are not production ready. You may need to make updates to the code and may require some re-work. Of course, there is always a better way doing things.Use at your own risk!


<!--Add JQuery reference-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>

<script type="text/javascript">

//Get the source list items to loop through and update the destinantion list.
function GetSourceListItems() {

//Assign the name of the list to use as Source List
var strSourceListName = "SourceListName";

//Get the current SharePoint Context: Represents the context for objects and operations
var oContext = SP.ClientContext.get_current();

//Get the current web
var oWeb = oContext.get_web();

//Get the source list using the Name or GUID
var oList = oWeb.get_lists().getByTitle(strSourceListName);

//CAML Query to query the Source List
//Following is the Query to get items less than ID 800.
var strQuery = '<View><Query> <Where> <Leq> <FieldRef Name=\'ID\' \/> <Value Type=\'Counter\'>800<\/Value> <\/Leq> <\/Where> <\/Query><\/View>';
var oQuery = new SP.CamlQuery();
oQuery.set_viewXml(strQuery);

//Get the items based on Query
var allItems = oList.getItems(oQuery);
oContext.load(allItems);

//Make an asynchronous call.
oContext.executeQueryAsync(Function.createDelegate(this, function () { onQuerySuccess(allItems); }),
Function.createDelegate(this, this.onQueryFailed));
}

//On Query success loop through the items and update the destination list:
function onQuerySuccess(allItems) {

//Returns an enumerator that iterates through the SP.ClientObjectCollection Class.
var ListEnumerator = allItems.getEnumerator();

//Names of the columns in the source list to use
var sourceColumnArray = ["SourceListColumn1", "SourceListColumn2", "SourceListColumn3"];

//Iterate though list items and update the destination list.
while (ListEnumerator.moveNext()) {
//Get the current item
var currentItem = ListEnumerator.get_current();

//Create an array of values that should be used to update the destination list.
var valuesArray = [];

//Loop through the source column array and populate the array.
for (var i = 0; i < sourceColumnArray.length; i++) {
var value = currentItem.get_item(sourceColumnArray[i]);
valuesArray.push(value);
}

//Get the value of the common key that relates both the Source and Destination Lists.
//Use the same key to query against the destination list.
var commonKey = currentItem.get_item('commonColumnName');

//Check the length of array and send it update the destination list.
if (valuesArray.length > 0) {
UpdateDestinationListItem(commonKey, valuesArray);
}
}
}

//On Query failure log message
function onQueryFailed(sender, args) {
//Log Error
}

//Update the destination list
//Use common key to query the distination list
//Use values array to update the values of the desination list
function UpdateDestinationListItem(commonKey, valuesArray) {
//****Important 1.0****//
//Use of JQuery deferred
var d = $.Deferred();

//Give the name of the distination list to update with values.
var destinationListName = "DestinationListName";

//Use the key from the source list to query the destination list.
var strDistinationCAMLQuery = '<View><Query><Where><Eq><FieldRef Name=\'FileLeafRef\' \/> <Value Type=\'File\'>' + commonKey + '<\/Value> <\/Eq> <\/Where> <\/Query><\/View>';

//Get the current SharePoint Context: Represents the context for objects and operations
var oClientContext = SP.ClientContext.get_current();

//Get the current web
var oWeb = oClientContext.get_web();

//Get the destination list using the Name or GUID
var oDestinationlist = oWeb.get_lists().getByTitle(destinationListName);

//Specifies a Collaborative Application Markup Language (CAML) query on a list or joined lists.
var oCamlQuery = new SP.CamlQuery();
oCamlQuery.set_viewXml(strDistinationCAMLQuery);

//Get the list of items using the CAML Query
var oCollListItem = oDestinationlist.getItems(oCamlQuery);
oClientContext.load(oCollListItem);

//****Important 2.0****//
//Use of JQuery deferred
//Send list of items, client context, array of values from Source List
var o = { d: d, listOfItems: collListItem, clientContext: clientContext, valuesArray: valuesArray };

clientContext.executeQueryAsync(Function.createDelegate(o, successCallback), Function.createDelegate(o, failCallback));

return d.promise();

function successCallback() {

var itemCount = this.listOfItems.get_count();

var destinationColumnArray = ["DestinationListColumn1", "DestinationListColumn2", "DestinationListColumn3"];

var listItemInfo;

if (itemCount > 0) {
//****Important 3.0****//
//Use of JQuery deferred: Using 'listOfItems'
var listItemEnumerator = this.listOfItems.getEnumerator();

//Iterate though the list of items fetched from destination list
while (listItemEnumerator.moveNext()) {

var oCurrentListItem = listItemEnumerator.get_current();

for (var i = 0; i < destinationColumnArray.length; i++) {
//Write to console for debugging
console.log('Updating Value');

//****Important****//
//Destination list item getting updated.
oCurrentListItem.set_item(destinationColumnArray[i], this.valuesArray[i]);

//Write to console for debugging
console.log('Update Successfull');
}
oCurrentListItem.update();

this.clientContext.executeQueryAsync(onUpdateItemSuccess, onUpdateItemFailed);
}
}
}

function failCallback() {
this.d.reject("Failed at failCallback() method");
}

function onUpdateItemSuccess() {
console.log("Item Updated Sucessful");
}

function onUpdateItemFailed() {
console.log("Item Updated Failed");
}
}
</script>

I am not sure if this blog post helped you with what you wanted, but I would be glad if  you have discovered about JavaScript Promises for the first time via my blog post. Happy Coding!

0

Provider Hosted App (Add-in) on SharePoint Online in 5 steps – Step 5/5

Step 5: Create Publishing Profiles for SharePoint Online and publish

  • Create a new Publishing Profile for SharePoint app and provide the Client ID and Client Secret

New Publishing Profile to deploy SharePoint APP

New Publishing Profile to deploy SharePoint APP Step 2

New Publishing Profile to deploy SharePoint APP Step 3

Publish the app or Hit F5. An you should see similar screens as below

App Install Page

  • Following is the screen capture of the app, this is just a simple HTML and JavaScript added to default.aspx page.

SharePoint Online Showing the Final App

Note:  This blog post has been to split into multiple posts as they render fast with fewer images and it will greatly enhance the experience for readers accessing this via mobile devices

0

Provider Hosted App (Add-in) on SharePoint Online in 5 steps – Step 4/5

Step 4: Create Publishing Profiles for Azure Web App and publish

Create a new Publishing Profile for Azure web app and publish

  • Import the azure Publishing Profile downloaded in Step 1
    Import Publishing Profile
  • Once you import the publish settings files you will fine similar to following and validate your connectionImport Publishing Profile Summary

Select Profile Debug Publish

  • Preview will show the files that will be published to Azure Web App.

Optional Preview Step

  •  Publish the Azure Web App.

Continue to Step 5: Create Publishing Profiles for SharePoint Online and publish>>

 

Note:  This blog post has been to split into multiple posts as they render fast with fewer images and it will greatly enhance the experience for readers accessing this via mobile devices

0

Provider Hosted App (Add-in) on SharePoint Online in 5 steps – Step 3/5

Step 3: Register the app and update the Visual Studio

  • Step 3 a: Register the app in SharePoint
    • Go the URL on your SharePoint Online Site: https://yourname.sharepoint.com /_layouts/15/appregnew.aspx
    • Click generate for Client Id and Secret, new ids will be generated
    • Give a title to the app of your choice
    • Add app domain: This is your Azure web app with out HTTP or HTTPS
    • Redirect URI: You may enter the URI: http://yourazureurl/default.aspx
      • This part is tricky there are developers that use just HTTP and no /default.aspx in the end
    • Please follow Register SharePoint Add-in from MSDN for more informationRegister App on SharePoint online

      This is the most important step of all. Please save the following info you need this information later on!!

      App Identier Created Successfull Message

  • Step 3 b: Update web.config file of the Azure Web App Project: Update ‘Client Id’ and ‘Client Secret’
  • Web Config Changes for Azure Web App
  • Step 3 c :Update the Permissions section of Manifest.xml by double clicking the the fileChange the App Manifest Permissions
  • Step 3 d: Update code of Manifest.xml by right clicking the file and click ‘<> View Code’App Manifest Code File Changes

Continue Step 4: Create Publishing Profiles for Azure Web App and publish>>

Note:  This blog post has been to split into multiple posts as they render fast with fewer images and it will greatly enhance the experience for readers accessing this via mobile devices

0

Provider Hosted App (Add-in) on SharePoint Online in 5 steps – Step 2/5

Step 2: Configure Visual Studio for development

Step 2 a: Create a new project of Type ‘Apps for SharePoint’

Create Visual Studio Project

Enter the SharePoint Site URL where this app needs to be deployed and select Provider-hosted

Site Name and Select Provider Hosted APP

You will prompted to enter your office 365 credentials to select the version of the SharePoint

Connect Visual Studio with Office 365

Please select SharePoint Online

Select the SharePoint version

Leave the default Option, unless you want to use certificate authentication.

App Authentication

Choose the web application project of your choice

Select Web Application Type

  • Two projects will be created
    • One for SharePoint online – ThermoConverterApp
    • One for Azure Web App     – ThermoConverterAppWeb

If you publish/deploy ‘ThermoConverterAppWeb’ it will be deployed to Azure and the if you deploy/publish ‘ThermoConverterApp’ it will be deployed to SharePoint. Notice the icons to differentiate better.

Visual Studio with two project

Once you are complete with all the above steps, please check the properties of project, the ‘SiteURL’ should match your SharePoint Online site.

SharePoint Project Properties

Continue to Step 3: Register the app and update the Visual Studio>>

Note:  This blog post has been to split into multiple posts as they render fast with fewer images and it will greatly enhance the experience for readers accessing this via mobile devices

1

Provider Hosted App (Add-in) on SharePoint Online in 5 steps – Step 1/5

This blog post is a mere refresher to the folks who already know what SharePoint apps are and also know the basic difference between SharePoint hosted and Provider hosted app.

This blog post unfortunately does not get into the weeds but focuses on quickly connecting all the dots to quickly set up a provider hosted app for development. If you would like to choose pattern for your development read this MSDN Article

A picture is worth a thousand words, most of the blog post will have loads of images and they will speak for them selves.

Let’s get started! Following are the steps to get a basic Provider Hosted App up and running!

Step 1:  Create a Azure Web App to host your code and download Publishing Profile

Step 2:  Configure Visual Studio for development

  • Step 2 a: Create a new project of Type ‘Apps for SharePoint’
  • Step 2 b: Choose .NET 4.5 as target framework
  • Step 2 c: Enter the SharePoint Site URL where this app needs to be deployed
  • Step 2 d: Choose the type of app as ‘Provide hosted app’
  • Step 2 e: Enter Office 365 Credentials to connect visual studio with Office 365
  • Step 2 f:  Create a new publishing profile, import the Azure web app profile and Publish

Step 3: Register the app and update the Visual Studio

Step 4: Create Publishing Profiles for Azure Web App and publish

Step 5: Create Publishing Profiles for SharePoint Online and publish

Step 1: Create a Azure Web App to host your code and download Publishing Profile 

Create New Web App

Create Azure Web App

Create Azure Web App Running

Download Publishing Profile

  • Download publishing settings and save it for later use in Step 4

Download Publishing Profile

Continue to Step 2 :Configure Visual Studio for development >>

Note:  This blog post has been to split into multiple posts as they render fast with fewer images and it will greatly enhance the experience for readers accessing this via mobile devices