Permissions

Repairing List Item Permission Actions in Exported Nintex Workflows

While working on a sizeable SharePoint and Nintex Workflow development project recently, I came across a significant issue in Nintex Workflow that the support engineers at Nintex said was not a bug. I disagree with them, and had to find a workaround anyway, so thought I would share it.

The Problem

If you export a workflow from one SharePoint system (e.g. a development farm), and import it into a different SharePoint system (e.g. a production farm), if you are using the “Set Item Permissions” action within your workflow, you will discover that it is broken after importing. I did a bit of digging, and discovered why – the exported workflow describes the permissions sets in XML by both their name, and their internal IDs (large integers) – but only seems to use the IDs when importing – Nintex Workflow doesn’t try to correlate the permission sets by name on the destination system, so presumes it cannot find the permission sets described in the workflow actions.

It’s worth repeating – the Nintex support engineer I dealt with said this was by design. I was quite shocked.

The Solution

If you’re working on a sizeable project, you probably have all the workflows exported to a folder on the filesystem. You can therefore process the files to replace the IDs from the original system with those of the target system. So – we can run the following PowerShell script on the files, while they are sitting on the destination server(s):


$url = "https://server/sites/site_collection/subsite"

$uri = [System.Uri]$url

# Loop through files in Workflows subdirectory
foreach ( $source_file in $(Get-ChildItem './Workflows' -File | Sort-Object -Property Name) ) {

    Write-Host $("Processing [" + $source_file.Name + "]") -foregroundcolor white
    
    $file_content = Get-Content "../Workflows/$source_file"
    
    # repair the role definitions in the XML
    Write-Host " - Repairing Role Definition IDs in XML"
    foreach ($role_definition in $web.RoleDefinitions){
        $pattern     = $('\#' + $role_definition.Name + '\;\#None\;\#[0-9]+\$\$\#\#')
        $replacement = $('#' + $role_definition.Name + ';#None;#' + $role_definition.Id + '$$$$##')
        $file_content = $file_content -replace $pattern , $replacement
    }
    
    # Write the file into the modified directory
    $file_content | out-file -encoding utf8 "./Workflows/Modified/$source_file"
    
    Write-Host $(" - Finished Processing [" + $source_file.Name + "]")

}

The above snippet presumes you have all your workflows in a folder called “Workflows”, alongside the PowerShell script. It also presumes a sub-folder called “Modified” exists within the Workflows folder, to put the modified workflows into. The script does a regex search for the role definition names in the XML (the permission sets), and swaps them out for the matching ones for the destination system. After running the script, you end up with a set of workflow export files that work.

In my mind, this entire situation could have been avoided if the developers at Nintex had been a bit more forward thinking. At least there is a solution.

Posted by Jonathan Beckett in Notes, 0 comments

Problems with Breaking Inheritance and Limited Access User Permission Lock Down Mode in SharePoint

What is “Limited Access User Permission Lock Down Mode” ?

Lets start this by describing a little known site collection feature called “Limited Access User Permission Lock Down Mode”. When enabled, it stops users from viewing the list that a file they have been given specific access to exists within. In some cases it seems to stop Microsoft Office from working correctly too.

The reason you might use it, is to allow a user read access to a specific file within a SharePoint Library, but not let them modify the URL in order to see the list – essentially only the URL to the file will work for them.

If you switch off the site collection feature, the user will be able to at least see the library within SharePoint containing the file they have access to.

How does this relate to Permissions ?

It just so happens I developed a PowerShell script for a client that creates sub-sites for projects – breaking permissions inheritance on each sub-site, and wiring up custom groups, and permissions for them for each sub-site (e.g. “Project A”, with groups “Project A Owners”, “Project A Members”, and so on).

It turns out the method used in the PowerShell script to break permissions inheritance on the sub-site was incorrect (although advocated by Microsoft I might add).

I used the following method :

$web.RoleDefinitions.BreakInheritance($true,$false)

It turns out this does something that is impossible through the SharePoint interface – it not only breaks inheritance, and copies the Group assignments to the subsite, it also breaks inheritance of the Permission Levels (aka “permission sets”), and creates new permission sets tied to the sub-site with the same names as the parent. The tell-tale that this has happened is that checkboxes appear next to the permission set names when viewed from the sub-site (via “view site permissions”).

Why is this important? Because when the permission sets are copied, the configuration of the Limited Access User Permission Lock Down Mode feature is also copied – and then if it is enabled, or disabled at the site collection level (it’s a site collection feature, remember), it will not affect sub-sites with broken inheritance.

How can it be fixed ?

When you create a sub-site via Powershell, you need to use a slightly different method to break permissions inheritance :

$web.BreakRoleInheritance($true,$false)

This method copies the existing group assignments, but inherits the permission sets. It’s obviously the method used by the SharePoint interface, which exhibits the same behaviour.

If you have already created a number of sub-sites, they can be repaired by writing a PowerShell script to iterate through them, first reading the groups and roles assigned to them, then re-inheriting, and re-breaking permission inheritance correctly, before re-building the group and role assignments appropriately.

Posted by Jonathan Beckett in Notes, 0 comments

Provisioning Groups and Assigning Permissions within SharePoint Subsites with PowerShell

The following snippet shows how you might provision a new group within a subsite of SharePoint using PowerShell. Note that you not only need to create the group – you also need to associate it with the subsite, and assign permissions to the relationship between the group and the subsite. It’s not obvious at all.

# Connect to SharePoint Site
$web = get-spweb "https://server/sites/site_collection/subsite"

$group_name = "My Group"

# Remove group if it already exists
if ($web.SiteGroups[$group_name] -ne $null)
{
    $web.SiteGroups.Remove($group_name) > $null
    $web.Update() > $null
}

# Create the group
$web.SiteGroups.Add($group_name, $web.Site.Owner, $web.Site.Owner, $group_name) > $null
$web.Update() > $null

# Add Group to Associated Groups Collection
if ($web.AssociatedGroups[$group_name] -eq $null)
{
    $web.AssociatedGroups.Add($web.SiteGroups[$group_name])
    $web.Update()
}

# Assign Permissions to the Group
$group = $web.SiteGroups[$group_name]
$group_role_assignment = new-object Microsoft.SharePoint.SPRoleAssignment($group)
$full_control_role_definition = $web.RoleDefinitions["Full Control"]
$group_role_assignment.RoleDefinitionBindings.Add($full_control_role_definition) > $null
$web.RoleAssignments.Add($group_role_assignment) > $null
$web.Update()

# Release resources
$web.Close()
$web.Dispose()
Posted by Jonathan Beckett in Notes, 0 comments

Breaking Permissions Inheritance and Setting up new Permission Sets in SharePoint with PowerShell

The following snippet shows how you might create a new permission set in a subsite of SharePoint. One of the more common permission sets you might need in a production application is ‘restricted contribute’ – contribute without delete. This shows one method of doing that (there are many) – by duplicating the contribute permission set, minus the delete permission.

# Connect to SharePoint Site
$web = get-spweb "https://server/sites/site_collection/subsite"

# Break Inheritance for the subsite
$web.RoleDefinitions.BreakInheritance($false, $false) > $null
$web.Update() > $null

# Get the Contribute Definition
$contribute_role_definition = $web.RoleDefinitions["Contribute"]
$contribute_base_permissions = $contribute_role_definition.BasePermissions

# Delete the role definition if it exists
if ($web.RoleDefinitions["Restricted Contribute"]) {
    Write-Host " - Removing Existing Role Definition"
    $web.RoleDefinitions.Delete("Restricted Contribute")
    $web.Update()
}

# Create a new Role Definition, and copy the Base permissions minus Delete Items
$restricted_contribute_role_definition = New-Object Microsoft.SharePoint.SPRoleDefinition
$restricted_contribute_role_definition.BasePermissions = $contribute_base_permissions -bxor [Microsoft.SharePoint.SPBasePermissions]::DeleteListItems

# Set the name and description of the new role definition
$restricted_contribute_role_definition.Name = "Restricted Contribute"
$restricted_contribute_role_definition.Description = "Contribute without Delete Items"

# Apply the new role definition to the web
$web.RoleDefinitions.Add($restricted_contribute_role_definition);
$web.Update();

# Release Resources
$web.Close()
$web.Dispose()
Posted by Jonathan Beckett in Notes, 0 comments