Public/User.ps1

function Invoke-CrmWhoAmI{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM( 
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn
    )
    
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    $request = New-Object Microsoft.Crm.Sdk.Messages.WhoAmIRequest
    
    try
    {
        $result = $conn.Execute($request)
    }
    catch
    {
        $_ | Format-List * -Force
        throw
    }    

    return $result
}

#Alias for Get-MyCrmUserId
New-Alias -Name Get-CrmCurrentUserId -Value Get-MyCrmUserId

#GetMyCrmUserId
function Get-MyCrmUserId{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM( 
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn
    )

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

    try
    {
        $result = Invoke-CrmWhoAmI -conn $conn

        return $result.UserId
    }
    catch
    {
        throw $_.Exception
    }    
}

#AssignEntityToUser
function Set-CrmRecordOwner{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [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)][alias("UserId")]
        [guid]$PrincipalId,
        [parameter(Mandatory=$false, Position=4)]
        [switch]$AssignToTeam
    )
    begin
    {
        $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    }     
    process
    {
        if($CrmRecord -ne $null)
        {
            $EntityLogicalName = $CrmRecord.logicalname
            $Id = $CrmRecord.($EntityLogicalName + "id")
        }
        try
        {            
            # As CrmClientService does not have method to assign to team, use Organization Request
            if($AssignToTeam){
                write-verbose "Assigning record with Id: $Id to Team with Id: $PrincipalId"
                
                $req = New-Object Microsoft.Crm.Sdk.Messages.AssignRequest
                $req.target = New-CrmEntityReference -EntityLogicalName $EntityLogicalName -Id $Id
                $req.Assignee = New-CrmEntityReference -EntityLogicalName "team" -Id $PrincipalId
                $result = [Microsoft.Crm.Sdk.Messages.AssignResponse]$conn.Execute($req)
                # If no result returend, then it had an issue.
                if($result -eq $null)
                {
                    $result = $false
                }
            }
            else{
                $req = New-Object Microsoft.Crm.Sdk.Messages.AssignRequest
                $req.Target = New-Object Microsoft.Xrm.Sdk.EntityReference($EntityLogicalName, $Id)
                $req.Assignee = New-Object Microsoft.Xrm.Sdk.EntityReference("systemuser", $PrincipalId)
                $result = [Microsoft.Crm.Sdk.Messages.AssignResponse]$conn.Execute($req)
            }            
            if(!$result)
            {
                throw
            }

            write-verbose "Completed..."
        }
        catch
        {
            throw
        }
    }
}

function Get-CrmUserMailbox{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$UserId
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    
    $fetch = @"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
    <entity name="mailbox">
    <all-attributes />
    <filter type="and">
      <condition attribute="regardingobjectid" operator="eq" value="{$UserId}" />
    </filter>
  </entity>
</fetch>
"@


    $record = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch).CrmRecords
    switch ($record.count)
    {
        {$_ -eq 0} {Throw "The user $UserId has no mailbox."}
        {$_ -ge 2} {
                        foreach( $id in $record.mailboxid)
                        {
                            if(!$idString)
                            {
                                [string]$idString = $id
                            }
                            else
                            {
                                [string]$idString = "$idString,$id"
                            }
                        }
                        Throw "The user $UserId has more than one mailbox: $idString"
                    }
        Default {
                    return $record}
    }
    
}

function Get-CrmUserPrivileges{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$UserId
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    
    # Get User Rolls including Team
    $roles = Get-CrmUserSecurityRoles -conn $conn -UserId $UserId -IncludeTeamRoles
    # Get User name
    $user = Get-CrmRecord -conn $conn -EntityLogicalName systemuser -Id $UserId -Fields fullname
    # Get all privilege records for PrivilegeName
    $privilegeRecords = (Get-CrmRecords -conn $conn -EntityLogicalName privilege -Fields name,privilegeid -WarningAction SilentlyContinue).CrmRecords
    # Create hash for performance reason
    $privileges = @{}
    $privilegeRecords | % {$privileges[$_.privilegeid] = $_.name} 

    # Create Result as hash for performance reason
    $results = @{}
    
    $isUserRoleInitialized = $false
    foreach($role in $roles | sort TeamName)
    {
        # Get all privileges for the role
        $request = New-Object Microsoft.Crm.Sdk.Messages.RetrieveRolePrivilegesRoleRequest
        
        try
        {
            $request.RoleId = $role.RoleId
            $rolePrivileges = ($conn.Execute($request)).RolePrivileges            
        }
        catch
        {
            throw $_.Exception
        }        
        
        foreach($rolePrivilege in $rolePrivileges)
        {
            # Create origin as "RoleName:Depth" format
            $origin = $role.RoleName + ":" + $rolePrivilege.Depth
            
            # If the role is assigned to a team, then add them separately.
            # For roles assign to the user, then accumulate them.
            if($isUserRoleInitialized -and $results.Contains($rolePrivilege.PrivilegeId))
            {
                $existingObj = $results[$rolePrivilege.PrivilegeId]
                                
                # Overwrite Depth only if it has higher privilege
                if([Microsoft.Crm.Sdk.Messages.PrivilegeDepth]::($rolePrivilege.Depth) -gt [Microsoft.Crm.Sdk.Messages.PrivilegeDepth]::($existingObj.Depth))
                {
                    $existingObj.Depth = $rolePrivilege.Depth
                }

                $existingObj.Origin += "," + $origin
            }
            else
            {       
                # Create new result object
                $psobj = New-Object -TypeName System.Management.Automation.PSObject
                if($role.TeamName -eq $null)
                {
                    $principalType = "User"
                    $principalName = $user.fullname
                    $key = $rolePrivilege.PrivilegeId
                }
                else
                {
                    $principalType = "Team"
                    $principalName = $role.TeamName
                    $key = $rolePrivilege.PrivilegeId.Guid + $origin
                }
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "Depth" -Value $rolePrivilege.Depth
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "PrivilegeId" -Value $rolePrivilege.PrivilegeId
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "PrivilegeName" -Value $privileges[($rolePrivilege.PrivilegeId)]
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "Origin" -Value $origin
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "PrincipalType" -Value $principalType
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "PrincipalName" -Value $principalName
                Add-Member -InputObject $psobj -MemberType NoteProperty -Name "BusinessUnitName" -Value $role.BusinessUnitName
                $results[$key] = $psobj
            }
        }

        if($role.TeamName -eq $null) {$isUserRoleInitialized = $true} 
    }
    
    return $results.Values | sort principalName, PrivilegeName
}

function Get-CrmUserSecurityRoles{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$UserId,
        [parameter(Mandatory=$false)]
        [switch]$IncludeTeamRoles
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    
    $roles = New-Object System.Collections.Generic.List[PSObject]
    
    if($IncludeTeamRoles)
    {
        $fetch = @"
        <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" no-lock="true">
          <entity name="role">
            <attribute name="name"/>
            <attribute name="roleid" />
            <link-entity name="teamroles" from="roleid" to="roleid" visible="false" intersect="true">
              <link-entity name="team" from="teamid" to="teamid" alias="team">
              <attribute name="name"/>
              <attribute name="businessunitid"/>
                <link-entity name="teammembership" from="teamid" to="teamid" visible="false" intersect="true">
                  <link-entity name="systemuser" from="systemuserid" to="systemuserid" alias="af">
                    <filter type="and">
                      <condition attribute="systemuserid" operator="eq" value="{0}" />
                    </filter>
                  </link-entity>
                </link-entity>
              </link-entity>
            </link-entity>
          </entity>
        </fetch>
"@
 -F $UserId
        
        (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch).CrmRecords | `
        select @{name="RoleId";expression={$_.roleid}}, @{name="RoleName";expression={$_.name}}, `
        @{name="TeamName";expression={$_.'team.name'}}, @{name="BusinessUnitName";expression={($_.'team.businessunitid').Name}} | `
        % {$roles.Add($_)}    
    }

    $fetch = @"
    <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" no-lock="true">
      <entity name="role">
        <attribute name="name" />
        <attribute name="roleid" />
        <order attribute="name" descending="false" />
        <link-entity name="systemuserroles" from="roleid" to="roleid" visible="false" intersect="true">
          <link-entity name="systemuser" from="systemuserid" to="systemuserid" alias="user">
          <attribute name="businessunitid"/>
            <filter type="and">
              <condition attribute="systemuserid" operator="eq" value="{0}" />
            </filter>
          </link-entity>
        </link-entity>
      </entity>
    </fetch>
"@
 -F $UserId
    
    (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch).CrmRecords | `
    select @{name="RoleId";expression={$_.roleid}}, @{name="RoleName";expression={$_.name}}, `
    @{name="BusinessUnitName";expression={($_.'user.businessunitid').Name}}  | % { $roles.Add($_) }
    
    return $roles
}

function Get-CrmUserSettings{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$UserId,
        [parameter(Mandatory=$true, Position=2)]
        [string[]]$Fields
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
  
    return Get-CrmRecord -conn $conn -EntityLogicalName usersettings -Id $UserId -Fields $Fields
}

function Set-CrmUserMailbox {
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml
    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [string]$UserId,
        [parameter(Mandatory=$false)]
        [string]$EmailAddress,
        [parameter(Mandatory=$false, ParameterSetName="Custom")]        
        [guid]$EmailServerProfile,
        [parameter(Mandatory=$false, ParameterSetName="Custom")]
        [int]$IncomingEmailDeliveryMethod,
        [parameter(Mandatory=$false, ParameterSetName="Custom")]
        [int]$OutgoingEmailDeliveryMethod,
        [parameter(Mandatory=$false, ParameterSetName="Custom")]
        [int]$ACTDeliveryMethod,
        [parameter(Mandatory=$false, ParameterSetName="Default")]
        [switch]$ApplyDefaultEmailSettings,
        [parameter(Mandatory=$false, ParameterSetName="Status")]
        [string]$StateCode,
        [parameter(Mandatory=$false, ParameterSetName="Status")]
        [string]$StatusCode,
        [parameter(Mandatory=$false, ParameterSetName="Status")]
        [switch]$ScheduleTest,
        [parameter(Mandatory=$false, ParameterSetName="Status")]
        [switch]$MarkedAsPrimaryForExchangeSync,
        [parameter(Mandatory=$false, ParameterSetName="Status")]
        [switch]$ApproveEmail
    )
    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))

    $fetch = @"
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
  <entity name="mailbox">
    <attribute name="mailboxid" />
    <filter type="and">
      <condition attribute="regardingobjectid" operator="eq" value="{$UserId}" />
    </filter>
  </entity>
</fetch>
"@


    $Id = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch).CrmRecords[0].MailboxId

    $updateFields = @{}
    if($ApplyDefaultEmailSettings)
    {
        $fetch = @"
        <fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" no-lock="true">
            <entity name="organization">
                <attribute name="defaultemailserverprofileid" />
                <attribute name="defaultemailsettings" />
            </entity>
        </fetch>
"@

        $record = (Get-CrmRecordsByFetch -conn $conn -Fetch $fetch).CrmRecords[0]
        $updateFields.Add("emailserverprofile", $record.defaultemailserverprofileid_Property.Value)
        $xml = [xml]$record.defaultemailsettings
        $updateFields.Add("incomingemaildeliverymethod", (New-CrmOptionSetValue $xml.ChildNodes.IncomingEmailDeliveryMethod))
        $updateFields.Add("outgoingemaildeliverymethod", (New-CrmOptionSetValue $xml.ChildNodes.OutgoingEmailDeliveryMethod))
        $updateFields.Add("actdeliverymethod", (New-CrmOptionSetValue $xml.ChildNodes.ACTDeliveryMethod))
    }
    if($ScheduleTest)
    {
        $updateFields.Add("testemailconfigurationscheduled", $true)
    }
    if($MarkedAsPrimaryForExchangeSync)
    {
        $updateFields.Add("orgmarkedasprimaryforexchangesync", $true)
    }
    if($ApproveEmail)
    {
        Approve-CrmEmailAddress -conn $conn -UserId $UserId
    }
    foreach($parameter in $MyInvocation.BoundParameters.GetEnumerator())
    {   
        if($parameter.Key -in ("EmailServerProfile"))
        {
            $updateFields.Add($parameter.Key.ToLower(), (New-CrmEntityReference emailserverprofile $parameter.Value))
        }
        elseif($parameter.Key -in ("IncomingEmailDeliveryMethod","OutgoingEmailDeliveryMethod","ACTDeliveryMethod"))
        {
            $updateFields.Add($parameter.Key.ToLower(), (New-CrmOptionSetValue $parameter.Value))
        }
        elseif($parameter.Key -in ("StateCode","StatusCode"))
        {
            Set-CrmRecordState -conn $conn -EntityLogicalName mailbox -Id $Id -StateCode $StateCode -StatusCode $StatusCode
        }
        elseif($parameter.Key -in ("EmailAddress"))
        {
            $updateFields.Add($parameter.Key.ToLower(), $parameter.Value)
        }
    }

    Set-CrmRecord -conn $conn -EntityLogicalName mailbox -Id $Id -Fields $updateFields
}

function Set-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,
        [parameter(Mandatory=$true, Position=2)]
        [guid]$ManagerId,
        [parameter(Mandatory=$true, Position=3)]
        [bool]$KeepChildUsers
    )

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

    $request = New-Object 'Microsoft.Crm.Sdk.Messages.SetParentSystemUserRequest'
    $request.ParentId = $ManagerId
    $request.UserId = $UserId
    $request.KeepChildUsers = $KeepChildUsers

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

function Set-CrmUserSettings{
# .ExternalHelp Campgemini.Xrm.Data.PowerShell.Help.xml

    [CmdletBinding()]
    PARAM(
        [parameter(Mandatory=$false)]
        [Microsoft.Xrm.Sdk.IOrganizationService]$conn,
        [parameter(Mandatory=$true, Position=1)]
        [Alias("UserSettingsRecord")]
        [PSObject]$CrmRecord
    )

    $conn = VerifyCrmConnectionParam -conn $conn -pipelineValue ($PSBoundParameters.ContainsKey('conn'))
    
    try
    {
        $result = Set-CrmRecord -conn $conn -CrmRecord $CrmRecord
    }
    catch
    {
        throw
    }    
}