public/Import-Users.ps1

Function Import-Users {

    <#
 
    .Synopsis
    Use this function to import users from a CSV file in to Active Directory
 
    .Description
    Users are imported in to an imported users OU, from there you can move them as you wish
 
    .Parameter CSV
    The path to a CSV file containing user data, CSV MUST have 3 columns, firstname, lastname & description
 
    .Parameter UsernameFormat
    Select the format you want for the usernames generated, currently johnd, john.d, jdoe, j.doe, john.doe are supported.
 
    .Parameter Usertype
    Select the type of user account, the function uses this to find the home directory (eg Home$\Staff) and also adds them to the corresponding security group
 
    .Parameter Homeshare
    Path to the Home$ share (eg \\DC01\Home$)
 
    .Parameter Profileshare
    Path to the Profile$ share (eg \\DC01\Profile$)
 
    .Parameter Password
    What password you want for the account, MUST comply with domain policy OR fine grained password policy.
 
    .Parameter RandomPassword
    Tells the function to use www.dinopass.com to generate random passwords for each account
 
    .Parameter Logpath
    What path to generate the log files, by default is current users desktop
 
    .EXAMPLE
    Import-Users -csv C:\users.csv -UsernameFormat -john.d -UserType Office
 
 
    #>

    
    [cmdletbinding(SupportsShouldProcess=$True)]
    #[CmdletBinding(DefaultParameterSetName='password')]
    Param(
        
        [Parameter(
            Mandatory=$true
            )]
        $csv,
        
        [Parameter(
            Mandatory=$true
            )]
        [ValidateSet('johnd','john.d','jdoe','j.doe','john.doe')]
        [string]$UsernameFormat,
        
        [Parameter(
            Mandatory=$true
            )]
        [ValidateSet('Staff','Office','Students')]
        [string]$UserType,

        [Parameter(
            ParameterSetName='password'
            )]
        [string]$Password,
        
        [Parameter(
            ParameterSetName='random'
            )]
        [switch]$RandomPassword,
        
        [string]$HomeShare = "\\$Env:COMPUTERNAME\Home$",
        
        [string]$ProfileShare = "\\$Env:COMPUTERNAME\Profile$",
        
        [string]$LogPath = "$env:USERPROFILE\Desktop\User Import Logs"
    )

    $ErrorActionPreference = "Stop"

    # Setup logging
    $Log = "$LogPath\$(Get-Date -UFormat %Y-%m-%d) Import Log.csv"
    $FailLog = "$LogPath\$(Get-Date -UFormat %Y-%m-%d) FAILED Import Log.csv"

    if (!(Test-Path $Log)) {

        New-Item $Log, $FailLog -Force | Out-Null
        Set-Content -Path $Log -Value '"Full Name","UserName","Description","Password"'
        Set-Content -Path $FailLog -Value '"Full Name","UserName"'
        
        }
    
    # Store the data from the CSV in the $Users variable
    $Users = Import-csv $csv

    if ((Get-Content $csv)[0] -ne "firstname,lastname,description") {

        throw "Check your CSV Headers! Should be 'firstname,lastname,description'"
    
    }
    
    # Show current settings and require confirmation to continue
    Write-Host "Home Folder = $HomeShare\$UserType" -ForegroundColor Green
    Write-Host "Profile Folder = $ProfileShare\$UserType" -ForegroundColor Green
    Write-Host "Username Format = $UsernameFormat" -ForegroundColor Green
    Write-Warning "Please confirm these settings are correct" -WarningAction Inquire
    
    Write-Host "Log file: $LogPath" -ForegroundColor Cyan



    # Set some Variables
    $Domain = (Get-ADDomain).name
    $FullDomain = (Get-ADDomain).dnsroot
    $DomainRoot = (Get-ADDomain).DistinguishedName
    $HomePath = "$HomeShare\$UserType"
    $ProfilePath = "$ProfileShare\$UserType"

    # Tests for an "Imported Users" OU at root of domain and if it does not exist then it creates it
    $ImportOU = "OU=Imported Users,$DomainRoot"

    try {
        Get-ADOrganizationalUnit -Identity $ImportOU | Out-Null
        } catch {
        New-ADOrganizationalUnit -Name "Imported Users" -Path $DomainRoot
        }


    # Check Home & Profile paths exist
    if (!(Test-Path $HomePath)) {
        Throw "Could not find $HomePath!"
    }
        
    if (!(Test-Path $ProfilePath)) {
        Throw "Could not find $ProfilePath!"
    }

    # Loop through each row containing user details in the CSV file

    foreach ($User in $Users) {

        # Read user data from each field in each row and assign the data to a variable as below
            
        $Firstname      = $User.firstname 
        $Lastname      = $User.lastname
        $FullName    = "$Firstname $Lastname"
        $Description = $User.description

        # Select username format

        if ($UsernameFormat -eq "johnd") {
            $Username = $Firstname + $Lastname.substring(0,1)
        }

        if ($UsernameFormat -eq "john.d") {
            $Username = $Firstname + "." + $Lastname.substring(0,1)
        }

        if ($UsernameFormat -eq "jdoe") {
            $Username = $Firstname.substring(0,1) + $Lastname
        }

        if ($UsernameFormat -eq "j.doe") {
            $Username = $Firstname.substring(0,1) + "." + $Lastname
        }

        if ($UsernameFormat -eq "john.doe") {
            $Username = $Firstname + "." + $Lastname
        }
        
        # change to lower case and remove - and ' and spaces
        $Username = $Username.ToLower() -replace "[^a-zA-Z.]"

        # Generate a random password and make the first letter a capital
        if ($RandomPassword) {
            
            $Password = (Get-Culture).TextInfo.ToTitleCase((Invoke-WebRequest "http://www.dinopass.com/password/simple" -Verbose:$False | Select-Object Content -ExpandProperty Content))

            }

        $PasswordSecure = $Password | ConvertTo-SecureString -AsPlainText -Force


        # Create splat of user params
            
        $UserParams = @{
            SamAccountName = $Username
            UserPrincipalName  = "$Username@$FullDomain"
            Name = $FullName
            GivenName = $Firstname
            Surname = $Lastname
            Path = $ImportOU
            ProfilePath = "$ProfilePath\$Username"
            HomeDrive = "H:"
            HomeDirectory = "$HomePath\$Username"
            Description = $Description
            ChangePasswordAtLogon = $true
            }

        # Create an object to make reporting later easier
        
        $UserObject = [PSCustomObject]@{

            Name            = $Fullname
            UserName        = $Username
            Description     = $Description
            Password        = $Password

            }

        try {
            
            # Create the account
            New-ADUser @UserParams
            
            # Create user home folder
            New-Item -Name $Username -Path $HomePath -ItemType Directory | Out-Null
            
            # Set access rights on home folder
            Add-NTFSAccess -Path "$HomePath\$Username" -Account $Username -AccessRights FullControl
            
            # Add to groups
            Add-ADGroupMember -Identity $UserType -Members $Username
            
            # Set account password
            Set-ADAccountPassword -Identity $Username -Reset -NewPassword $PasswordSecure
            Set-ADUser -Identity $Username -Enabled $true -CannotChangePassword $false -ChangePasswordAtLogon $true

            # If student then change password requirements
            if ($UserType -eq "Students") {

                Set-ADUser -Identity $Username -Enabled $true -CannotChangePassword $true -ChangePasswordAtLogon $false -PasswordNeverExpires $true

                }

            # Write success message
            Write-Host "SUCCESS: Created $Username" -ForegroundColor Green

            # Log to file
            $UserObject | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -FilePath $Log -Append -encoding ASCII

            }
    
        catch {

            # Write failure message
            Write-Host "FAILURE: Unable to create $Username" -ForegroundColor Red

            # Log to file
            $UserObject | Select-Object Username | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -FilePath $FailLog -Append -encoding ASCII
            $_.Exception.Message | Out-File -FilePath $FailLog -Append -encoding ASCII
            
            continue
            
            }

        }

}