Public/Security.ps1


function Grant-CrmRecordAccess {
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [OutputType([void])]
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false, Position=0)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord", ValueFromPipeline=$true)]
        [PSObject[]]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="NameWithId")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="NameWithId")]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3)]
        [Campgemini.Xrm.Sdk.EntityReference]$Principal,
        [parameter(Mandatory=$true, Position=4)]
        [Microsoft.Crm.Sdk.Messages.AccessRights]$AccessMask
    )
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

        if ($EntityLogicalName) {
            $CrmRecord += [PSCustomObject] @{
                logicalname = $EntityLogicalName
                "$($EntityLogicalName)id" = $Id
            }
        }
    }
    process
    {
        foreach ($record in $CrmRecord) {
            try {
                $request = [Microsoft.Crm.Sdk.Messages.GrantAccessRequest]::new()
                $request.Target = New-CrmEntityReference -EntityLogicalName $record.logicalname -Id $record.($record.logicalname + "id")
                $principalAccess = [Microsoft.Crm.Sdk.Messages.PrincipalAccess]::new()
                $principalAccess.Principal = $Principal
                $principalAccess.AccessMask = $AccessMask
                $request.PrincipalAccess = $principalAccess
                
                [Microsoft.Crm.Sdk.Messages.GrantAccessResponse]$conn.Execute($request) | Out-Null
            }
            catch {
                Write-Error $_
            }   
        }
    }
}

function Add-CrmSecurityRoleToTeam{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [PSObject]$TeamRecord,
        [parameter(Mandatory=$false, Position=2, ParameterSetName="CrmRecord")]
        [PSObject]$SecurityRoleRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Id")]
        [string]$TeamId,
        [parameter(Mandatory=$false, Position=2, ParameterSetName="Id")]
        [string]$SecurityRoleId,
        [parameter(Mandatory=$false, Position=2)]
        [string]$SecurityRoleName
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    if($SecurityRoleRecord -eq $null -and $SecurityRoleId -eq "" -and $SecurityRoleName -eq "")
    {
        Write-Warning "You need to specify Security Role information"
        return
    }
    
    if($SecurityRoleName -ne "")
    {
        if($TeamRecord -eq $null -or $TeamRecord.businessunitid -eq $null)
        {
            $TeamRecord = Get-CrmRecord -conn $conn -EntityLogicalName team -Id $TeamId -Fields businessunitid
        }

        $fetch = @"
        <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
          <entity name="role">
            <attribute name="businessunitid" />
            <attribute name="roleid" />
            <filter type="and">
              <condition attribute="name" operator="eq" value="{0}" />
              <condition attribute="businessunitid" operator="eq" value="{1}" />
            </filter>
          </entity>
        </fetch>
"@
 -F $SecurityRoleName, $TeamRecord.businessunitid_Property.Value.Id
        
        $roles = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch)
        if($roles.CrmRecords.Count -eq 0)
        {
            Write-Warning "Not Security Role found"
            return
        }
        else
        {
            $role = $roles.CrmRecords[0]
        }
    }

    if($SecurityRoleName -ne "")
    {
        Add-CrmRecordAssociation -conn $conn -CrmRecord1 $TeamRecord -CrmRecord2 $role -RelationshipName teamroles_association
    }
    elseif($TeamRecord -ne $null)
    {
        Add-CrmRecordAssociation -conn $conn -CrmRecord1 $TeamRecord -CrmRecord2 $SecurityRoleRecord -RelationshipName teamroles_association
    }
    else
    {
        Add-CrmRecordAssociation -conn $conn -EntityLogicalName1 team -Id1 $TeamId -EntityLogicalName2 role -Id2 $SecurityRoleId -RelationshipName teamroles_association
    }
}

function Add-CrmSecurityRoleToUser{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [PSObject]$UserRecord,
        [parameter(Mandatory=$false, Position=2, ParameterSetName="CrmRecord")]
        [PSObject]$SecurityRoleRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Id")]
        [string]$UserId,
        [parameter(Mandatory=$false, Position=2, ParameterSetName="Id")]
        [string]$SecurityRoleId,
        [parameter(Mandatory=$false, Position=3, ParameterSetName="Id")]
        [parameter(Mandatory=$false, Position=3, ParameterSetName="CrmRecord")]
        [string]$SecurityRoleName
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    if(!$SecurityRoleRecord -and !$SecurityRoleId -and !$SecurityRoleName)
    {
        Write-Error "You need to provide a SecurityRole"
        return
    }
    
    if($SecurityRoleName)
    {
        if($UserRecord -eq $null -or $UserRecord.businessunitid -eq $null)
        {
            $UserRecord = Get-CrmRecord -conn $conn -EntityLogicalName systemuser -Id $UserId -Fields businessunitid
        }

        $fetch = @"
        <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
          <entity name="role">
            <attribute name="businessunitid" />
            <attribute name="roleid" />
            <filter type="and">
              <condition attribute="name" operator="eq" value="{0}" />
              <condition attribute="businessunitid" operator="eq" value="{1}" />
            </filter>
          </entity>
        </fetch>
"@
 -F $SecurityRoleName, $UserRecord.businessunitid_Property.Value.Id
        
        $roles = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch)
        if($roles.CrmRecords.Count -eq 0)
        {
            Write-Error "No Security Role found"
            return
        }
        else
        {
            $role = $roles.CrmRecords[0]
        }
    }

    if($SecurityRoleName)
    {
        Add-CrmRecordAssociation -conn $conn -CrmRecord1 $UserRecord -CrmRecord2 $role -RelationshipName systemuserroles_association
    }
    elseif($UserRecord -ne $null)
    {
        Add-CrmRecordAssociation -conn $conn -CrmRecord1 $UserRecord -CrmRecord2 $SecurityRoleRecord -RelationshipName systemuserroles_association
    }
    else
    {
        Add-CrmRecordAssociation -conn $conn -EntityLogicalName1 systemuser -Id1 $UserId -EntityLogicalName2 role -Id2 $SecurityRoleId -RelationshipName systemuserroles_association
    }
}

function Remove-CrmSecurityRoleFromTeam{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [PSObject]$TeamRecord,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="CrmRecord")]
        [PSObject]$SecurityRoleRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Id")]
        [string]$TeamId,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="Id")]
        [string]$SecurityRoleId
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    if($TeamRecord -and $SecurityRoleRecord)
    {
        Remove-CrmRecordAssociation -conn $conn -CrmRecord1 $TeamRecord -CrmRecord2 $SecurityRoleRecord -RelationshipName teamroles_association
    }
    elseif($TeamId -and $SecurityRoleId)
    {
        Remove-CrmRecordAssociation -conn $conn -EntityLogicalName1 team -Id1 $TeamId -EntityLogicalName2 role -Id2 $SecurityRoleId -RelationshipName teamroles_association
    }
    else{
        throw "Parameters not valid, no operations were performed"
    }
}

function Remove-CrmSecurityRoleFromUser{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord")]
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecordRoleName")]
        [PSObject]$UserRecord,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="CrmRecord")]
        [PSObject]$SecurityRoleRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="Id")]
        [parameter(Mandatory=$true, Position=1, ParameterSetName="IdRoleName")]
        [string]$UserId,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="Id")]
        [string]$SecurityRoleId,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="CrmRecordRoleName")]
        [parameter(Mandatory=$true, Position=2, ParameterSetName="IdRoleName")]
        [string]$SecurityRoleName
    )
    
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    #ensure the businessunitid is available for the user
    if(-not $UserRecord -and $UserId -ne $null)
    {
        Write-Verbose "Getting UserRecord for businessunitid with UserId provided: $UserId"
        $UserRecord = Get-CrmRecord -conn $conn -EntityLogicalName systemuser -Id $UserId -Fields businessunitid
    }
    elseif($UserRecord -ne $null -and -not $UserRecord.businessunitid)
    {
        Write-Verbose "Getting businessunitid for UserRecord"
        $UserRecord = Get-CrmRecord -conn $conn -EntityLogicalName systemuser -Id $UserRecord.ReturnProperty_Id -Fields businessunitid
    }
    else{
        throw "The UserId cannot be determined."
    }
    
    #if we have a name but no ID then we must get the roleid
    if(-not $SecurityRoleId -and $SecurityRoleName -ne $null)
    {
        $fetch=@"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
        <entity name="role">
        <attribute name="businessunitid" />
        <attribute name="roleid" />
        <attribute name="name" />
        <filter type="and">
            <condition attribute="name" operator="eq" value="{0}" />
            <condition attribute="businessunitid" operator="eq" value="{1}" />
        </filter>
        </entity>
    </fetch>
"@
 -F $SecurityRoleName, $UserRecord.businessunitid_Property.Value.Id
    
        $roles = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch)
        if($roles.CrmRecords.Count -eq 0)
        {
            throw "No Security Role found for rolename $SecurityRoleName"
        }
        else
        {
            $SecurityRoleRecord = $roles.CrmRecords[0]
            Write-Verbose "Found Role with ID: $($role.ReturnProperty_Id) and name: $($SecurityRoleRecord.name)"
        }
    }

    if($UserRecord -and $SecurityRoleRecord)
    {
        Write-Verbose ("Removing role from user")
        Remove-CrmRecordAssociation -conn $conn -CrmRecord1 $UserRecord -CrmRecord2 $SecurityRoleRecord -RelationshipName systemuserroles_association
    }
    elseif($UserId -and $SecurityRoleId)
    {
        Write-Verbose ("Removing role from user")
        Remove-CrmRecordAssociation -conn $conn -EntityLogicalName1 systemuser -Id1 $UserId -EntityLogicalName2 role -Id2 $SecurityRoleId -RelationshipName systemuserroles_association
    }
    else{
        throw "Role removal could not be completed with the provided inputs"
    }
}

function Remove-CrmUserManager{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 [CmdletBinding()]
    PARAM( 
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [guid]$UserId
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    $request = New-Object 'Microsoft.Crm.Sdk.Messages.RemoveParentRequest'
    $target = New-CrmEntityReference systemuser $UserId
    $request.Target = $target
    
    try
    {
        $result = $conn.Execute($request)
        if($result -eq $null)
        {
            throw "Could not remore user manager"
        }
    }
    catch
    {
        throw $_.Exception
    } 
}

function Revoke-CrmRecordAccess {
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [OutputType([void])]
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false, Position=0)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord", ValueFromPipeline=$true)]
        [PSObject[]]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="NameWithId")]
        [string]$EntityLogicalName,        
        [parameter(Mandatory=$true, Position=2, ParameterSetName="NameWithId")]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3)]
        [Campgemini.Xrm.Sdk.EntityReference]$Revokee
    )
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

        if ($EntityLogicalName) {
            $CrmRecord += [PSCustomObject] @{
                logicalname = $EntityLogicalName
                "$($EntityLogicalName)id" = $Id
            }
        }
    }
    process
    {
        foreach ($record in $CrmRecord) {
            try {
                $request = [Microsoft.Crm.Sdk.Messages.RevokeAccessRequest]::new()
                $request.Target = New-CrmEntityReference -EntityLogicalName $record.logicalname -Id $record.($record.logicalname + "id")
                $request.Revokee = $Revokee
                
                [Microsoft.Crm.Sdk.Messages.RevokeAccessResponse]$conn.Execute($request) | Out-Null
            }
            catch {
                Write-Error $_
            }   
        }
    }
}

function Set-CrmUserBusinessUnit{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
 [CmdletBinding()]
    PARAM( 
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [guid]$UserId,
        [parameter(Mandatory=$true, Position=2)]
        [guid]$BusinessUnitId,
        [parameter(Mandatory=$false, Position=3)]
        [guid]$ReassignUserId
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    # If ReassignUserId is not passed, then assign them to myself
    if($ReassignUserId -eq $null)  
    {  
        $ReassignUserId = $UserId  
    }  

    $ReassignPrincipal = New-CrmEntityReference -EntityLogicalName systemuser -Id $ReassignUserId

    $request = New-Object 'Microsoft.Crm.Sdk.Messages.SetBusinessSystemUserRequest'
    $request.BusinessId = $BusinessUnitId
    $request.UserId = $UserId
    $request.ReassignPrincipal = $ReassignPrincipal

    try
    {
        $result = $conn.Execute($request)
        if($result -eq $null)
        {
            throw "Could not set business unit"
        }
    }
    catch
    {
        throw 
    }
}

function Set-CrmRecordAccess {
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [OutputType([void])]
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false, Position=0)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="CrmRecord", ValueFromPipeline=$true)]
        [PSObject[]]$CrmRecord,
        [parameter(Mandatory=$true, Position=1, ParameterSetName="NameWithId")]
        [string]$EntityLogicalName,
        [parameter(Mandatory=$true, Position=2, ParameterSetName="NameWithId")]
        [guid]$Id,
        [parameter(Mandatory=$true, Position=3)]
        [Campgemini.Xrm.Sdk.EntityReference]$Principal,
        [parameter(Mandatory=$true, Position=4)]
        [Microsoft.Crm.Sdk.Messages.AccessRights]$AccessMask
    )
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

        if ($EntityLogicalName) {
            $CrmRecord += [PSCustomObject] @{
                logicalname = $EntityLogicalName
                "$($EntityLogicalName)id" = $Id
            }
        }
    }
    process
    {
        foreach ($record in $CrmRecord) {
            try {
                $request = [Microsoft.Crm.Sdk.Messages.ModifyAccessRequest]::new()
                $request.Target = New-CrmEntityReference -EntityLogicalName $record.logicalname -Id $record.($record.logicalname + "id")
                $principalAccess = [Microsoft.Crm.Sdk.Messages.PrincipalAccess]::new()
                $principalAccess.Principal = $Principal
                $principalAccess.AccessMask = $AccessMask
                $request.PrincipalAccess = $principalAccess
                
                [Microsoft.Crm.Sdk.Messages.ModifyAccessResponse]$conn.Execute($request) | Out-Null
            }
            catch {
                Write-Error $_
            }   
        }
    }
}