From 596bca0b4ede4e1601f6e62aee5c6a0288a6550d Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Wed, 21 Aug 2024 18:34:18 +0200 Subject: [PATCH] Streamline the creation of users --- scripts/Common/Scripts/Config.ps1 | 89 ++++++++++++++++++++- scripts/Windows/OS/Install.ps1 | 126 +++++++++++++----------------- scripts/Windows/Scripts/Users.ps1 | 110 +++++++++++++++++++------- 3 files changed, 227 insertions(+), 98 deletions(-) diff --git a/scripts/Common/Scripts/Config.ps1 b/scripts/Common/Scripts/Config.ps1 index 60fca018..e7c56140 100644 --- a/scripts/Common/Scripts/Config.ps1 +++ b/scripts/Common/Scripts/Config.ps1 @@ -9,12 +9,20 @@ enum SetupStage { Configure Install CreateUser - ConfigureUser +} + +enum UserStage { + Create + Configure + Completed } $null = New-Module { [string] $configRoot = "HKLM:\Software\PortValhalla"; [string] $stageOption = "Stage"; + [string] $userOption = "SetupUser"; + [string] $userStageOption = "UserStage"; + [string] $accountOption = "MSAccount"; [string] $finishedOption = "Finished"; [RegistryKey] $key = $null; @@ -273,6 +281,85 @@ $null = New-Module { $null = Set-SetupOption $stageOption $Name; } + <# + .SYNOPSIS + Gets the current user to set up. + #> + function Get-CurrentUser { + return (Get-SetupOption $userOption) ?? 0; + } + + <# + .SYNOPSIS + Sets the index of the current user to set up. + + .PARAMETER Value + The index of the user to set up. + #> + function Set-CurrentUser { + param( + [int] $Value + ) + + Set-SetupOption $userOption $value; + } + + <# + .SYNOPSIS + Gets the name of the current stage of the user setup. + #> + function Get-UserStage { + $stage = Get-SetupOption $userStageOption; + + if ($null -ne $stage) { + $stage = [UserStage]$stage; + } + + return $stage; + } + + <# + .SYNOPSIS + Sets the current stage of the user setup. + + .PARAMETER Name + The name of the stage to set. + #> + function Set-UserStage { + param( + $Name + ) + + if (-not (($null -eq $Name) -or ($Name -is [string]))) { + $Name = ([UserStage]$Name).ToString(); + } + + $null = Set-SetupOption $userStageOption $Name; + } + + <# + .SYNOPSIS + Gets the name of the microsoft account to create. + #> + function Get-MSAccountName { + return Get-SetupOption $accountOption; + } + + <# + .SYNOPSIS + Sets the name of the microsoft account to create. + + .PARAMETER Name + The name of the microsoft account to create. + #> + function Set-MSAccountName { + param( + [string] $Name + ) + + Set-SetupOption $accountOption $Name; + } + <# .SYNOPSIS Gets a value indicating whether the setup has finished. diff --git a/scripts/Windows/OS/Install.ps1 b/scripts/Windows/OS/Install.ps1 index a3ce7631..afabab06 100644 --- a/scripts/Windows/OS/Install.ps1 +++ b/scripts/Windows/OS/Install.ps1 @@ -196,6 +196,9 @@ $null = New-Module { Start-OneShot { switch (Get-OneShotTask) { + ([OneShotTask]::InitializeMSAccount) { + Initialize-UserCreation; + } ([OneShotTask]::DisableUAC) { Disable-UAC; Register-Setup; @@ -536,87 +539,70 @@ $null = New-Module { Set-Stage ([SetupStage]::CreateUser); } ([SetupStage]::CreateUser) { - Start-ValhallaUserSetup; - Set-Stage ([SetupStage]::ConfigureUser); - } - ([SetupStage]::ConfigureUser) { - $userOption = "CurrentUser"; + $users = @(Get-Users); + $i = Get-CurrentUser; - function Get-CurrentUser { - (Get-SetupOption $userOption) ?? 0; - } + for (; $i -lt $users.Count; $i++) { + $name = $users[$i]; + $msAccount = Get-UserConfig -UserName $name "microsoftAccount"; + Set-CurrentUser $i; - function Set-CurrentUser { - param([int] $Value) - Set-SetupOption $userOption $Value; - } + if (Test-Admin) { + Disable-BootMessage; + } - [string[]] $users = Get-Users; - $currentUser = Get-CurrentUser; - - if (Test-Admin) { - Disable-BootMessage; - } - - if ($currentUser -lt $users.Count) { - $user = Get-LocalUser $users[$currentUser]; - $msAccount = Get-UserConfig -UserName "$user" -Name "microsoftAccount"; - - $adminGroup = @{ - SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null); - }; - - Add-LocalGroupMember ` - @adminGroup ` - $user ` - -ErrorAction SilentlyContinue; - - if ($env:UserName -ne "$user") { - Disable-LocalUser $env:UserName; - Enable-LocalUser $user; - - if ($msAccount) { - Enable-UAC; - Disable-Autologin; - Enable-OneShotListener; - Set-BootMessage -Caption "Please Log In" -Message "Please log in using your new Microsoft Account ``$user``."; - } else { - Set-AutologinUser "$user"; - } - - Restart-Intermediate -DefaultUser; - return; - } else { - $configure = { - Deploy-SoftwareAction -Action ([InstallerAction]::ConfigureUser); - Remove-LocalGroupMember -Member "$user" @adminGroup -ErrorAction SilentlyContinue; - - foreach ($group in Get-UserConfig -UserName "$user" "groups") { - Add-LocalGroupMember -Member "$user" -Name "$group"; + while ((Get-UserStage) -ne ([UserStage]::Completed)) { + switch (Get-UserStage) { + ($null) { + Set-UserStage ([UserStage]::Create); + continue; } - } + ([UserStage]::Create) { - if ($msAccount) { - if (-not (Test-Admin)) { - Invoke-OneShot DisableUAC; - Restart-Computer; - return; - } else { - & $configure; - Clear-SetupRegistration; - Disable-OneShotListener; + if ($env:UserName -ne $name) { + New-ValhallaUser $name; + + if ($msAccount) { + Register-Setup -DefaultUser; + logoff; + } else { + Restart-Intermediate; + } + + exit; + } else { + if ($msAccount) { + if (-not (Test-Admin)) { + Invoke-OneShot DisableUAC; + Restart-Computer; + return; + } + + Clear-SetupRegistration; + Disable-OneShotListener; + } + + Set-UserStage ([UserStage]::Configure); + } + } + (([UserStage]::Configure)) { + $adminGroup = @{ + SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null); + }; + + Deploy-SoftwareAction -Action ([InstallerAction]::ConfigureUser); + Remove-LocalGroupMember -Member $name @adminGroup -ErrorAction SilentlyContinue; + + foreach ($group in Get-UserConfig -UserName $name "groups") { + Add-LocalGroupMember -Member $name -Name "$group"; + } } - } else { - & $configure; } } if (-not $msAccount) { - net user "$user" /logonpasswordchg:yes; + net user $name /logonpasswordchg:yes; } - - Set-CurrentUser ($currentUser + 1); - continue; } Set-IsFinished $true; diff --git a/scripts/Windows/Scripts/Users.ps1 b/scripts/Windows/Scripts/Users.ps1 index 32b41924..6d9a38ca 100644 --- a/scripts/Windows/Scripts/Users.ps1 +++ b/scripts/Windows/Scripts/Users.ps1 @@ -1,15 +1,23 @@ using namespace System.Management.Automation.Host; +using namespace System.Security.Principal; $null = New-Module { . "$PSScriptRoot/../../Common/Scripts/Config.ps1"; - [string] $userOption = "SetupUser"; + . "$PSScriptRoot/../../Common/Scripts/Operations.ps1"; + . "$PSScriptRoot/../../Common/Types/OneShotTask.ps1"; + $loggedInUserOption = "LoggedInUser"; <# .SYNOPSIS - Creates the configured users. + Creates a new user for the PortValhalla setup. + + .PARAMETER Name + The name of the user to create. #> - function Start-ValhallaUserSetup { - [string[]] $users = Get-Users; + function New-ValhallaUser { + param( + [string] $Name + ) function Add-MicrosoftAccount { param( @@ -26,7 +34,7 @@ $null = New-Module { "Thus, you have to do it by yourself.", "So sorry…") -join "`n"); - Write-Host "Create a user for ``$Name`` manually (because Windows is too stupid)…"; + Write-Host "Create a user for ``$Name`` manually… (because Windows is too stupid)"; $null = Read-Host "Hit enter once you're done"; $newUsers = @(Get-LocalUser | Where-Object { -not ($currentUsers -contains $_.Name) }); @@ -57,7 +65,6 @@ $null = New-Module { for ($i = 0; $i -lt $newUsers.Count; $i++) { $name = "$($newUsers[$i])"; - [ChoiceDescription]::new("&$($i + 1) - ``$name``", "Your user is ``$name``"); } }), 0); @@ -74,33 +81,82 @@ $null = New-Module { } }; - Write-Host "Renaming the new user to ``$Name``…"; - Rename-LocalUser $newUser $Name; + Set-MSAccountName ([string]$newUser); } - for ($i = 0; $i -lt $users.Count; $i++) { - Set-SetupOption $userOption $i; - $name = $users[$i]; - Write-Host "Creating personal user ``$name``…"; - $displayName = Get-UserConfig -UserName $name "displayName"; + $msAccount = Get-UserConfig -UserName $Name "microsoftAccount"; - $userArguments = @{ - name = $name; - }; - - if ($displayName) { - $userArguments.fullName = $displayName; + if ($msAccount) { + if (Test-Admin) { + Write-Host "Preparing environment for creating MS Account"; + Enable-OneShotListener; + Enable-UAC; + Restart-Intermediate -CurrentUser; + exit; } + } - if (Get-UserConfig -UserName $name "microsoftAccount") { - Add-MicrosoftAccount $name; - } else { - New-LocalUser -Disabled -NoPassword @userArguments; - Set-LocalUser $name -PasswordNeverExpires $true; - Set-LocalUser $name -PasswordNeverExpires $false; - } + Write-Host "Creating personal user ``$Name``…"; - Set-LocalUser @userArguments; + if ($msAccount) { + Add-MicrosoftAccount $Name; + Set-SetupOption $loggedInUserOption $env:UserName; + Invoke-OneShot ([OneShotTask]::InitializeMSAccount); + } else { + New-LocalUser -NoPassword $Name; + Set-LocalUser $Name -PasswordNeverExpires $true; + Set-LocalUser $Name -PasswordNeverExpires $false; + Initialize-UserCreation; + } + } + + <# + .SYNOPSIS + Prepares the first login for initializing the current user under configuration. + #> + function Initialize-UserCreation { + $name = (@(Get-Users))[(Get-CurrentUser)]; + $msAccount = Get-UserConfig -UserName $name "microsoftAccount"; + $displayName = Get-UserConfig -UserName $Name "displayName"; + + Write-Host "Initializing user ``$name``…"; + + $userArguments = @{ + name = $name; + }; + + if ($displayName) { + $userArguments.fullName = $displayName; + } + + $adminGroup = @{ + SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null); + }; + + if ($msAccount) { + $accountName = Get-MSAccountName; + Write-Host "Renaming ``$accountName`` to ``$name``…" + Rename-LocalUser $accountName $name; + } + + Set-LocalUser @userArguments; + + if ($msAccount) { + Disable-LocalUser (Get-SetupOption $loggedInUserOption); + } else { + Disable-LocalUser $env:UserName; + } + + Add-LocalGroupMember ` + @adminGroup ` + $name ` + -ErrorAction SilentlyContinue; + + if ($msAccount) { + Disable-Autologin; + Set-BootMessage -Caption "Please Log In" -Message "Please log in using your new Microsoft Account ``$name``."; + } else { + Set-AutologinUser "$name"; } } };