Replace Edit with Contribute permissions with SharePoint Site TemplatesReplace Edit with Contribute permissions with SharePoint Site Templates

How do we replace Edit with contribute permissions? When you create a new team site members will have Edit permissions, but often we only want members to have Contribute permissions.

Edit vs Contribute permissions

When we look at the various permission levels in SharePoint, we can see the different between Edit and Contribute permissions within the Permission Level settings.

Edit – Can add, edit and delete lists; can view, add, update and delete list items and documents.

Contribute – Can view, add, update, and delete list items and documents.

So where Edit allows you to adjust lists and libraries, Contribute only allows users to work with content such as list items and documents.

Contribute permissions SharePoint Templates permissions
Contribute permissions SharePoint Templates

Site Scripting

For an introduction to site scripting please have a look at the Microsoft Site Scripting documentation.

Using site scripting we have the following options available to us:

  • Add Content Types From Hub
  • Create a new SharePoint list
    • setDescription
    • addSPField
    • deleteSPField
    • addSPFieldXml
    • addSPLookupFieldXml
    • addSiteColumn
    • addSPView
    • removeSPView
    • addContentType
    • removeContentType
    • setSPFieldCustomFormatter
    • associateFieldCustomizer
    • associateListViewCommandSet
    • setTitle
  • Define a new site column
  • Define a new content type
    • addSiteColumn
    • removeSiteColumn
  • Add a navigation link
  • Remove a navigation link
  • Apply a theme
  • Set branding properties
  • Set a site logo
  • Join a hub site
  • Install an add-in or solution
  • Register an extension
  • Activate a Feature
  • Trigger a flow
  • Configure regional settings
  • Add users (principals) to SharePoint Groups
  • Manage guest access

So in short, we can do a lot with site scripting! But there is no step to change permission levels. Or is there …

As we look at the options available to us, we ca do anything we want as we can call a flow, and a flow can call a SharePoint REST API.

Running a flow from a site script

To trigger a flow from a site script, we will need to use the When an HTTP request is received trigger.

Add When an HTTTP request is received action
Add When an HTTTP request is received action

Once you have saved the flow, the trigger will give you a HTTP POST URL.

Get the URL for from the Power Automate trigger
Get the URL for from the Power Automate trigger

Within the Site script we will use the URL that we have been given within a section that looks like this:

{
              "verb": "triggerFlow",
              "url": "https://prod-29.uksouth.logic.azure.com:443/workflows/590fd5c21acf435aa1d85a665927060d/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=....",
              "name": "Provision Site"              
            }

Notice that the trigger Flow section should be added at the end of all the steps. Placing it earlier in the site script could result in timing issues , if your flow depends on the other steps within the site script

Now the next step in our flow. The trigger will return the a record like this to us:

{
  "webUrl": "https://myorg.sharepoint.com/sites/PVTest2",
  "webTitle": "PV Test 2",
  "webDescription": "PV Test 2",
  "groupId": "22141721-0733-4a61-a628-0a438495551c",
  "creatorEmail": "PVTest2@myorg.onmicrosoft.com",
  "creatorName": "PV Test 2 Owners",
  "createdTimeUTC": "11/27/2023 9:31:58 AM"
}

By adding a Parse JSON step in our flow and renaming this to SiteDetails. We will make things a bit easier for ourselves.

Replace COntribute (BROKEN LINK)3
Replace COntribute (BROKEN LINK)3

The schema, of the data should look like this:

{
    "type": "object",
    "properties": {
        "webUrl": {
            "type": "string"
        },
        "webTitle": {
            "type": "string"
        },
        "webDescription": {
            "type": "string"
        },
        "groupId": {
            "type": "string"
        },
        "creatorEmail": {
            "type": "string"
        },
        "creatorName": {
            "type": "string"
        },
        "createdTimeUTC": {
            "type": "string"
        }
    }
}

Why use a parse JSON? We could just specify the schema on the trigger. Well, yes we could specify the schema at the trigger level. However when we specify the schema on the trigger, the trigger could fail, if we got the schema wrong. Most of the time it is better not to validate data at the trigger level. As error handling becomes easier once the flow has been started.

My Requirements, Replace Edit with Contribute permissions

In my case I want to change the permissions of the Members group from Edit to Contribute on the site that the site design/script is applied to.

Where the out of the box team sites gives us a Members group with Edit permissions I will now want this to be set to Contribute. So we will need to replace Edit with Contribute.

Replace Contribute (BROKEN LINK)2
Replace Contribute (BROKEN LINK)2

Get SharePoint Groups

I will first need to get our SharePoint group using the SharePoint REST API. I would have liked to use OData Filters, however I’m looking for a filter like.

_api/web/SiteGroups?$filter=endswith(Title, ' Members')

However the endswith is not supported in this case. So we will have to get all the site groups as shown below using a Send an HTTP request to SharePoint action:

Get SharePoint site groups
Get SharePoint site groups

And then we can use the Filter Array action to get the right group only.

Members group
Members group

The From is set to : body(‘Get_Groups_found_on_site’).value

While the Filter Query is set to item().Title

We should now have the following flow.

replace contribute (BROKEN LINK)
replace contribute (BROKEN LINK)

To replace Edit with Contribute we will need to go through two steps. First we add the contribute and then we will remove the edit permissions.

Add Contribute Permissions to a group

Continuing with the Send an HTTP request to SharePoint action, we can create the following step:

Add contribute permissions
Add contribute permissions

The expression used to get the PrincipalId within the endpoint Uri is as follows:

_api/web/RoleAssignments/AddRoleAssignment(PrincipalId=@{First(body('Members_Group')).Id},RoleDefId=1073741827)

Remove Edit Permissions from a group

Similar to the adding of the Contribute permissions we can also remove the edit permissions.

Remove Edit permissions
Remove Edit permissions
_api/web/RoleAssignments/RemoveRoleAssignment(PrincipalId=@{First(body('Members_Group')).Id},RoleDefId=1073741830)

As we’ve seen there is a RoleDefId that represents the Contribute(1073741827) and the Edit (1073741830).

And that is it, with a small flow I’ve now replace Edit with Contribute permissions on the site that had the template applied. When using this in production you should of course always add the try catch pattern, so that you can handle any issues.

Replace contribute parameters
Replace contribute parameters
Avatar for Pieter Veenstra

By Pieter Veenstra

Business Applications Microsoft MVP working as the Head of Power Platform at Vantage 365. You can contact me using contact@sharepains.com

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from SharePains by Microsoft MVP Pieter Veenstra

Subscribe now to keep reading and get access to the full archive.

Continue reading