Flow: Set permissions using REST API without app permissions

In my last blog post Flow: Set permissions using REST API, I explained how to use the HTTP action and the app permissions. With the HTTP action you can start web services from SharePoint but also from other solutions.
In this blog post I will explain an easier way of using the SharePoint REST API. This setup does not require setting the app permissions. We can simply use the action Send an HTTP request to SharePoint.

Creating the Flow

  • First, we will break the inheritance.
  • Create a Flow with the required trigger.
  • Add the Initialize variable.
  • Rename it to Initialize variable – User Principle ID.
  • Set the name to User Principle ID.
  • Set the type to String.
  • Add the Send an HTTP request to SharePoint action.
  • Change the name to Send an HTTP request to SharePoint – Break inheritance.
  • Select or set the correct Site Address.
  • Set the Methode to POST.
  • The URI is different for every item/list you want to manipulate.
  • _api/lists/getbytitle(‘<list display name>’)/items(<ITEM ID>)/breakroleinheritance(true)
  • Set the Headers as follows.
  • The key is Accept
  • The value is application/json;odata=verbose
  • Now we will look up the user’s information.
  • Add the Send an HTTP request to SharePoint action.
  • Change the name to Send an HTTP request to SharePoint – Get User Info.
  • Select or set the correct Site Address.
  • Set the Methode to GET
  • The URI is different for every item/list you want to manipulate.
    _api/web/siteusers/getbyemail(‘<email address>’)
  • Set the Headers as follows.
  • The key is Accept
  • The value is application/json;odata=verbose
  • Add the Parse JSON action.
  • Set the Content to Body (the result of the Get User info action).
  • Change the name to Parse JSON – Get User Principal ID.
  • Use the following Schema to parse the JSON. This will give you more than you will not for this example. I add this Schema, so you have access to more information if required.
{
    "type": "object",
    "properties": {
        "d": {
            "type": "object",
            "properties": {
                "Alerts": {
                    "type": "object",
                    "properties": {
                        "__deferred": {
                            "type": "object",
                            "properties": {
                                "uri": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "Groups": {
                    "type": "object",
                    "properties": {
                        "__deferred": {
                            "type": "object",
                            "properties": {
                                "uri": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "Id": {
                    "type": "integer"
                },
                "IsHiddenInUI": {
                    "type": "boolean"
                },
                "LoginName": {
                    "type": "string"
                },
                "Title": {
                    "type": "string"
                },
                "PrincipalType": {
                    "type": "integer"
                },
                "Email": {
                    "type": "string"
                },
                "Expiration": {
                    "type": "string"
                },
                "IsEmailAuthenticationGuestUser": {
                    "type": "boolean"
                },
                "IsShareByEmailGuestUser": {
                    "type": "boolean"
                },
                "IsSiteAdmin": {
                    "type": "boolean"
                },
                "UserId": {
                    "type": "object",
                    "properties": {
                        "__metadata": {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "type": "string"
                                }
                            }
                        },
                        "NameId": {
                            "type": "string"
                        },
                        "NameIdIssuer": {
                            "type": "string"
                        }
                    }
                },
                "UserPrincipalName": {
                    "type": "string"
                }
            }
        }
    }
}
  • Add the Set variable action.
  • Change the name to Set variable – User Principle ID.
  • Select by name the variable User Principle ID.
  • Set the value to ID (the ID output from Parse JSON – Get User Principal ID)
  • Now we will grant a user permissions, I am granting the challenger (property of the item) contribution access.
  • Add the Send an HTTP request to SharePoint action.
  • Change the name to Send an HTTP request to SharePoint – Grant Contribute permissions.
  • Select or set the correct Site Address.
  • Set the Methode to POST.
  • The URI is different for every item/list you want to change.
    <site url>/_api/lists/getbytitle(‘<list display name>’)/items(<ITEM ID>)//roleassignments/addroleassignment(principalid='<d.ID>’roleDefId=1073741827)
  • The id 1073741827 stands for contributor, in my blog post SharePoint: Get the Role ID you can read more about role id’s.
  • Your Flow will now look like this.

Flow: Set permissions using REST API

For a customer I am creating Microsoft Flows to support various business processes. One Flow controls the process of reviewing and approving vital business documents. These documents are so important that during the day to day business the reviewers and approvers are unable to edit these documents. Only when the documents are in review a select few are allowed to edit them.

Microsoft Flow contains many default actions for all sorts of tasks, but
during the writing of this blog post there is no default action that can set permissions or break the inheritance.

In this blog post I will explain how set custom permissions, break the inheritance and restore the inheritance using the REST API.

Register app and grant app permissions

For the Flow to work we will need to Register an App and grant it permissions. During the registration of the App we will receive various id’s we will use in the Flow.

  • Navigate to the app registration page on the SharePoint site.
https://<tenant>.sharepoint.com/_layouts/15/appregnew.aspx
  • Generate a Client ID and Client Secret.
  • Set the Title to Flow Web Service
  • Set App Domain to www.localhost.com
  • Set Redirect URI to https://www.localhost.com
  • Save the generated Client Id and Client Secret.
  • Navigate to the Grant permissions to an app page. This must be done by browsing to the appinv.aspx page of the site.
http://<hostname>/<the Site Collection>/_layouts/15/appinv.aspx
  • Fill in the Client Id and click on Lookup
  • Now we will grant the App full control access to the site collection.
  • Set the following XML as the Permission Request XML
<AppPermissionRequests>
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" />
</AppPermissionRequests>
  • Click on Create.
  • A pop-up screen will appear asking to Trust the App, click on Trust It.
  • The App has been granted permissions and can be used in the Flow.

Creating the Flow

  • Create a Flow with the required trigger.
  • Add two initialize variable actions for the Token type and Access token.
  • Add the HTTP action to acquire the access token and type.
  • Set the name to HTTP – Request access token and type
  • Set the Method to POST.
  • The URI is different for every tenant, you will need to your tenant id.
  • https://accounts.accesscontrol.windows.net/<tenant ID>/tokens/OAuth/2
  • Set the Headers as follows.
  • The key is Content-Type
  • The value is application/x-www-form-urlencoded
  • For the body you will need the tenant ID, client_credentials, client_id and client_secret.
  • grant_type=client_credentials&client_id=
    <Client ID>@<Tenant ID&client_secret=<Encoded Client Secret>&resource=00000003-0000-0ff1-ce00-000000000000/<tenant>.sharepoint.com@<Tenant ID>
  • Add a Parse JSON action.
  • Set the content to the BODY (result) of the HTTP – Request access token and type action.
  • Use the following Schema to parse the JSON.
{
    "type": "object",
    "properties": {
        "token_type": {
            "type": "string"
        },
        "access_token": {
            "type": "string"
        }
    }
}
  • Set the variable Token type and Access token using the results of the parsed JSON.
  • Now you can break the inheritance, add a HTTP action.
  • Set the name to HTTP – break inheritance.
  • Set the Method to POST.
  • The URI is different for every item/list you want to change.
  • <site url>/_api/lists/getbytitle(‘<list display name>’)/items(<ITEM ID>)/breakroleinheritance(true)
  • Set the Headers as follows.
  • The key is Authorization
  • The value is the Token type and Access token variable. Make sure to add a space between the variables.
  • The key is Accept
  • The value is application/json;odata=verbose
  • Now you can grant an user permissions, I am granting the challenger (property of the item) contribution access.
  • Add a HTTP action, with this action we will get the users information.
  • Set the name to HTTP – Get User info
  • Set the Method to GET
  • The URI is different for every location where you want to get the information from.
    <site url>/ _api/web/siteusers/getbyemail(‘<Challengers email>’)
  • Set the same Headers as before.
  • Add the Parse JSON action, name is Parse JSON – Get User Principal ID
  • Set the content to the BODY (result) of the
    HTTP – Get User info action
  • Add the following Schema to the Use sample payload to generate the schema option.
  • Make sure to enter your own account details.
{
  "d": {
    "results": [
      {
        "Id": 9,
        "LoginName": "i:0#.f|membership|<youraccount>",
        "Title": "<your name>",
        "PrincipalType": 1,
        "Email": "<youremail>",
        "IsSiteAdmin": true
      },
      {
        "Id": 14,
        "LoginName": "i:0#.f|membership|<youraccount>",
        "Title": "Example Title",
        "PrincipalType": 1,
        "Email": "<youremail>",
        "IsSiteAdmin": false
      }
  
    ]
  }
}
  • Add a HTTP action, set the name to HTTP – Grant contribute permissions
  • Set the Method to POST
  • The URI is different for every item/list you want to change.
    <site url>/_api/lists/getbytitle(‘<list display name>’)/items(<ITEM ID>)//roleassignments/addroleassignment(principalid='<d.ID>’roleDefId=1073741827)
  • The id 1073741827 stands for contributor, in my blog post SharePoint: Get the Role ID you can read more about role id’s.
  • Set the same Headers as before.
  • Now you can reset the inheritance if needed, add a HTTP action
  • Set the name to HTTP – Reset Role Inheritance
  • Set the Method to POST
  • The URI is different for every item/list you want to change.
    <site url>/_api/lists/getbytitle(‘<list display name>’)/items(<ITEM ID>)/resetroleinheritance
  • Set the same Headers as before.
  • Your Flow will now look like this.

Flow: Performance issue

In my previous blog post Flow: Start a flow with another flow I talked about a flow that was becoming very big and slow. In this blog post I will explain why the Flow was very slow and how you can prevent this from happening.

The purpose of the Flow was to convert a complete SharePoint List into a comma separated Excel file. This was not a simple extract but also various data manipulations and user profile data request where required. The Flow ended up with a large number of for each loops and unique variables.

Reason 1: Too many of the action Initialize variable

The Flow contained too many unique variables. I noticesd hat there was a steep incline in the overall processing time when I added more and more unique variables. It started to become slow after about 12 variables. Try too avoid to many unique variables.

Reason 2: Nested for each loops

The Flow also contained too many nested Apply to each actions. This slowed down the Flow but much less than the unique variables. Try too avoid nested loops.

Turn scripting capabilities on

By default scripting capabilities are turned off in Office 365. This will prevent the use of a set of settings and a larger number of web parts.
The administrator of the environment can enable scripting in SharePoint admin center. When scripting is turned on it takes about 24 hours for the change to take effect.

Solution
1. Sign in to Office 365.
2. Open the admin center.
Open Admin Center
3. Open the SharePoint admin center.
Open SharePoint admin
4. Click on settings.
5. Set custom scripting to allow.
Allow scripting
6. Save the changes and wait 24 hours.

The following web part, features are settings are effected by the turning scripting on/off. When scripting is disabled (off) these functions will be unavailable to administrators.

Effect Web parts and features
Web Part Category Web Part
Blog Blog Archives
Blog Notifications
Blog Tools
Business Data Business Data Actions
Business Data Item
Business Data Item Builder
Business Data List
Business Data Related List
Excel Web Access
Indicator Details
Status List
Visio Web Access
Community About This Community
Join
My Membership
Tools
What’s Happening
Content Rollup Categories
Project Summary
Relevant Documents
RSS Viewer
Site Aggregator
Sites in Category
Term Property
Timeline
WSRP Viewer
XML Viewer
Document Sets Document Set Contents
Document Set Properties
Forms HTML Form Web Part
Media and Content Content Editor
Script Editor
Silverlight Web Part
Search Refinement
Search Box
Search Navigation
Search Results
Search-Driven Content Catalog-Item Reuse
Social Collaboration Contact Details
Note Board
Organization Browser
Site Feed
Tag Cloud
User Tasks
Master Page Gallery Can’t create or edit master pages
Publishing Sites Can’t create or edit master pages and page layouts

 

Effected sites settings
Site Feature Behavior Notes
Save Site as Template No longer available in Site Settings. You can still build sites from templates created before scripting was disabled.
Save document library as template No longer available in Library Settings. You can still build document libraries from templates created before scripting was disabled.
Solution Gallery No longer available in Site Settings. You can still use solutions created before scripting was disabled.
Theme Gallery No longer available in Site Settings. You can still use themes created before scripting was disabled.
Help Settings No longer available in Site Settings. You can still access help file collections available before scripting was disabled.
HTML Field Security No longer available in Library Settings. You can still use HTML field security that you set up before scripting was disabled.
Sandbox solutions Solution Gallery will not appear in the Site Settings so you can’t add, manage, or upgrade sandbox solutions. You can still run sandbox solutions that were deployed before scripting was disabled.
SharePoint Designer Site Pages: No longer able to update web pages that are not HTML.
Handling List: Create Form and Custom Action will no longer work.
Subsites: New Subsite and Delete Site redirect to the Site Settings page in the browser.
Data Sources: Properties button is no longer available.
You can still open data sources.
Uploading files that potentially include scripts The following file types can no longer be uploaded to a library
.asmx
.ascx
.aspx
.htc
.jar
.master
.swf
.xap
.xsf
Existing files in the library are not impacted.

SharePoint 2013 CQWP Office Online hyperlink

With the introduction of Office Online (Office web apps) files can be opened in the browser with Office Online (Office web apps) or with the local client. If able SharePoint 2013 will open files (.pptx, docx, xslx) in office Online and other files in the related client (doc, xsl, pdf etc.) This behavior works great within the document library, however this does not work out of the box for files that are displayed using a content query webpart. With XSLT we are able to create an variable which creates per file the required hyperlink.

Solution
1. Edit the CQWP Template where the semi dynamic hyperlink is required.
2. First we need to create the variable that builds the correct office online or default hyperlink. The default hyperlink opens the files in the client software.

<xsl:variable name="DynamicURL">
   <xsl:choose>						
      <xsl:when test="contains(@FileExtension,'docx')">
         /sites/PH/OH/_layouts/WopiFrame.aspx?sourcedoc=<xsl:value-of select="@LinkUrl"/>	
      </xsl:when>
      <xsl:when test="contains(@FileExtension,'pptx ')">
         /sites/PH/OH/_layouts/WopiFrame.aspx?sourcedoc=<xsl:value-of select="@LinkUrl"/>	
      </xsl:when>
      <xsl:when test="contains(@FileExtension,'xslx')">
         /sites/PH/OH/_layouts/WopiFrame.aspx?sourcedoc=<xsl:value-of select="@LinkUrl"/>	
      </xsl:when>
      <xsl:otherwise>
         <xsl:value-of select="@LinkUrl"/>
      </xsl:otherwise>
   </xsl:choose>
</xsl:variable>

3. The choose function determines the file type and sets the correct Office Online hyperlink or the default Hyperlink based of LinkUrl field.
4. Secondly we need to use the DynamicURL variable to create the hyperlink.

<a href="{$DynamicURL}" target="_blank">
   <xsl:value-of select="@Name"/>
</a>

 

Result
Files with extensions docx, pptx and xslx will open in Office Online other files will open in the related client.

CQWP Hyperlink Office Online