Users.psm1

<#
.SYNOPSIS
    This function returns a list of the properties present in an MSPComplete User object.
#>

function Get-MSPCompleteUserPropertyList {
    # Return the list of properties
    return @(
        "FirstName",
        "LastName",
        "DisplayName",
        "FullName",
        "PrimaryEmailAddress",
        "UserPrincipalName"
    )
}

<#
.SYNOPSIS
    This function returns a hash table that maps MSPComplete user properties to
    Exchange Online user properties
#>

function Get-MSPCompleteUserToExchangeOnlineUserPropertyMap {
    # Return the map of properties
    return @{
        FirstName           = "FirstName"
        LastName            = "LastName"
        DisplayName         = "DisplayName"
        FullName            = "Name"
        PrimaryEmailAddress = "UserPrincipalName"
        UserPrincipalName   = "UserPrincipalName"
    }
}

<#
.SYNOPSIS
    This function returns a list of the extended properties present in an MSPComplete User object.
#>

function Get-MSPCompleteUserExtendedPropertyList {
    # Return the list of properties
    return @(
        "AddressLine1",
        "AddressLine2",
        "City",
        "StateOrProvince",
        "PostalOrZipCode",
        "CountryOrRegion",
        "MobilePhoneNumber",
        "LandLinePhoneNumber",
        "CompanyName",
        "Department",
        "JobTitle",
        "Salutation",
        "ManagerEmailAddress"
    )
}

<#
.SYNOPSIS
    This function returns a hash table that maps MSPComplete user extended properties to
    Exchange Online user properties
#>

function Get-MSPCompleteUserToExchangeOnlineUserExtendedPropertyMap {
    # Return the map of properties
    return @{
        AddressLine1        = "StreetAddress"
        City                = "City"
        StateOrProvince     = "StateOrProvince"
        PostalOrZipCode     = "PostalCode"
        CountryOrRegion     = "CountryOrRegion"
        MobilePhoneNumber   = "MobilePhone"
        LandLinePhoneNumber = "HomePhone"
        CompanyName         = "Company"
        Department          = "Department"
        JobTitle            = "Title"
        ManagerEmailAddress = "ManagerEmailAddress"
    }
}

<#
.SYNOPSIS
    This function performs a comparison between a reference user object and a comparison user object.
.DESCRIPTION
    This function performs a comparison between a reference user object and a comparison user object.
    It returns true if the objects match in both property values and extended property values,
    and false otherwise.
.PARAMETER referenceUser
    The user used as the reference object.
.PARAMETER comparisonUser
    The user used as the comparison object.
#>

function Compare-MSPCompleteUser {
    param (
        # The user used as the reference object.
        [Parameter(Mandatory=$true)]
        $referenceUser,

        # The user used as the comparison object.
        [Parameter(Mandatory=$true)]
        $comparisonUser
    )

    try {
        # Get list of properties to compare
        $propertiesToCompare = Get-MSPCompleteUserPropertyList

        # Keep track of comparison result
        $result = $true

        # Compare properties
        foreach ($property in $propertiesToCompare) {
            if ($referenceUser.$property -ne $comparisonUser.$property) {
                Write-Error "Property '$($property)' does not match for user '$($referenceUser.DisplayName)' - Reference: '$($referenceUser.$property)' Comparison: '$($comparisonUser.$property)'"
                return $false
            }
        }

        # Get list of extended properties to compare
        $extendedPropertiesToCompare = Get-MSPCompleteUserExtendedPropertyList

        # Compare extended properties
        foreach ($property in $extendedPropertiesToCompare) {
            if ($referenceUser.ExtendedProperties.$property -ne $comparisonUser.ExtendedProperties.$property) {
                Write-Error "Extended property '$($property)' does not match for user '$($referenceUser.DisplayName)' - Reference: '$($referenceUser.ExtendedProperties.$property)' Comparison: '$($comparisonUser.ExtendedProperties.$property)'"
                return $false
            }
        }
    }
    catch {
        # Any exception means that comparison failed
        $result = $false
    }

    # Return the result of the comparison
    return $result
}

<#
.SYNOPSIS
    This function performs a comparison between two lists of MSPComplete users
.DESCRIPTION
    This function performs a comparison between two lists of MSPComplete users.
    It returns true if both lists contain the same set of users with matching property
    and extended property values, and false otherwise.
#>

function Compare-MSPCompleteUsers {
    param (
        # The users used as the reference objects.
        [Parameter(Mandatory=$true)]
        [AllowEmptyCollection()]
        [Object[]]$referenceUsers,

        # The users used as the comparison objects.
        [Parameter(Mandatory=$true)]
        [AllowEmptyCollection()]
        [Object[]]$comparisonUsers
    )

    # Check if list of users is identical
    if ($referenceUsers.length -ne $comparisonUsers.length) {
        Write-Error "Lengths of user lists are different: $($referenceUsers.length) and $($comparisonUsers.length)."
        return $false
    }

    # Sort lists by UserPrincipalName
    $referenceUsers = $referenceUsers | Sort-Object -Property UserPrincipalName
    $comparisonUsers = $comparisonUsers | Sort-Object -Property UserPrincipalName

    # Run through users to compare
    for ($i = 0; $i -lt $referenceUsers.length; ++$i) {
        if (!(Compare-MSPCompleteUser -ReferenceUser $referenceUsers[$i] -ComparisonUser $comparisonUsers[$i] -ErrorAction Stop)) {
            return $false
        }
    }

    # Users match
    return $true
}

<#
.SYNOPSIS
    This function converts a user from a different environment to a MSPComplete user.
.DESCRIPTION
    This function converts a user from a different environment to a MSPComplete user.
    The conversion is done by mapping the other user to the MSPComplete user's
    properties and extended properties.
#>

function ConvertTo-MSPCompleteUserForm {
    param (
        # A user from Exchange Online
        [Parameter(Mandatory=$true, ParameterSetName="ExchangeOnline")]
        $exchangeOnlineUser
    )

    if ($PSCmdlet.ParameterSetName -eq "ExchangeOnline") {
        # Retrieve mapping from MSPComplete user to Exchange Online user properties
        $propertyMap = Get-MSPCompleteUserToExchangeOnlineUserPropertyMap

        # Create MSPComplete user
        $mspCompleteUser = [PSCustomObject]@{}

        # Add all properties to the MSPComplete user
        foreach ($property in $propertyMap.GetEnumerator()) {
            if (![String]::IsNullOrWhiteSpace($exchangeOnlineUser.($property.Value))) {
                $mspCompleteUser | Add-Member -NotePropertyName $property.Key -NotePropertyValue $exchangeOnlineUser.($property.Value)
            }
        }

        # Retrieve mapping from MSPComplete user to Exchange Online user extended properties
        $extendedPropertyMap = Get-MSPCompleteUserToExchangeOnlineUserExtendedPropertyMap

        # Add all extended properties to the MSPComplete user
        $mspCompleteUser | Add-Member -NotePropertyName "ExtendedProperties" -NotePropertyValue @{}
        foreach ($property in $extendedPropertyMap.GetEnumerator()) {
            if (![String]::IsNullOrWhiteSpace($exchangeOnlineUser.($property.Value))) {
                $mspCompleteUser.ExtendedProperties.Add($property.Key, $exchangeOnlineUser.($property.Value))
            }
        }
    }

    # Return the MSPComplete user
    return $mspCompleteUser
}