Categories
Sitecore

Copy Permissions Using Sitecore PowerShell Extensions

In this module, we replicate permissions from one portion of the Sitecore tree to another. Additionally, these permissions can be applied to a different role. To provide contextual examples, we will be using a fictional company, Rhombic Networks.

TLDR: Copy Permissions.ps1 and the CopyPermissions-1.0.zip Sitecore package of this SPE module can be found on GitHub.

The Scenario

Rhombic Networks Medical Group owns multiple hospitals. Sitecore security is set up where each hospital has its own role to maintain permissions. In this scenario, the content manager wants to replicate the Sitecore General Hospital permissions onto the Akamai Urgent Care tree. The trees have a similar structure as do the rest of the medical locations.

Medical Location Tree

To accomplish this task, we will be using Sitecore PowerShell Extensions (SPE) and creating a module. The outcome will be a PowerShell script that can be executed from the ribbon in Sitecore.

The Modals

First, lets create some SPE modals to collect user input. We will modals for:

  • Where in the content tree to copy from
  • Where in the content tree to copy to
  • Which role to copy from
  • Which role to copy to
Copy From modal example

The modals have many configurable parameters. To select locations, we will use a droptree.

### Copy From Location Modal
$props = @{
    Parameters = @(
        @{Name="copyFromLocation"; Title="Location - Copy From"; Options=$options; Tooltip="Choose an item."; Editor = "droptree"}
    )
    Title = "Location - Copy From"
    Description = "Choose an item."
    Width = 500
    Height = 300
    ShowHints = $true
}
$cfl = Read-Variable @props
if($cfl -ne "ok") {
    break
}

Selecting a role is fairly similar except your Editor will be of type multiple user role.

While writing this, I selected the wrong paths many times, even with the descriptive modal text. So why not implement this simple confirmation modal?

## Confirm Inputs
$confirmText = "You are about to copy permissions from <b>" + $copyFromLocation.FullPath + "</b> and the <b>" + $copyRoleFrom + "</b> role to " 
$confirmText += "<b>" + $copyToLocation.FullPath + "</b> and the <b>" + $copyRoleTo + "</b> role"
$confirmText += ".  Do you want to continue?"
$confirm = Show-Confirm -Title $confirmText
if($confirm -eq "no") {
    break
}

With all of the modals, make sure to check the cancel action is handled, otherwise, the script will run regardless of pressing “Ok” or “Cancel.”

Get the Items

Getting all the items from the tree can be done in a couple of ways. One way is using a Get-Item and specifying a Query.

Get-Item -Path master:// -Query "/sitecore/content/home//*"

This works well, except it relies on Query.MaxItems and the default value in Sitecore 9.3 is 100. You can increase this in the config, but doing so can cause major performance issues. Instead, we should change this code to use Find-Item. Find-Item uses the index and is much more performant.

$criteria = @(
    @{Filter = "StartsWith"; Field = "_fullpath"; Value = $copyFromLocation.FullPath},
    @{Filter = "Equals"; Field = "_latestversion"; Value = "1"}
)
$props = @{
    Index = "sitecore_master_index"
    Criteria = $criteria
}
$allItemsFrom = Find-Item @props

Update Item Permissions

In a ForEach loop, we will be using Get-ItemAcl to retrieve the security access rules from the item. We will filter the results based on the user’s previous input.

$acls = Get-ItemAcl -Path $item.Path -Filter $copyRoleFrom[0] 

Looping through the ACLs, we can create a New-ItemAcl, mimicking the permissions on the users specified role. Then we can apply using Add-ItemAcl.

ForEach($acl in $acls) {
    $aclModified = New-ItemAcl -Identity  $copyRoleTo[0] `
              -AccessRight $acl."AccessRight" `
              -PropagationType $acl."PropagationType" `
              -SecurityPermission $acl."SecurityPermission"
    
    #Apply permissions to matching item
    Add-ItemAcl -AccessRules $aclModified -Path $toItem.FullPath
    }
    
    Get-Item -Path $toItem.FullPath | Add-ItemAcl -AccessRules $aclModified

The full script, Copy Permissions.ps1, is available on GitHub.

Add SPE Script to the Sitecore Ribbon

Some folks just keep a save of all their scripts directly in the library, but what if you want non-admins to access them? This is where you will likely want to create a module. Modules have multiple integration points where scripts can be executed within the Sitecore interface. For our module, we want users to interact with our script via the ribbon.

Create a Module

In the PowerShell ISE, click the New Module.

Select New Module

You will be presented with a list of integration point options. Name your module and choose Content Editor – Ribbon.

Navigate to your new module in /sitecore/system/Modules/PowerShell/Script Library/. Expanding the tree, you will notice all of the strips have been automatically created for you. These should mimic what you find in the core database under /sitecore/content/Applications/Content Editor/Ribbons/Strips.

While the mimicked strips are useful for quickly adding your script under another strip, they are unnecessary if you are not placing anything under them. I’ve removed all the strips and created my own.

Script Tree

This folder structure is created from the PowerShell Script Library template located in the insert options. The structure is important and is basically Ribbon Tab Name(Strip), Chunk Name, Button Name.

Notice I did change my icon on CopyPermissions as it will be shown as a large icon in the ribbon.

Configure the Permissions

We want all editors to be able to run this script. In the real world, we don’t, but for this example, we will. Select your script and click on Elevate Session so we can edit the item.

Elevate session warning on script item

Once you have elevated the session, you will now notice a show rule and an enable rule field. In most situations, it will make sense to limit this based on role, but I’m just going to make sure the user is authenticated.

Sync with Core Database

If you were expecting it to magically appear, remember, these ribbon representations need to be synced with the core database. This can be done in the PowerShell ISE, going to the Settings tab, and selecting Sync Library with Content Editor Ribbon.

Once the script has run, re-open your content editor. If it is not visible, make sure you have right-clicked in the dark grey tab area and enabled your strip.

You’re done! Now all authenticated users should be able to execute our script.

In case you missed it at the top, Copy Permissions.ps1 and the CopyPermissions-1.0.zip Sitecore package of this SPE module can be found on GitHub.

By Greg Coffman

Technical strategist, agile evangelist, and all-around web nerd. Formerly a Solution Architect at Sitecore. Thoughts and ideas are my own and do not represent my employer.