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. For more information, see https://kb.msp360.com/managed-backup-service/add-users-and-companies-to-MBS-in-bulk
 
    .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: MSP360 Onboarding Team
 
    .LINK
        https://mspbackups.com/AP/Help/powershell/cmdlets/api/import-mbsapiuser
    #>


    [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
# MIInWwYJKoZIhvcNAQcCoIInTDCCJ0gCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA0UQBDhZ8z1LzO
# Do23BQoEeg6ZN5spetG8eodT0GiS6aCCEekwggVvMIIEV6ADAgECAhBI/JO0YFWU
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s
# hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD
# J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7
# P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme
# me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz
# T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q
# RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz
# mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc
# QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T
# OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/
# AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID
# AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD
# VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV
# HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE
# VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v
# ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE
# KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
# hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF
# OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC
# J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ
# pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl
# d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH
# +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M
# UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv
# ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5
# NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp
# BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI
# ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV
# DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3
# 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw
# mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm
# +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe
# dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4
# 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM
# dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY
# MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU
# pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV
# HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG
# A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1
# YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG
# AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl
# U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
# aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh
# w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd
# OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj
# cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc
# WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO
# hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs
# zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7
# 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J
# KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH
# j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2
# Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/
# L9Uo2bC5a4CH2RwwggZUMIIEvKADAgECAhBQGj1MeADxcRs/FOU26uyrMA0GCSqG
# SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0
# ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw
# HhcNMjExMjAzMDAwMDAwWhcNMjQxMjAyMjM1OTU5WjBYMQswCQYDVQQGEwJVUzEV
# MBMGA1UECAwMUGVubnN5bHZhbmlhMRgwFgYDVQQKDA9NU1BCeXRlcywgQ29ycC4x
# GDAWBgNVBAMMD01TUEJ5dGVzLCBDb3JwLjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
# ADCCAgoCggIBAKNUOYUGihQGjTJdJ6k5Fm3+6QJGhj2wUbubiiqxJeqmW6616o5e
# ExwiGSxPOqafJzOJNq0XOigb3OQhtdIR4bG38+JghFt8rZe/DxBmPBZDR9bD1hrk
# 9vY714QhqvhIlUDXHnDUc9pnVGFfI945hRgaFHL77GQAEFyMvjNupOvT674/E8rI
# gYKMQBwY0cqiuRQwr3FnRMmNhd8/5mqrZGglDT1JizOnpfFVgNJ0x4ev7mPYIF6T
# rFGPwHsOOujzydmGgqvtGASEuz74A6arzYrhbjXv8XsEdT2tz6hHIpMwsgWMk6BD
# KDCsSIl5oEmVbQNXKrC0k62/XpbWRd+i350k07kl1bdV+nbi1K62TyS+7eVxehC1
# gFp+Knob1aqAJD9sPBLdbN3E4FOB/rvOLP1i2IxAcTGirAyRkkUriD4LUSWO6pju
# Qv2V4ZU/+K/3ZLXYCbIflzpDq6z9FmazK5csv99Coslv9s6lm9s1RRxgRBj5sn1q
# Xe/5l0VbF7tG/cgBvt8aJBD0u8knujI17lDy1TGA77r/KKj65xSsxC6nm0RA9pTw
# 0tz5OQ4ABYrH6TpdUBJz8m8cFgPipvyohN0RdE7InB3Nao11L1UHlnnL0SG1z5qQ
# YU7BhvfiSu44pSY9/uTPmAPlNIj3MO5utjfMD+MX9u86d8h/DWwrvQZzAgMBAAGj
# ggGcMIIBmDAfBgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4E
# FgQU7XGG9N0fpUpnonmgh6+IzR3lGj0wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB
# /wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEoG
# A1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8v
# c2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRw
# Oi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2
# LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2Vj
# dGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3J0MCMGCCsG
# AQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOC
# AYEAhLlUlrWxmB3MSCX9LcaY3p6jCnaeFR4chgRmhjdH+Gy5UyFpEq1/3X/Pv2Ih
# GGnX0uVbXsQ90D/CwFk7bXCFUUblu4ldzNqjmnf+lcTtv/WJR9FTS9t79WdiWbuN
# /YIEXVDERUGPC7v55aaJvXJbDS+4vYeJPAHl2xsvbARWui1nwBLOSVGTGk6T2Q6s
# BnlHFToFc4UFtMhYUMf8L03jypocNGM9z6yamsOANd/dXt582U5DD0g7SVS2pyHD
# Ot7UvVq6769TGZNwq9s1tFwQjm3IGz4DIO1ADMwoGLzqqalYQ1xq2JAqUq41hSlN
# YHecLTjAOTwA81wv71XbZdARR0DfmpqdzdKkTbVucWhJFWL7clDQ0WzfAx1/ZsjR
# t6X9p+XuLnJPMD3V5swX52ZCcB6LY3FyK7kgwNseH+Xqo+Ln7OtAs3Bwa/Cm9lbL
# xYs8wkDitxFnpKFstyE7EE+wtEJkyszfLqjkmUCw/hjzX6I40hahbPCxaxdlv8+3
# drczMYIUyDCCFMQCAQEwaDBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGln
# byBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcg
# Q0EgUjM2AhBQGj1MeADxcRs/FOU26uyrMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYB
# BAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGC
# NwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEdJf/3qiUF2rsLQ
# 1FWz+MSgu9Vzpebm1Rt4J/4EMAgDMA0GCSqGSIb3DQEBAQUABIICAIpeXNbN4RSd
# JlWNFEe027Sgg79NfsbZCpTxBLXuoDq6My4BUV1xkfeo3Koa+UzjO9/pNqYALGGl
# B13VgwCM7fFcB/9KtKrpNsFxWDRjokS3wSTsNQGpOsgtlSv8NxptfYzECVw7OcwV
# lvXqz5sTmQpfYf+b/IuLHNAkLR0t3PmYLfl/Z4YGBVUmtbILwcdIceBH2xJptVl6
# GtbYIJZO0nLJczKu2mByTk2EvanEVVxfRjT0SHSrLXQGT1GXeG8H0gX74aOSQfgq
# r/MDr4BTPGZfmhYPftLJfqzDBSAEM6iDHm3UqNNyv072/eI6xVN3EV34rnR9fCUA
# SPrkFQ3F3NVcCVlfW32mSo3TXAQ8U1pbjEMzmdK+iuo9ByNbXawQGmPhuH49j6d/
# 1FTaP0EpI5nh5/2pCAmmjCyQXyfSOXadbG1Wb+qkRZJN8EffGmJ6nI8BwZ0kbsNU
# pXA1RJa6YkMJt6Q5KqGHyb0Cll8TnwbNRieUNijKGOGEpdgYoVzARthNRzxclkIK
# BLLWJXEuZ2AKHsk+Algtvfl+sRcLcpfT958Rn0vePm7LjrQTmujvYkmbQpZ5a60D
# CREb1HN4lRfZmNAczxeM4OXFdo4DFJjouriBDrAw5GlZZVi47SxwN0LhGfpXVTu1
# 0kdoMbMEB9J9IUghWEn2pIKJr6I6qmkyoYIRszCCEa8GCisGAQQBgjcDAwExghGf
# MIIRmwYJKoZIhvcNAQcCoIIRjDCCEYgCAQMxDzANBglghkgBZQMEAgEFADB4Bgsq
# hkiG9w0BCRABBKBpBGcwZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAE
# IOVDm1Vl4IL8yecAnxBKInjJ/uorAU72aVSNtVEtY0rjAhEAuf8FcQKpyT98+aJK
# 9X6QwRgPMjAyMjA2MTAyMDE1NDdaoIINfDCCBsYwggSuoAMCAQICEAp6SoieyZlC
# kAZjOE2Gl50wDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoT
# DkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJT
# QTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTAeFw0yMjAzMjkwMDAwMDBaFw0z
# MzAzMTQyMzU5NTlaMEwxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjEkMCIGA1UEAxMbRGlnaUNlcnQgVGltZXN0YW1wIDIwMjIgLSAyMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuSqWI6ZcvF/WSfAVghj0M+7MXGzj
# 4CUu0jHkPECu+6vE43hdflw26vUljUOjges4Y/k8iGnePNIwUQ0xB7pGbumjS0jo
# iUF/DbLW+YTxmD4LvwqEEnFsoWImAdPOw2z9rDt+3Cocqb0wxhbY2rzrsvGD0Z/N
# CcW5QWpFQiNBWvhg02UsPn5evZan8Pyx9PQoz0J5HzvHkwdoaOVENFJfD1De1Fks
# RHTAMkcZW+KYLo/Qyj//xmfPPJOVToTpdhiYmREUxSsMoDPbTSSF6IKU4S8D7n+F
# AsmG4dUYFLcERfPgOL2ivXpxmOwV5/0u7NKbAIqsHY07gGj+0FmYJs7g7a5/KC7C
# nuALS8gI0TK7g/ojPNn/0oy790Mj3+fDWgVifnAs5SuyPWPqyK6BIGtDich+X7Aa
# 3Rm9n3RBCq+5jgnTdKEvsFR2wZBPlOyGYf/bES+SAzDOMLeLD11Es0MdI1DNkdcv
# nfv8zbHBp8QOxO9APhk6AtQxqWmgSfl14ZvoaORqDI/r5LEhe4ZnWH5/H+gr5BSy
# FtaBocraMJBr7m91wLA2JrIIO/+9vn9sExjfxm2keUmti39hhwVo99Rw40KV6J67
# m0uy4rZBPeevpxooya1hsKBBGBlO7UebYZXtPgthWuo+epiSUc0/yUTngIspQnL3
# ebLdhOon7v59emsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EM
# AQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57I
# bzAdBgNVHQ4EFgQUjWS3iSH+VlhEhGGn6m8cNo/drw0wWgYDVR0fBFMwUTBPoE2g
# S4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNB
# NDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcw
# AoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0
# UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOC
# AgEADS0jdKbR9fjqS5k/AeT2DOSvFp3Zs4yXgimcQ28BLas4tXARv4QZiz9d5YZP
# vpM63io5WjlO2IRZpbwbmKrobO/RSGkZOFvPiTkdcHDZTt8jImzV3/ZZy6HC6kx2
# yqHcoSuWuJtVqRprfdH1AglPgtalc4jEmIDf7kmVt7PMxafuDuHvHjiKn+8RyTFK
# WLbfOHzL+lz35FO/bgp8ftfemNUpZYkPopzAZfQBImXH6l50pls1klB89Bemh2RP
# PkaJFmMga8vye9A140pwSKm25x1gvQQiFSVwBnKpRDtpRxHT7unHoD5PELkwNuTz
# qmkJqIt+ZKJllBH7bjLx9bs4rc3AkxHVMnhKSzcqTPNc3LaFwLtwMFV41pj+VG1/
# calIGnjdRncuG3rAM4r4SiiMEqhzzy350yPynhngDZQooOvbGlGglYKOKGukzp12
# 3qlzqkhqWUOuX+r4DwZCnd8GaJb+KqB0W2Nm3mssuHiqTXBt8CzxBxV+NbTmtQyi
# maXXFWs1DoXW4CzM4AwkuHxSCx6ZfO/IyMWMWGmvqz3hz8x9Fa4Uv4px38qXsdhH
# 6hyF4EVOEhwUKVjMb9N/y77BDkpvIJyu2XMyWQjnLZKhGhH+MpimXSuX4IvTnMxt
# tQ2uR2M4RxdbbxPaahBuH0m3RFu0CAqHWlkEdhGhp3cCExwwggauMIIElqADAgEC
# AhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMw
# MDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5E
# aWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0
# MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC
# DwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la
# 9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4r
# gISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/Z
# kIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y
# 3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6ws
# OeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz
# 9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4
# xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB
# 7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhK
# WD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8e
# CXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQAB
# o4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3Mp
# dpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYD
# VR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGsw
# aTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUF
# BzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk
# Um9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2Vy
# dC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeB
# DAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQi
# AX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+Vc
# W9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/
# q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6Wvep
# ELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoar
# CkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJS
# pzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrk
# nq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f5
# 6PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2Bn
# FqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ
# 8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW
# +6kvRBVK5xMOHds3OBqhK/bt1nz8MYIDdjCCA3ICAQEwdzBjMQswCQYDVQQGEwJV
# UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRy
# dXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAKekqInsmZ
# QpAGYzhNhpedMA0GCWCGSAFlAwQCAQUAoIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG
# 9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjIwNjEwMjAxNTQ3WjArBgsqhkiG9w0B
# CRACDDEcMBowGDAWBBSFCPOGUVyz0wd9trS3wH8bSl5B3jAvBgkqhkiG9w0BCQQx
# IgQgL9H5ehXbJCHKe41+fXu+qX3njG9n5ulDK2YHABOelyQwNwYLKoZIhvcNAQkQ
# Ai8xKDAmMCQwIgQgnaaQFcNJxsGJeEW6NYKtcMiPpCk722q+nCvSU5J55jswDQYJ
# KoZIhvcNAQEBBQAEggIAtnEjpP5Ha0QJUyqCGSpZg1+nSbYuJAPf1TGGt+GPE5c6
# MkgsN+Yz/1FL7mzoiD0Q1uv2jf4JqNGf17qnsutpzOK6IabmS18nhDBx17gf4uLv
# p65TEgufDqO75fe3jUlXQ/nfKAOW7X5EyUGB1Y+57GAsv+v+Pst9OcRmb7awd4Of
# a59LyZxHGpeHvrv+91jQhQP5Iubp+H0WVVetohyOh7/NaeYqg7861bCkPsPQMyEb
# Wg16VctZkewUXayV9+6zyKvMFzYMCjczIyHIhHnaR2SS4xoUoCs3IS42lmJhIohz
# LXvRuhzqr7OqFzXZimMagOGcqp/tpFV0Phy1APqAcu/nh52En/2/GAgKWINYB8GS
# Z/OSloxGUZ4MKaNQdjzSxVBMMtI2HPKNwwSkWxtOXWjw2odnD04Z/hP4BMXbg+zw
# ojD7PSQQsx3mHsJDz0n8fzSX7CqUP/KMexk+rKAm1siiMB5EnIP91y172A6UYhbH
# OJCJIniGnEAIfMDW7JSvXTl1MeQKb1OrxlKBKX63C2cgRWLc5yfCXsP+D3bB5NIl
# 3Uhe3KX2a4SI1HVD90NhsOs88F8W9xn5j8c2ZPmFONVZWQkENiRVP+RcqLglochJ
# 6kwhOdTIigpOfEhQb1EAxXYosbAwi/Vycn7d/tPApIhCbPMORIaBQH8lx74v8ZQ=
# SIG # End signature block