Public/AD/New-AdUserFromPopuliPerson.ps1

function New-AdUserFromPopuliPerson
{

    [CmdletBinding(PositionalBinding = $true)]
    param
    (
        [Parameter(Mandatory = $true)][object]$PersonInput,
        [Parameter(Mandatory = $true)][string]$DomainName,
        [Parameter(Mandatory = $true)]$RoleOuMap,

        [Parameter(Mandatory = $false)][ValidateLength(200, 999)][string]$PopuliToken = $env:PopuliToken,
        [Parameter(Mandatory = $false)][ValidatePattern('^(?i)https:\/\/\S+\.populiweb\.com\/?$')][string]$BaseUrl = $env:PopuliBaseUrl
    )


    try
    {

        $PersonId = $PersonInput.Person.PersonId

        Write-Log "Processing person with Popuili PersonId ""$($PersonId)""" -PersonId $PersonId

        $personObj = Get-PopuliPerson -PersonId $PersonId -PopuliToken $PopuliToken -BaseUrl $BaseUrl

        if ($personObj.first.Length -lt 1 -or $personObj.last.Length -lt 1)
        {
            Write-Log "Error creating new aduser from Populi person ""$PersonId"". No valid Person was returned from Populi using command: Get-PopuliPerson -PersonId ""$PersonId""" -LogType: warning -PersonId $PersonId
            $PersonInput.Steps.'Populi Fetch User' = 'ERROR: ErrorFetchingPersonFromPopuli'
            return $PersonInput
        }

        $PersonInput.Steps.'Populi Fetch User' = 'OK'

        $firstName = $personObj.first
        $lastName = $personObj.last

        if ($personObj.preferred_name.Length -gt 0)
        {
            $firstName = $personObj.preferred_name
        }

        if ($personObj.prefix.Length -gt 0)
        {
            $displayName = "$lastName, $($personObj.prefix) $firstName"
        }
        else
        {
            $displayName = "$lastName, $firstName"
        }

        $firstInitial = $firstName[0].ToString().ToUpper()
        $lastInitial = $lastName[0].ToString().ToLower()
        $password = $firstInitial + $lastInitial + $PersonId
        $passwordSecureString = $password | ConvertTo-SecureString -AsPlainText -Force

        $samAccountName = $firstInitial.ToLower() + $lastName.ToLower() -replace '\s'

        $samAccountName = Remove-StringDiacritic $samAccountName

        $email = "$samAccountName@$DomainName"

        $PersonInput.Person.FirstName = $firstName
        $PersonInput.Person.LastName = $lastName
        $PersonInput.Person.LoginName = $samAccountName
        $PersonInput.Person.Password = $password
        $PersonInput.Person.Email = $email
        $PersonInput.Person.PersonalEmail = @($personObj.email | ? {$_.address -match '@' -and $_.address -notmatch $DomainName} | sort is_primary -Descending)[0].address

        $adUserAlreadyExists = $null

        try
        {
            $adUserAlreadyExists = Get-ADUser $samAccountName
        }
        catch
        {
        }

        if ($adUserAlreadyExists)
        {
            Write-Log "Error creating new aduser from Populi person ""$PersonId"" ($displayName). User with SamAccountName ""$samAccountName"" already exists in AD: ""$($adUserAlreadyExists.DistinguishedName)""" -LogType: warning -PersonId $PersonId
            $PersonInput.Steps.'AD Setup' = 'ERROR: AlreadyExistsInAD'
            return $PersonInput
        }

        $personRoles = @(Get-PopuliPersonRoles -PersonId $PersonId -PopuliToken $PopuliToken -BaseUrl $BaseUrl)
        $personTags = @()
        $personTags += $personObj.tags.tag.Name

        $ou = $null

        foreach ($role in $personRoles)
        {
            if ($RoleOuMap.Keys -contains $role.name)
            {
                $PersonInput.Person.UserType = $role.name
                $ou = $RoleOuMap[$role.name]
                break
            }
        }

        if (!$ou)
        {

            if ($personTags -match 'Student')
            {
                $PersonInput.Steps.'Populi Get User Type' = 'OK'
                $defaultRole = 'Student'
            }
            elseif ($personTags -match 'Faculty|Staff')
            {
                $PersonInput.Steps.'Populi Get User Type' = 'OK'
                $defaultRole = 'Faculty'
            }
            elseif ($RoleOuMap.Keys -contains 'default')
            {
                $defaultRole = $RoleOuMap.default
                $PersonInput.Steps.'Populi Get User Type' = "WARN: User did not have a valid role. Used default ""$defaultRole"""
                Write-Log "Could not find a role that matched value in RoleOuMap param. Using default Role: ""$defaultRole""" -PersonId $PersonId
            }
            else
            {
                Write-Log "Cannot create new user ""$PersonId"". Invalid default OU in RoleOuMap param." -PersonId $PersonId
                $PersonInput.Steps.'AD Setup' = "ERROR: InvalidDefaultOU"
                return $PersonInput
            }

            $ou = $RoleOuMap[$defaultRole]
            $PersonInput.Person.UserType = $defaultRole

        }
        else
        {
            $PersonInput.Steps.'Populi Get User Type' = 'OK'
        }


        $newUserProps = [ordered]@{
            Enabled               = $true
            EmployeeId            = $PersonId
            GivenName             = $firstName
            Surname               = $lastname
            SamAccountName        = $samAccountName
            Name                  = $displayName
            DisplayName           = $displayName
            UserPrincipalName     = $email
            EmailAddress          = $email
            AccountPassword       = $passwordSecureString
            PasswordNeverExpires  = $true
            ChangePasswordAtLogon = $false
            Description           = "Automatically created $(Get-Date -Format "yyyy-MM-dd") by Populi-AD-Sync script"
            Path                  = $ou
            ErrorAction           = "Stop"
            Country               = 'US'

        }

        Write-Log "Creating new AD User: $($newUserProps | ConvertTo-Json -Compress)" -PersonId $PersonId

        try
        {
            $newUserResp = New-ADUser @newUserProps
            Write-Log "AD Setup ok!" -PersonId $PersonId
            $PersonInput.Steps.'AD Setup' = 'OK'
        }
        catch
        {
            Write-Log "Error using New-ADUser. PersonId: $PersonId" -LogType error -ErrorObject $_ -PersonId $PersonId
            $PersonInput.Steps.'AD Setup' = "ERROR: Exception calling New-ADUser"
            return $PersonInput
        }



        try
        {
            if ($PersonInput.Person.UserType -match 'Faculty|Staff')
            {
                if ($personTags -notcontains '@O365_employees')
                {
                    $personTags += '@O365_employees'
                    $PersonInput.Steps.'Populi Add Tag @O365_' = Add-PopuliPersonTag -PersonId $PersonId -TagName '@O365_employees' -ErrorAction: Ignore
                }
            }
            else
            {
                if ($personTags -notcontains '@O365_students')
                {
                    $personTags += '@O365_students'
                    $PersonInput.Steps.'Populi Add Tag @O365_' = Add-PopuliPersonTag -PersonId $PersonId -TagName '@O365_students' -ErrorAction: Ignore
                }
            }

            $PersonInput.Steps.'Populi Add Tag @O365_' = 'OK'

        }
        catch
        {
            Write-Log "Error adding O365 tag" -PersonId $PersonId -LogType: error -ErrorObject $_
            $PersonInput.Steps.'Populi Add Tag @O365_' = 'ERROR: See log'
        }



        if ($personTags.Count -gt 0)
        {
            $tagListString = """$($personTags -join '", "')"""
            $PersonInput.Person.Tags = $tagListString

            $adGroupsToAdd = @(Get-ADGroup -Filter * -Properties Description | ? { $_.Description.Length -gt 3 -and $personTags -contains $_.Description })

            if ($adGroupsToAdd.Count -gt 0)
            {
                $adGroupListString = """$($adGroupsToAdd.Name -join '", "')"""
                $PersonInput.Person.AdGroups = $adGroupListString

                Write-Log "Adding ""$samAccountName"" ($PersonId) to $($adGroupsToAdd.Count) AD Group(s). Tags >> $tagListString || Matching AD Groups >> $adGroupListString" -PersonId $PersonId

                foreach ($group in $adGroupsToAdd)
                {
                    try
                    {
                        Add-ADGroupMember -Identity $group.ObjectGUID.Guid -Members $samAccountName -ErrorAction Stop
                        Write-Log "Added ""$samAccountName"" ($PersonId) to AD Group ""$($group.Name)"". Command: Add-ADGroupMember -Identity ""$($group.DistinguishedName)"" -Members ""$samAccountName""" -PersonId $PersonId
                        $PersonInput.Steps.'AD Groups Add' = 'OK'
                    }
                    catch
                    {
                        Write-Log "Error adding ""$samAccountName"" ($PersonId) to AD Group ""$($group.Name)"". Command: Add-ADGroupMember -Identity ""$($group.DistinguishedName)"" -Members ""$samAccountName""" -LogType error -ErrorObject $_ -PersonId $PersonId
                        $PersonInput.Steps.'AD Groups Add' = "ERROR: adding ""$($group.Name)"""
                        continue
                    }

                }
            }
            else
            {
                Write-Log "Could not find any AD Groups that match new user's tags. User: ""$samAccountName"" ($PersonId). Tags: $tagListString " -LogType warning -PersonId $PersonId
                $PersonInput.Steps.'AD Groups Add' = 'WARN: No groups matching tags'
            }

        }
        else
        {
            Write-Log "Skipping AD Group membership for user ""$samAccountName"" ($PersonId). No tags found." -LogType warning -PersonId $PersonId
            $PersonInput.Steps.'AD Groups Add' = 'WARN: No tags'
        }


    }
    catch
    {
        $PersonInput.Steps.'AD Setup' = 'ERROR: Unhandled Exception. See log'
        Write-Log "Unhandled exception" -LogType: error -ErrorObject $_ -PersonId $PersonId

        return $PersonInput
    }

    return $PersonInput


}