Public/Check-NLBaselineUpdates.ps1

<#
.SYNOPSIS
    Checks for available updates to NLBaseline baseline resources
.DESCRIPTION
    Compares module resources with workspace files to detect if updates are available
    Checks file modification dates and versions to determine if workspace needs updating
.OUTPUTS
    PSCustomObject with update information
.EXAMPLE
    Check-NLBaselineUpdates
#>

function Check-NLBaselineUpdates {
    [CmdletBinding()]
    param()

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

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

    Write-Host "`nChecking for NLBaseline updates...`n" -ForegroundColor Cyan
    Write-Host "Workspace: $workspacePath" -ForegroundColor White

    $modulePath = $PSScriptRoot -replace 'Public$', ''
    $updateInfo = @{
        UpdatesAvailable = $false
        UpdatedFiles = @()
        MissingFiles = @()
        ModuleVersion = "1.0.0"
        WorkspaceVersion = "1.0.0"
    }

    # Get module version
    try {
        $moduleManifest = Join-Path -Path $modulePath -ChildPath "NLBaseline.psd1"
        if (Test-Path -Path $moduleManifest) {
            $manifestContent = Get-Content -Path $moduleManifest -Raw
            if ($manifestContent -match "ModuleVersion\s*=\s*['`"]([^'`"]+)['`"]") {
                $updateInfo.ModuleVersion = $matches[1]
            }
        }
    }
    catch {
        Write-Verbose "Could not read module version: $_"
    }

    # Get workspace version from config
    try {
        $configPath = Join-Path -Path $workspacePath -ChildPath "config.json"
        if (Test-Path -Path $configPath) {
            $config = Get-Content -Path $configPath -Raw | ConvertFrom-Json
            if ($config.Workspace.Version) {
                $updateInfo.WorkspaceVersion = $config.Workspace.Version
            }
        }
    }
    catch {
        Write-Verbose "Could not read workspace version: $_"
    }

    # Check Baseline files
    Write-Host "`nChecking Baseline files..." -ForegroundColor Yellow
    $resourcesPath = Join-Path -Path $modulePath -ChildPath "Resources\Baseline"
    $baselineDest = Join-Path -Path $workspacePath -ChildPath "Baseline"
    
    if (Test-Path -Path $resourcesPath) {
        $baselineFiles = Get-ChildItem -Path $resourcesPath -Filter "*.json"
        foreach ($file in $baselineFiles) {
            $destPath = Join-Path -Path $baselineDest -ChildPath $file.Name
            if (-not (Test-Path -Path $destPath)) {
                $updateInfo.MissingFiles += "Baseline\$($file.Name)"
                $updateInfo.UpdatesAvailable = $true
                Write-Host " Missing: $($file.Name)" -ForegroundColor Red
            }
            elseif ($file.LastWriteTime -gt (Get-Item $destPath).LastWriteTime) {
                $updateInfo.UpdatedFiles += "Baseline\$($file.Name)"
                $updateInfo.UpdatesAvailable = $true
                Write-Host " Update available: $($file.Name)" -ForegroundColor Yellow
            }
        }
    }

    # Check 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 "`nChecking $($folder.Dest)..." -ForegroundColor Yellow
            $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
                
                if (-not (Test-Path -Path $destFilePath)) {
                    $updateInfo.MissingFiles += "$($folder.Dest)\$relativePath"
                    $updateInfo.UpdatesAvailable = $true
                    Write-Host " Missing: $relativePath" -ForegroundColor Red
                }
                elseif ($file.LastWriteTime -gt (Get-Item $destFilePath).LastWriteTime) {
                    $updateInfo.UpdatedFiles += "$($folder.Dest)\$relativePath"
                    $updateInfo.UpdatesAvailable = $true
                    Write-Host " Update available: $relativePath" -ForegroundColor Yellow
                }
            }
        }
    }

    # Summary
    Write-Host "`n" + ("=" * 60) -ForegroundColor Cyan
    Write-Host "Update Check Summary" -ForegroundColor Cyan
    Write-Host ("=" * 60) -ForegroundColor Cyan
    Write-Host "Module Version: $($updateInfo.ModuleVersion)" -ForegroundColor White
    Write-Host "Workspace Version: $($updateInfo.WorkspaceVersion)" -ForegroundColor White
    Write-Host "Updates Available: $(if ($updateInfo.UpdatesAvailable) { 'Yes' } else { 'No' })" -ForegroundColor $(if ($updateInfo.UpdatesAvailable) { 'Yellow' } else { 'Green' })
    
    if ($updateInfo.UpdatedFiles.Count -gt 0) {
        Write-Host "`nFiles with updates: $($updateInfo.UpdatedFiles.Count)" -ForegroundColor Yellow
        foreach ($file in $updateInfo.UpdatedFiles) {
            Write-Host " - $file" -ForegroundColor Gray
        }
    }
    
    if ($updateInfo.MissingFiles.Count -gt 0) {
        Write-Host "`nMissing files: $($updateInfo.MissingFiles.Count)" -ForegroundColor Red
        foreach ($file in $updateInfo.MissingFiles) {
            Write-Host " - $file" -ForegroundColor Gray
        }
    }

    if (-not $updateInfo.UpdatesAvailable) {
        Write-Host "`nWorkspace is up to date!" -ForegroundColor Green
    }

    return $updateInfo
}