Unique Usernames

Here is the world I live in. Our company must keep records of all those that have touched the core application for the life of the company. These records include the user account. This means, no deleting any usernames. We have a turn over rate of 50%. So, how do you create unique usernames for cChrissmith when you already have 3 Chris smiths without using numbers? The answer seems simple, middle names. Well… Middle names tend to be the same. We have two Chris Richard Smiths in the company. Now, lets throw in another block, the usernames can’t pass 10 char. This means, if the name is long, it has to be cut off at 10 char. The username can’t have any unique characters either and it must be lowercased. Thus the name can only have a-z. Also hyphenated requires to be a single last name. Which means, we have to select from one of the names… That gets messy, so making it a single thing makes it easier. Oh, the fun of the legacy system.

The Script

function Auto-FullNameUserName {
     
    [cmdletbinding()]
    param (
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string]$FirstName,
        [Parameter(ValueFromPipelineByPropertyName=$true)][string]$MiddleName = $null,
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string]$LastName
    )
    $Return = @()
    $FirstNameOrig = $FirstName
    $LastNameOrig = $LastName
    if ($MiddleName -ne "") {$Name = "$FirstName $MiddleName $LastName"} else {$Name = "$FirstName $LastName"}
    
    $FirstName = $FirstName.Split('-')[0]
    $FirstName = $FirstName -replace '[^a-zA-Z]',''
    $LastName = $LastName.Split('-')[0]
    $LastName = $LastName -replace '[^a-zA-Z]',''
    


    #We create our default first letter of the first name and last name.
    $Username = "$($FirstName.Substring(0,1))$($Lastname)"

    #Next we limit the size if need be. Dovac has a 10 char cap. So, if the username is 10 chars, we cut it at the 10th char and place it back into username.
    if ($Username.Length -ge 10) {$Username = $Username.Substring(0,10);Write-Verbose "Limited"}

    #Then we do some old school testing to see if the username exists. If the username does not exist, we produce our answer.
    if (!(dsquery user -samid $Username)) {

        #We check to see if there is a middle name. If so that will become the inital.
        if ($MiddleName -ne "") {$Init = $MiddleName.substring(0,1)} else {$Init = $null}
        $Return += [pscustomobject][ordered]@{
            Name = $Name 
            GivenName = $FirstNameOrig
            Initial = $Init
            Surname = $LastNameOrig
            #Our standard requires lowercased usernames.
            Username = $Username.ToLower()
        }
            

        #If the username does exist we ask if we have a middle name to work with.
    } elseif ($MiddleName -ne $null) {

        #We add the first letter of the middle name to the mix.
        $Username = "$($FirstName.Substring(0,1))$($MiddleName.substring(0,1))$($Lastname)"
            
        #Then we test it to see if it is to long or not. If it is, we shorten it to 10 char.
        if ($Username.Length -ge 10) {$Username = $Username.Substring(0,10);Write-Verbose "Limited"}

        #If that username doesn't exist, then we produce our answer.
        if (!(dsquery user -samid $Username)) {
            if ($MiddleName -ne "") {$Init = $MiddleName.substring(0,1)} else {$Init = $null}
            $Return += [pscustomobject][ordered]@{
                Name = $Name 
                GivenName = $FirstNameOrig
                Initial = $Init
                Surname = $LastNameOrig
                Username = $Username.ToLower()
            }
                

            #However, if it does exist. Then we start working with our loop. 
        } else {
                
            #We will loop through each char of the first name adding it and shortening it then testing it until we get a username that is unique and works. 
                
            Write-Verbose "Name - $Firstname $Lastname"
            for ($A = 1; $A -le $FirstName.ToCharArray().count; $A++) {

                #We start off A as 1 because it A0 has aleady be tested. Then we loop through which pushes the first name towards the front. 
                $Username = "$($FirstName.Substring(0,$A))$($Lastname)"
                Write-Verbose "$Username"

                #We cut it down to size
                if ($Username.Length -ge 10) {$Username = $Username.Substring(0,10);Write-Verbose "Limited"}

                #Then we test it. If success, then we go with that, if not we loop again.
                if (!(dsquery user -samid $Username)) {
                    if ($MiddleName -ne "") {$Init = $MiddleName.substring(0,1)} else {$Init = $null}
                    $Return += [pscustomobject][ordered]@{
                        Name = $Name 
                        GivenName = $FirstNameOrig
                        Initial = $Init
                        Surname = $LastNameOrig
                        Username = $Username.ToLower()
                    }
                    Write-Verbose "Break"
                    Break
                }
            }
        }
    } else {
        #if we don't have a middle name to work with we skip stright to the loop. 

        for ($A = 1; $A -le $FirstName.ToCharArray().count; $A++) {

            #We start off A as 1 because it A0 has aleady be tested. Then we loop through which pushes the first name towards the front. 
            $Username = "$($FirstName.Substring(0,$A))$($Lastname)"
            Write-Verbose "$Username"

            #We cut it down to size
            if ($Username.Length -ge 10) {$Username = $Username.Substring(0,10);Write-Verbose "Limited"}

            #Then we test it. If success, then we go with that, if not we loop again.
            if (!(dsquery user -samid $Username)) {
                if ($MiddleName -ne "") {$Init = $MiddleName.substring(0,1)} else {$Init = $null}
                $Return += [pscustomobject][ordered]@{
                    Name = $Name 
                    GivenName = $FirstNameOrig
                    Initial = $Init
                    Surname = $LastNameOrig
                    Username = $Username.ToLower()
                }
                #Breaks this loop if we get a good username. 
                break
            }
        }
    }
    $Return
}

I use a process i like to call reverse physiology on this script. If it doesn’t work, then we try something else instead of if it works.

I hope you all like it.

Leave a Reply

Your email address will not be published. Required fields are marked *