public/api/Import-MBSAPIUser.ps1

function Import-MBSAPIUser {
    <#
    .Synopsis
    Import users from CSV file to MBS via API 2.0
 
    .DESCRIPTION
    The cmdlet imports users from CSV file to MBS via API 2.0
 
    .PARAMETER UserFile
    Specify user csv file path. The script uses .\Users.csv by default.
 
    .PARAMETER GeneratePassword
    Generate random password (8 symbols long) for users with blank password fields.
 
    .PARAMETER Force
    Import users without errors from CSV file. By default, in case of any errors in CSV file no users will be imported.
 
    .PARAMETER ProfileName
    Profile name used with MSP360 PowerShell for MBS API (set via Set-MBSApiCredential)
 
    .EXAMPLE
        Import-MBSAPIUser -GeneratePassword
 
        Imports users from file "Users.csv" in current folder. If no password specified for user in CSV file, it will be generated.
 
    .EXAMPLE
        Import-MBSAPIUser -UserFile "D:\Users.csv" -Force
 
        Imports users from file "D:\Users.csv" to MBS. In case of errors, only users with correct information will be imported.
 
    .INPUTS
        None
 
    .OUTPUTS
        None
 
    .NOTES
        Author: Alex Volkov
        Editor: Andrew Anushin
 
    .LINK
        https://kb.msp360.com/managed-backup-service/add-users-and-companies-to-MBS-in-bulk
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$false, HelpMessage="Full path to user CSV file. By default, "".\Users.csv"".")]
        [string]
        $UserFile = "$((Get-Location).Path)\Users.csv",
        #
        [Parameter(Mandatory=$false, HelpMessage="Generate random password if no password specified for user in CSV file.")]
        [switch]
        $GeneratePassword,
        #
        [Parameter(Mandatory=$false, HelpMessage="Import users without errors from CSV file.")]
        [switch]
        $Force,
        #
        [Parameter(Mandatory=$false, HelpMessage="The profile name, which must be unique.")]
        [string]
        $ProfileName
    )
    
    begin {
        if (Test-Path $UserFile) {
            Write-Verbose "$($PSCmdlet.MyInvocation.MyCommand.Name): File ""$UserFile"" found."
            $headers = Get-MBSAPIHeader -ProfileName $ProfileName
        } else {
            Write-Error -Message "Cannot find file ""$UserFile"""
            Break
        }
    }

    process {
        [array]$UsersCSV = Import-Csv -Path $UserFile
        Write-Verbose "$($PSCmdlet.MyInvocation.MyCommand.Name): Checking contents of ""$UserFile"" for errors..."
        $UsersCSV | ForEach-Object {$i = 0; $HasErrors = $False; $SuccessIndexList = [System.Collections.ArrayList]@()} {
            $Errors = "Found errors in line ["+($i+2)+"]: "
            if (-Not ($_.Email)) {
                $Errors += ' Email (empty) '
                $HasErrors = $True
            }
            if (-Not ($_.Enabled)) {
                $Errors += ' Enabled (empty) '
                $HasErrors = $True
            }
            if ((-Not ($_.Password)) -And (-Not ($GeneratePassword))) {
                $Errors += ' Password (empty)'
                $HasErrors = $True
            } elseif (($_.Password) -And ($_.Password.Length -lt 6)) {
                $Errors += ' Password (length less than 6 symbols)'
                $HasErrors = $True
            }
            if (-Not ($_.SendEmailInstruction)) {
                $Errors += ' SendEmailInstruction (empty) '
                $HasErrors = $True
            }
            if (-Not ($HasErrors)) {
                $SuccessIndexList.Add($i) | Out-Null
            } else {
                Write-Verbose "$($PSCmdlet.MyInvocation.MyCommand.Name): $Errors"
            }
            $i++
            $HasErrors = $False
        }

        if ((($SuccessIndexList.Count -eq $UsersCSV.Count) -Or (($SuccessIndexList.Count -gt 0) -And ($Force))) -And ($UsersCSV.Count -gt 0)) {
            $CurrentDateTime = -join (('{0:d4}' -f ((Get-Date).Year)), ('{0:d2}' -f ((Get-Date).Month)), ('{0:d2}' -f ((Get-Date).Day)), ('{0:d2}' -f ((Get-Date).Hour)), ('{0:d2}' -f ((Get-Date).Minute)), ('{0:d2}' -f ((Get-Date).Second)))
            $ExportPath = ($UserFile.Substring(0, $UserFile.LastIndexOf('\'))) + "\ImportedUsers_" + $CurrentDateTime + ".csv"
            $SuccessIndexList | ForEach-Object {$i = 0} {
                Write-Progress -Activity "Adding users to MBS" -Id 1 -PercentComplete (($i/$SuccessIndexList.Count)*100) -CurrentOperation ($UsersCSV[$_].'Email')
                Write-Host "Adding user ""$($UsersCSV[$_].'Email')"""
                $NotificationEmailsArray = $UsersCSV[$_].'NotificationEmails' -split ';'
                if ((-Not ($UsersCSV[$_].'Password')) -And ($GeneratePassword)) {
                    $PasswordChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".tochararray()
                    $Password = ($PasswordChars | Get-Random -Count 8) -Join ''
                } else {
                    $Password = $UsersCSV[$_].'Password'
                }
                $UsersPost = @{
                    Email = $UsersCSV[$_].'Email'.Trim()
                    FirstName =  $UsersCSV[$_].'FirstName'
                    LastName =  $UsersCSV[$_].'LastName'
                    NotificationEmails = @($NotificationEmailsArray)
                    Company =  $UsersCSV[$_].'Company'.Trim()
                    Enabled =  $UsersCSV[$_].'Enabled'
                    Password =  $Password
                    SendEmailInstruction =  $UsersCSV[$_].'SendEmailInstruction'
                }
                $UsersResponse = Invoke-RestMethod -Uri (Get-MBSApiUrl).Users -Method POST -Headers $headers -Body ($UsersPost|ConvertTo-Json) -ContentType 'application/json'
                Write-Host "Response: $UsersResponse"
                $i++
                if ($GeneratePassword) {
                    $UsersPostObject = New-Object -TypeName PSObject
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name Email -Value ($UsersPost.Get_Item("Email"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name FirstName -Value ($UsersPost.Get_Item("FirstName"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name LastName -Value ($UsersPost.Get_Item("LastName"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name NotificationEmails -Value ($UsersCSV[$_].'NotificationEmails')
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name Company -Value ($UsersPost.Get_Item("Company"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name Enabled -Value ($UsersPost.Get_Item("Enabled"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name Password -Value ($UsersPost.Get_Item("Password"))
                    $UsersPostObject | Add-Member -MemberType NoteProperty -Name SendEmailInstruction -Value ($UsersPost.Get_Item("SendEmailInstruction"))
                    Export-CSV -InputObject $UsersPostObject -Path $ExportPath -NoTypeInformation -Append
                }
            }
            if ($GeneratePassword) {
                Write-Host "List of imported users has been exported to: ""$ExportPath"""
            }
        } elseif (($SuccessIndexList.Count -gt 0) -And (-Not ($Force))) {
            Write-Error -Message "Nothing imported. There was a number of incorrect lines in CSV file. You can view the errors by running the script with ""-Verbose"" parameter. If you want to import at least correct lines from CSV file, use ""-Force"" parameter."
        } elseif ($UsersCSV.Count -eq 0) {
            Write-Error -Message "Nothing imported. CSV file is empty."
        } else {
            Write-Error -Message "Nothing imported. This may happen if there were no correct lines in CSV file."
        }
    }

    end {

    }
}

# SIG # Begin signature block
# MIIbtQYJKoZIhvcNAQcCoIIbpjCCG6ICAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB2MTf4ho3HrCAz
# 016V6rgyM1LkbolwTKDa/TqU/fXUhqCCC04wggVmMIIETqADAgECAhEA3VtfmfWb
# K32tKkM2xJo7CjANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJHQjEbMBkGA1UE
# CBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQK
# ExFDT01PRE8gQ0EgTGltaXRlZDEjMCEGA1UEAxMaQ09NT0RPIFJTQSBDb2RlIFNp
# Z25pbmcgQ0EwHhcNMTcxMjE0MDAwMDAwWhcNMjExMjE0MjM1OTU5WjCBqDELMAkG
# A1UEBhMCQ1kxDTALBgNVBBEMBDEwOTUxETAPBgNVBAgMCExlZmNvc2lhMRAwDgYD
# VQQHDAdOaWNvc2lhMRUwEwYDVQQJDAxMYW1wb3VzYXMsIDExJjAkBgNVBAoMHVRy
# aWNoaWxpYSBDb25zdWx0YW50cyBMaW1pdGVkMSYwJAYDVQQDDB1UcmljaGlsaWEg
# Q29uc3VsdGFudHMgTGltaXRlZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
# ggEBAJC5Ak9MZHfMGygnL9B+2OcFRvnTeYAJPa4tJS/ES3eSBBge9BiBUa6f+QlX
# lIjt+NBD9QrewScUj9EnaguKzc8NFonBJAgT43jD5rCuuj3GljTIHftLDF9vgetf
# 7KUYhwMypqxRP8pLMAuXzIzw5Yxjh1Quy92dZyJYpOuGbz1PQVRMj2fhRqeerP4J
# OiRktwnykjrxDsRNm+Iuas1BM+vjVA7B9Cj0Wf5NsMxSegJezvs0yqwHrsngEQrY
# GXDKHstfsxd8KM5LxJdYN1neIAO8v6AuM6yjQT1z1ZwVSCHu2swNCA3T3M26fkk9
# 9TIZZI/LvfR++FJCUvJkPoPbOKUCAwEAAaOCAbMwggGvMB8GA1UdIwQYMBaAFCmR
# YP+KTfrr+aZquM/55ku9Sc4SMB0GA1UdDgQWBBRqlxdnVxjIxF6fnOYUd7LOYeNe
# rjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEF
# BQcDAzARBglghkgBhvhCAQEEBAMCBBAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIB
# AwIwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMw
# QwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RP
# UlNBQ29kZVNpZ25pbmdDQS5jcmwwdAYIKwYBBQUHAQEEaDBmMD4GCCsGAQUFBzAC
# hjJodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDb2RlU2lnbmluZ0NB
# LmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMCQGA1Ud
# EQQdMBuBGWNvbnRhY3RAY2xvdWRiZXJyeWxhYi5jb20wDQYJKoZIhvcNAQELBQAD
# ggEBAEeInauUdqKYV4ncwGMqz5+frptASCXVnCMLI7j3JK0KCzmJkwHHmkIk3P0A
# Rzedj5+1aFuXANtT42IACVf00tqq0IHO2KT2vHHJHNnx3ht6kMcCmKmUlnkZMjEK
# +0WJD0JSP7lBRQBf5QJpDLmpbBTVvlbe/3nzpUZ95O5reaPekoQ1xC4Ossu06ba0
# djKhwk0HgeqZz7ZruWOVY/YRDfnlZ3it5+4Ck2JTXIVcUcXzT/ZdwNTkUiIqmh4T
# HwOj+k/Yej7Q13ILWTNZMELs3Iec6FSSGXUijHV65pPI0dUXnq8pWYMfutgwlBaL
# 78yXl4ihf46TXsnAMottH+ld8lAwggXgMIIDyKADAgECAhAufIfMDpNKUv6U/Ry3
# zTSvMA0GCSqGSIb3DQEBDAUAMIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
# YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
# RE8gQ0EgTGltaXRlZDErMCkGA1UEAxMiQ09NT0RPIFJTQSBDZXJ0aWZpY2F0aW9u
# IEF1dGhvcml0eTAeFw0xMzA1MDkwMDAwMDBaFw0yODA1MDgyMzU5NTlaMH0xCzAJ
# BgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcT
# B1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSMwIQYDVQQDExpD
# T01PRE8gUlNBIENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
# ADCCAQoCggEBAKaYkGN3kTR/itHd6WcxEevMHv0xHbO5Ylc/k7xb458eJDIRJ2u8
# UZGnz56eJbNfgagYDx0eIDAO+2F7hgmz4/2iaJ0cLJ2/cuPkdaDlNSOOyYruGgxk
# x9hCoXu1UgNLOrCOI0tLY+AilDd71XmQChQYUSzm/sES8Bw/YWEKjKLc9sMwqs0o
# GHVIwXlaCM27jFWM99R2kDozRlBzmFz0hUprD4DdXta9/akvwCX1+XjXjV8QwkRV
# PJA8MUbLcK4HqQrjr8EBb5AaI+JfONvGCF1Hs4NB8C4ANxS5Eqp5klLNhw972GIp
# pH4wvRu1jHK0SPLj6CH5XkxieYsCBp9/1QsCAwEAAaOCAVEwggFNMB8GA1UdIwQY
# MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBQpkWD/ik366/mmarjP
# +eZLvUnOEjAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV
# HSUEDDAKBggrBgEFBQcDAzARBgNVHSAECjAIMAYGBFUdIAAwTAYDVR0fBEUwQzBB
# oD+gPYY7aHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2VydGlmaWNh
# dGlvbkF1dGhvcml0eS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsGCCsGAQUFBzAChi9o
# dHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FBZGRUcnVzdENBLmNydDAk
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEB
# DAUAA4ICAQACPwI5w+74yjuJ3gxtTbHxTpJPr8I4LATMxWMRqwljr6ui1wI/zG8Z
# wz3WGgiU/yXYqYinKxAa4JuxByIaURw61OHpCb/mJHSvHnsWMW4j71RRLVIC4nUI
# BUzxt1HhUQDGh/Zs7hBEdldq8d9YayGqSdR8N069/7Z1VEAYNldnEc1PAuT+89r8
# dRfb7Lf3ZQkjSR9DV4PqfiB3YchN8rtlTaj3hUUHr3ppJ2WQKUCL33s6UTmMqB9w
# ea1tQiCizwxsA4xMzXMHlOdajjoEuqKhfB/LYzoVp9QVG6dSRzKp9L9kR9GqH1NO
# MjBzwm+3eIKdXP9Gu2siHYgL+BuqNKb8jPXdf2WMjDFXMdA27Eehz8uLqO8cGFjF
# BnfKS5tRr0wISnqP4qNS4o6OzCbkstjlOMKo7caBnDVrqVhhSgqXtEtCtlWdvpnn
# cG1Z+G0qDH8ZYF8MmohsMKxSCZAWG/8rndvQIMqJ6ih+Mo4Z33tIMx7XZfiuyfiD
# FJN2fWTQjs6+NX3/cjFNn569HmwvqI8MBlD7jCezdsn05tfDNOKMhyGGYf6/VXTh
# IXcDCmhsu+TJqebPWSXrfOxFDnlmaOgizbjvmIVNlhE8CYrQf7woKBP7aspUjZJc
# zcJlmAaezkhb1LU3k0ZBfAfdz/pD77pnYf99SeC7MH1cgOPmFjlLpzGCD70wgg+5
# AgEBMIGSMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0
# ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVk
# MSMwIQYDVQQDExpDT01PRE8gUlNBIENvZGUgU2lnbmluZyBDQQIRAN1bX5n1myt9
# rSpDNsSaOwowDQYJYIZIAWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC
# NwIBFTAvBgkqhkiG9w0BCQQxIgQgLcHPoqtlfdked0lzy4VpvTpmNS7/wR7arGsJ
# XDvOUOcwDQYJKoZIhvcNAQEBBQAEggEANLymeu9jtQVjoLN5S/p9wRGIZ501uyfa
# 6rqnWERjMP4fbn6wRFSeSJnR0nGhjrpmcnvOrSTw/2QXVfoVGKQ96U35CaPpjFfj
# 6dNbAxgEP/zxgXW7YJZhdGQUHgd7WYdUoiWQI1Yqf0DU3gtOobw/rEBbx2cXTqOm
# ClSWjox2jCU4L4SITel6kJ1FtJlvh3glRvkejXj8ntSNSlfnVGgR9FBoRdFNmT1K
# cNy/6BmYQeTTLfIzcSqYJxjAW3cff8ihPFxBnN5xHiRkG2Kbfc1h4EFDTDNE+k09
# UEIxenSr5gUtjTgj88DR6tCR+K0aSXUJEobilPtgnEyZ7RjxTXH7taGCDX0wgg15
# BgorBgEEAYI3AwMBMYINaTCCDWUGCSqGSIb3DQEHAqCCDVYwgg1SAgEDMQ8wDQYJ
# YIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQAQSgaARmMGQCAQEGCWCGSAGG/WwHATAx
# MA0GCWCGSAFlAwQCAQUABCBB5qy/x6I5nIBrxdQfy5728xXTR582SfgFZMoqX8rU
# aQIQdguMz6pmIMsXHqJFcwgK3RgPMjAyMTA2MjUxOTE0NDJaoIIKNzCCBP4wggPm
# oAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAwcjELMAkGA1UE
# BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj
# ZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVz
# dGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAwMDBaMEgxCzAJ
# BgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UEAxMXRGln
# aUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4dyG+RawyW5xpc
# SO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnHbQk9vmp2h+mK
# vfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1LsVDmQTo3Vobc
# kyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpKjIjF9zBa+RSv
# FV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756WwogL0sJyZWnjbL6
# 1mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNVHQ8BAf8EBAMC
# B4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBBBgNVHSAE
# OjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2lj
# ZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIlssgXNW4wHQYD
# VR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgwMqAwoC6GLGh0
# dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMuY3JsMDKgMKAu
# hixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDCB
# hQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
# dC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcN
# AQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIlxHBZvhSg5SeB
# pU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie38+dSn5On7UOe
# e+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTzZTlwS/Oc1np7
# 2gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0yOIHa9GCiurRS
# +1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4TrweOjSaH6zqe/
# Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUxMIIEGaADAgECAhAKoSXW1jIb
# fkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xNjAxMDcxMjAwMDBa
# Fw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lD
# ZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92puoKZxTlUKFe2I0rEDgdFM1EQ
# fdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I1moUADj3Lh477sym9jJZ/l9l
# P+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6Ij4YrBHk8JkDbTuFfAnT7l3I
# mgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkUxk0kIzBdvOw8YGqsLwfM/fDq
# R9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqYD4R/nzEU1q3V8mTLex4F0IQZ
# chfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXdrKzpVv+TAgMBAAGjggHOMIIB
# yjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgXNW4wHwYDVR0jBBgwFoAUReui
# r/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
# BAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYIKwYBBQUHAQEEbTBrMCQGCCsG
# AQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0
# dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD
# QS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwz
# LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwUAYDVR0g
# BEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRp
# Z2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4IBAQBx
# lRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC/cWnww4gQiyvd/MrHwwhWiq3
# BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6CJR7Euhx7LCHi1lssFDVDBGiy
# 23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyvKYnleB/WCxSlgNcSR3CzddWT
# hZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOFIoxhynmUfln8jA/jb7UBJrZs
# pe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bhfEJCKMYYVs9BNLZmXbZ0e/VW
# MyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYwcjELMAkGA1UEBhMCVVMxFTAT
# BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx
# MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBD
# QQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEFAKCB0TAaBgkqhkiG9w0B
# CQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIxMDYyNTE5MTQ0Mlow
# KwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGRvu9ryhaRtaq0lKYkm/MwLwYJ
# KoZIhvcNAQkEMSIEIE2BddyI3E2usFsckRFUOmqfJ1KO2/NSfMOdxbV7KAYMMDcG
# CyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmDB5FXKeBEA0Fcg+MpK2FPJpZM
# jTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBAET4ndIn5Hfe5DU0+E1dupOVGAud9Xa2
# R7IVI7QP6KvOYIgNCGVRPbA3QfzBfhSNBcus+6GTQudmczD4yBPQLn9H+VzeUhoq
# BMLqjqMtJ1SAoZjAsWqaUX43kDb91qUgl1u/D3k0P9GdLPY71ScxkUbwckxU5Nrx
# USayoS14nQ+qYfIs3n0wdawy4emgoVqsJwSrDYgZmFuikP+HpKq75ojUSTuXgej6
# PjYOkEzeiErZzu9yJdm5iE0yLxXqulTee5+uSEtAPtDrToVAYvbIwtPgauTvH6E2
# 9HgQxbQft1Bo4Jot66J00VMDj9MKxmg/AwFy+q45/4UiSzJdT0/mHtY=
# SIG # End signature block