Public/Update-NLBaselineWorkspace.ps1

<#
.SYNOPSIS
    Updates NLBaseline workspace with latest baseline resources
.DESCRIPTION
    Updates workspace baseline files by overwriting with newer versions from the module
    This will overwrite existing files in the workspace with updated versions
.PARAMETER Force
    Force update all files, even if they appear to be up to date
.PARAMETER Backup
    Create backup of workspace before updating (default: true)
.EXAMPLE
    Update-NLBaselineWorkspace
    Update-NLBaselineWorkspace -Force -Backup $true
#>

function Update-NLBaselineWorkspace {
    [CmdletBinding()]
    param(
        [switch]$Force,
        [bool]$Backup = $true
    )

    $ErrorActionPreference = "Stop"
    $workspacePath = Get-WorkspacePath
    if (-not $workspacePath) {
        Write-Error "Workspace not configured. Run Initialize-NLBaseline first."
        return
    }

    if (-not (Test-Path -Path $workspacePath)) {
        Write-Error "Workspace path does not exist: $workspacePath"
        return
    }

    Write-Host "`nUpdating NLBaseline Workspace`n" -ForegroundColor Cyan
    Write-Host "Workspace: $workspacePath" -ForegroundColor White

    # Check for updates first
    $updateInfo = Check-NLBaselineUpdates
    if (-not $updateInfo) {
        Write-Error "Failed to check for updates"
        return
    }

    if (-not $updateInfo.UpdatesAvailable -and -not $Force) {
        Write-Host "`nNo updates available. Workspace is already up to date." -ForegroundColor Green
        return
    }

    # Create backup if requested
    if ($Backup) {
        Write-Host "`nCreating backup..." -ForegroundColor Yellow
        $backupPath = Join-Path -Path $workspacePath -ChildPath "Backup_$(Get-Date -Format 'yyyyMMdd_HHmmss')"
        try {
            # Backup Baseline and resource folders
            $foldersToBackup = @("Baseline", "ExploitProtections", "EventViewerCustomViews", "CountryIPsData", "Mitigations", "IntuneFiles", "WingetAutoUpdate")
            foreach ($folder in $foldersToBackup) {
                $sourceFolder = Join-Path -Path $workspacePath -ChildPath $folder
                if (Test-Path -Path $sourceFolder) {
                    $destFolder = Join-Path -Path $backupPath -ChildPath $folder
                    $destParent = Split-Path -Path $destFolder -Parent
                    if (-not (Test-Path -Path $destParent)) {
                        New-Item -ItemType Directory -Path $destParent -Force | Out-Null
                    }
                    Copy-Item -Path $sourceFolder -Destination $destFolder -Recurse -Force
                }
            }
            Write-Host "Backup created: $backupPath" -ForegroundColor Green
        }
        catch {
            Write-Warning "Failed to create backup: $_"
            $confirm = Read-Host "Continue without backup? [Y/N]"
            if ($confirm -ne 'Y' -and $confirm -ne 'y') {
                Write-Host "Update cancelled." -ForegroundColor Yellow
                return
            }
        }
    }

    # Confirm update
    if (-not $Force) {
        Write-Host "`nThe following will be updated:" -ForegroundColor Yellow
        if ($updateInfo.UpdatedFiles.Count -gt 0) {
            Write-Host " Files with updates: $($updateInfo.UpdatedFiles.Count)" -ForegroundColor White
        }
        if ($updateInfo.MissingFiles.Count -gt 0) {
            Write-Host " Missing files to add: $($updateInfo.MissingFiles.Count)" -ForegroundColor White
        }
        $confirm = Read-Host "`nProceed with update? [Y/N]"
        if ($confirm -ne 'Y' -and $confirm -ne 'y') {
            Write-Host "Update cancelled." -ForegroundColor Yellow
            return
        }
    }

    $modulePath = $PSScriptRoot -replace 'Public$', ''
    $updatedCount = 0

    # Update Baseline files
    Write-Host "`nUpdating Baseline files..." -ForegroundColor Yellow
    $resourcesPath = Join-Path -Path $modulePath -ChildPath "Resources\Baseline"
    $baselineDest = Join-Path -Path $workspacePath -ChildPath "Baseline"
    
    if (Test-Path -Path $resourcesPath) {
        if (-not (Test-Path -Path $baselineDest)) {
            New-Item -ItemType Directory -Path $baselineDest -Force | Out-Null
        }
        $baselineFiles = Get-ChildItem -Path $resourcesPath -Filter "*.json"
        foreach ($file in $baselineFiles) {
            $destPath = Join-Path -Path $baselineDest -ChildPath $file.Name
            if ($Force -or -not (Test-Path -Path $destPath) -or $file.LastWriteTime -gt (Get-Item $destPath).LastWriteTime) {
                if ($file.Name -eq 'WMISettings.json') {
                    try {
                        $wmiSettings = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json
                        $baselineWMI = Convert-WMISettingsToBaseline -WMISettings $wmiSettings
                        $baselineWMI | ConvertTo-Json -Depth 10 | Set-Content -Path $destPath -Force
                        Write-Host " Updated: $($file.Name)" -ForegroundColor Green
                        $updatedCount++
                    }
                    catch {
                        Write-Warning "Failed to update WMISettings.json: $_"
                    }
                }
                else {
                    Copy-Item -Path $file.FullName -Destination $destPath -Force
                    Write-Host " Updated: $($file.Name)" -ForegroundColor Green
                    $updatedCount++
                }
            }
        }
    }

    # Update other resource folders
    $resourceFolders = @(
        @{ Source = "Resources\ExploitProtections"; Dest = "ExploitProtections"; Pattern = "*" },
        @{ Source = "Resources\EventViewerCustomViews"; Dest = "EventViewerCustomViews"; Pattern = "*.xml" },
        @{ Source = "Resources\CountryIPsData"; Dest = "CountryIPsData"; Pattern = "*" },
        @{ Source = "Resources\Mitigations"; Dest = "Mitigations"; Pattern = "*" },
        @{ Source = "Resources\IntuneFiles"; Dest = "IntuneFiles"; Pattern = "*" },
        @{ Source = "Resources\WingetAutoUpdate"; Dest = "WingetAutoUpdate"; Pattern = "*" }
    )

    foreach ($folder in $resourceFolders) {
        $sourcePath = Join-Path -Path $modulePath -ChildPath $folder.Source
        $destPath = Join-Path -Path $workspacePath -ChildPath $folder.Dest
        
        if (Test-Path -Path $sourcePath) {
            Write-Host "`nUpdating $($folder.Dest)..." -ForegroundColor Yellow
            if (-not (Test-Path -Path $destPath)) {
                New-Item -ItemType Directory -Path $destPath -Force | Out-Null
            }
            
            $sourceFiles = Get-ChildItem -Path $sourcePath -Filter $folder.Pattern -Recurse
            foreach ($file in $sourceFiles) {
                $relativePath = $file.FullName.Replace($sourcePath, "").TrimStart('\')
                $destFilePath = Join-Path -Path $destPath -ChildPath $relativePath
                $destParent = Split-Path -Path $destFilePath -Parent
                
                if (-not (Test-Path -Path $destParent)) {
                    New-Item -ItemType Directory -Path $destParent -Force | Out-Null
                }
                
                if ($Force -or -not (Test-Path -Path $destFilePath) -or $file.LastWriteTime -gt (Get-Item $destFilePath).LastWriteTime) {
                    Copy-Item -Path $file.FullName -Destination $destFilePath -Force
                    Write-Host " Updated: $relativePath" -ForegroundColor Green
                    $updatedCount++
                }
            }
        }
    }

    # Update workspace version in config
    try {
        $configPath = Join-Path -Path $workspacePath -ChildPath "config.json"
        if (Test-Path -Path $configPath) {
            $config = Get-Content -Path $configPath -Raw | ConvertFrom-Json
            $config.Workspace.Version = $updateInfo.ModuleVersion
            $config.Workspace.LastUpdated = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
            $config | ConvertTo-Json -Depth 10 | Set-Content -Path $configPath -Force
        }
    }
    catch {
        Write-Warning "Could not update workspace version in config: $_"
    }

    Write-Host "`n" + ("=" * 60) -ForegroundColor Cyan
    Write-Host "Update completed!" -ForegroundColor Green
    Write-Host "Files updated: $updatedCount" -ForegroundColor White
    if ($Backup) {
        Write-Host "Backup location: $backupPath" -ForegroundColor Gray
    }
}