Public/Permissions/Invoke-365TuneRevoke.ps1

function Invoke-365TuneRevoke {
    <#
    .SYNOPSIS
        Revokes all 365TUNE permissions — Azure and Exchange Online in one step.

    .DESCRIPTION
        Logs in once then runs Invoke-365TuneRevokeExchange and
        Invoke-365TuneRevokeAzure in sequence with a single login prompt.

        Exchange is revoked first (best practice — remove app-level access
        before RBAC). Azure revoke proceeds even if Exchange revoke fails.

        Run from local PowerShell only (not Cloud Shell).
        Your account must have Global Administrator and Exchange Administrator rights.

    .EXAMPLE
        Invoke-365TuneRevoke

    .NOTES
        Author : Metawise Consulting LLC
        Module : 365TUNE
        Version : 1.9.0
    #>


    [CmdletBinding()]
    param()

    Write-Host "`n══════════════════════════════════════════════════════" -ForegroundColor Cyan
    Write-Host " 365TUNE — Full Permissions Revoke" -ForegroundColor Cyan
    Write-Host " Revoking Azure + Exchange Online in one step" -ForegroundColor Cyan
    Write-Host "══════════════════════════════════════════════════════`n" -ForegroundColor Cyan

    # Login once upfront
    Write-Host "Authenticating..." -ForegroundColor Cyan
    Disconnect-AzAccount -ErrorAction SilentlyContinue | Out-Null
    Connect-AzAccount -WarningAction SilentlyContinue | Out-Null
    $context = Get-AzContext
    if (-not $context) { throw "Authentication failed. Please try again." }
    Write-Host " Tenant : $($context.Tenant.Id)" -ForegroundColor Gray
    Write-Host " Account : $($context.Account.Id)" -ForegroundColor Gray
    Write-Host " ✅ Authenticated.`n" -ForegroundColor Green

    # Step 1 — Exchange first
    Write-Host "[ STEP 1 OF 2 ] Exchange Online Permissions" -ForegroundColor Magenta
    Write-Host "──────────────────────────────────────────────────────" -ForegroundColor Magenta
    try {
        Invoke-365TuneRevokeExchange -SkipAuth
    } catch {
        Write-Host "`n❌ Exchange revoke failed: $($_.Exception.Message)" -ForegroundColor Red
        Write-Host " Azure revoke will still proceed." -ForegroundColor Yellow
        Write-Host " Fix Exchange errors and re-run Invoke-365TuneRevokeExchange if needed." -ForegroundColor Yellow
    }

    # Step 2 — Azure
    Write-Host "[ STEP 2 OF 2 ] Azure Permissions" -ForegroundColor Magenta
    Write-Host "──────────────────────────────────────────────────────" -ForegroundColor Magenta
    try {
        Invoke-365TuneRevokeAzure -SkipAuth
    } catch {
        Write-Host "`n❌ Azure revoke failed: $($_.Exception.Message)" -ForegroundColor Red
        Write-Host " Fix Azure errors and re-run Invoke-365TuneRevokeAzure." -ForegroundColor Yellow
        return
    }

    Write-Host "`n══════════════════════════════════════════════════════" -ForegroundColor Cyan
    Write-Host " 365TUNE permissions fully revoked. ✅" -ForegroundColor Green
    Write-Host " ✅ Exchange: View-Only Configuration role removed" -ForegroundColor Green
    Write-Host " ✅ Azure : Reader removed from / and /providers/Microsoft.aadiam" -ForegroundColor Green
    Write-Host "══════════════════════════════════════════════════════`n" -ForegroundColor Cyan
}