Blog about anything related to my learnings
  • About
  • posts
bluesky
Blog about anything related to my learnings
POSTS

# ===== Settings =====
$clientId  = "c9b5eaab-40cf-4e97-98ba-822241c2088c"
$dateTime  = Get-Date -Format "yyyy-MM-dd-HH-mm-ss"
$CertPath  = Read-Host "Please enter Certificate (.PFX) Path"
$CertPassword = Read-Host "Please enter Certificate Password" -AsSecureString
$Org = "bankofenglandcouk.onmicrosoft.com"

$invocation    = Get-Variable -Name MyInvocation -ValueOnly
$directoryPath = Split-Path $invocation.MyCommand.Path

# Log file path
$logFile = Join-Path $directoryPath "Log-$dateTime.csv"

# Create log header
"Timestamp,Message,Status" | Out-File -FilePath $logFile -Encoding utf8

# ===== Logging Function =====
function Log-Message {
    param (
        [string]$Message,
        [string]$Status = "Info"
    )

    switch ($Status) {
        "Success" { $color = "Green" }
        "Info"    { $color = "Blue" }
        "Error"   { $color = "Red" }
        default   { $color = "White" }
    }

    Write-Host -ForegroundColor $color "$Status => $Message"

    $logEntry = [PSCustomObject]@{
        Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
        Message   = $Message
        Status    = $Status
    }

    $logEntry | Export-Csv -Path $logFile -Append -NoTypeInformation
}
function Get-LibraryNameFromFileUrl {
    param([string]$fileUrl, [string]$siteUrl)

    # Remove base site URL
    $relative = $fileUrl.Replace($siteUrl, "")

    # Trim leading "/"
    if ($relative.StartsWith("/")) {
        $relative = $relative.Substring(1)
    }

    # First path segment = library name
    $libraryName = $relative.Split("/")[0]

    return $libraryName
}
# ===== Import CSV =====
$csvPath = Read-Host "Enter path to CSV file"
$rows = Import-Csv -Path $csvPath

Log-Message "Loaded CSV: $csvPath" "Info"

# Stores connections by site URL
$connectionCache = @{}

foreach ($row in $rows) {

    $fileUrl = $row.fileUrl
    $newEditor = $row.Editor
    $newAuthor = $row.Author

    if (-not $fileUrl) {
        Log-Message "Missing fileUrl in CSV row." "Error"
        continue
    }

    # -------- Extract site URL --------
    try {
        # Example:
        # https://tenant.sharepoint.com/sites/SiteA/Shared Documents/File.docx
        $uri = [Uri]$fileUrl

        # Keep: https://tenant.sharepoint.com
        $base = "$($uri.Scheme)://$($uri.Host)"

        # Extract the first two segments: /sites/SiteA or /teams/TeamA
        $segments = $uri.AbsolutePath.Split("/") | Where-Object { $_ -ne "" }

        if ($segments[0] -eq "sites" -or $segments[0] -eq "teams") {
            $siteUrl = "$base/$($segments[0])/$($segments[1])"
        } else {
            Log-Message "Unable to determine siteUrl from $fileUrl" "Error"
            continue
        }

        Log-Message "Derived siteUrl: $siteUrl" "Info"
    }
    catch {
        Log-Message "Failed to parse URL: $fileUrl" "Error"
        continue
    }

    # -------- Connect to the site (cached) --------
    if (-not $connectionCache.ContainsKey($siteUrl)) {
        try {
            Connect-PnPOnline -ClientId $clientId `
                -Url $siteUrl `
                -CertificatePath $CertPath `
                -CertificatePassword $CertPassword `
                -Tenant $Org

            $connectionCache[$siteUrl] = $true
            Log-Message "Connected to $siteUrl" "Success"
        }
        catch {
            Log-Message "Connection failed for $siteUrl : $_" "Error"
            continue
        }
    }

    # -------- Retrieve list item --------
    try {
        $item = Get-PnPFile -Url $fileUrl -AsListItem -ErrorAction Stop
        Log-Message "Retrieved file: $fileUrl" "Success"
    }
    catch {
        Log-Message "Failed to retrieve $fileUrl : $_" "Error"
        continue
    }
    $list = Get-LibraryNameFromFileUrl -fileUrl $fileUrl -siteUrl $siteUrl
    # -------- Update metadata --------
    try {
        Set-PnPListItem -List $list `
                        -Identity $item.Id `
                        -Values @{
                            "Author" = $newAuthor
                            "Editor" = $newEditor
                            "Modified" = $item.FieldValues["Modified"]
                        } `
                        -UpdateType UpdateOverwriteVersion

        Log-Message "Updated Author/Editor for: $fileUrl" "Success"
    }
    catch {
        Log-Message "Failed to update $fileUrl : $_" "Error"
    }
}

Log-Message "Processing complete." "Success"
    © Blog about anything related to my learnings 2026
    bluesky