Public/Export-Role.ps1

function Export-Role {
    <#
    .SYNOPSIS
        Exports one or more roles to a JSON file with many additional properties not directly attached to object received from Get-Role
    .DESCRIPTION
        Get-Role returns Role objects, but these objects do not have many additional properties attached to them. For example, the
        Smart Client Profile, Management Client Profile, Client Login Time Profile, and Overall Security are not available either
        directly, or through nested child properties of the Role object.
 
        This function enables you to backup roles for the purpose of recreating them later or creating identical roles on separate
        Management Servers.
 
        Some properties can add up to a few hunded milliseconds per role so some properties are optional such as Overall Security, and
        Client Time Profiles and View Group security. If you want to include all available options, ensure you add all the -Include* switches.
    .EXAMPLE
        PS C:\> Export-Role -Role (Get-Role) -OutFile .\roles.json -IncludeOverallSecurity -IncludeClientTimeProfile
        Export all roles to a roles.json file in the current working directory. The Overall Security and Smart Client and Management Client
        time profile names will be included in the output, but view group security will not be included.
    .EXAMPLE
        PS C:\> $roles = Export-Role -Role (Get-Role) -IncludeOverallSecurity -IncludeClientTimeProfile -IncludeViewGroupSecurity
        Export all roles to a variable and include all optional properties. Afterward you might modify one or more roles in the array
        and pass them into Import-Role as the InputObject property where whatever changes you have made will be imported.
    .NOTES
        Overall Security properties are included in the export, however individual device permissions are not. You must collect
        device-level permissions yourself using, for example, Get-Camera -Id $cameraId | Get-DeviceAcl -RoleId $roleId. The ACL
        objects could be gathered into a collection under each role name or ID for example.
    #>

    [CmdletBinding()]
    param (
        # Specifies one or more Role objects to be exported
        [Parameter(Mandatory, ValueFromPipeline)]
        [VideoOS.Platform.ConfigurationItems.Role[]]
        $Role,

        # Specifies the path of the destination json file
        [Parameter()]
        [string]
        $OutFile,

        # Specifies that the overall security information should be gathered. When omitted, the default value is null.
        [Parameter()]
        [switch]
        $IncludeOverallSecurity,

        # Specifies that the client time profile information should be gathered. When omitted, the default value is null.
        [Parameter()]
        [switch]
        $IncludeClientTimeProfile,

        # Specifies that the client time profile information should be gathered. When omitted, the default value is null.
        [Parameter()]
        [switch]
        $IncludeViewGroupSecurity,

        # Specifies that the resulting json file should be compressed by omitting all unnecessary white space. Equivalent to ConvertTo-Json -Compress
        [Parameter()]
        [switch]
        $Compress,

        # Specifies that the array of role properties should be passed through to the pipeline
        [Parameter()]
        [switch]
        $PassThru
    )

    begin {
        $config = BuildConfigMemoryMap
    }

    process {
        $total = $Role.Count
        $i = 0
        $progressParams = @{
            Activity = "Exporting Roles"
            Status = "Working"
            CurrentOperation = "Waiting"
            PercentComplete = $i / $total * 100
        }
        $result = New-Object System.Collections.Generic.List[pscustomobject]
        $sw = [Diagnostics.StopWatch]::StartNew()
        foreach ($r in $Role) {
            $sw.Restart()
            $progressParams.PercentComplete = $i / $total * 100
            $progressParams.Status = "Retrieved $i of $total roles"
            $progressParams.CurrentOperation = "Retrieving properties for $($r.Name)"
            Write-Progress @progressParams
            $i += 1

            $clientTimeProfile = $null
            if ($IncludeClientTimeProfile -and $config.VmoClient.ManagementServer.IsFeatureLicensed('TimeControlledAccessRights')) {
                try {
                    $clientTimeProfile = $r.GetClientTimeProfile().GetProperty('ItemSelection')
                }
                catch {
                    $clientTimeProfile = $null
                }
            }

            $viewGroupPermissions = $null
            if ($IncludeViewGroupSecurity) {
                if ($config.ViewGroups.ContainsKey($r.Name)) {
                    $viewGroupPermissions = $config.ViewGroups.$($r.Name).EffectivePermissions("[VideoOS]\$($r.Name)")
                }
            }

            $overallSecurity = $null
            if ($IncludeOverallSecurity -and $r.RoleType -ne 'Adminstrative') {
                $overallSecurity = @{}
                $namespaces = Get-OverallSecurity -Role $r
                foreach ($key in $namespaces.Keys) {
                    $overallSecurity.$key = Get-OverallSecurity -Role $r -SecurityNamespaceId $namespaces.$key
                }
            }

            $obj = [ordered]@{
                Name = $r.Name
                Description = $r.Description
                DualAuthorizationRequired = $r.DualAuthorizationRequired
                MakeUsersAnonymousDuringPTZSession = $r.MakeUsersAnonymousDuringPTZSession
                AllowMobileClientLogOn = $r.AllowMobileClientLogOn
                AllowSmartClientLogOn = $r.AllowSmartClientLogOn
                AllowWebClientLogOn = $r.AllowWebClientLogOn
                SmartClientProfile = $config.RoleToSmartClientProfile.$($r.Name)
                ManagementClientProfile = $config.RoleToMgmtClientProfile.$($r.Name)
                ClientTimeProfile = $clientTimeProfile
                HasMatchingViewGroup = $config.ViewGroups.ContainsKey($r.Name)
                ViewGroupPermissions = $viewGroupPermissions
                Members = $r.UserFolder.Users.Sid
                OverallSecurity = $overallSecurity
            }
            $result.Add($obj)
        }

        $json = $result | ConvertTo-Json -Depth 100 -Compress:$Compress
        if (![string]::IsNullOrWhiteSpace($OutFile)) {
            $json | Set-Content -Path $OutFile -Encoding UTF8
        }
        $progressParams.Completed = $true
        Write-Progress @progressParams

        if ($PassThru -or [string]::IsNullOrWhiteSpace($OutFile)) {
            Write-Output ( $json | ConvertFrom-Json )
        }
    }

    end {
        if ($null -ne $config.VmoClient) {
            $config.VmoClient.Dispose()
        }
    }
}