functions/Get-SPSitePermission.ps1

function Get-SPSitePermission {
    <#
    .SYNOPSIS
        Resolve the effective permissions on the specified sites.
     
    .DESCRIPTION
        Resolve the effective permissions on the specified sites.
     
    .PARAMETER Url
        Url to the sharepoint site to scan.
     
    .PARAMETER Exclude
        What kinds of principals to ignore
        By default, System, Sharepoint Roles (SPRole) and Sharepoint Users (SPUser) are ignored.
 
    .PARAMETER LogLevel
        How detailed a log should be written.
     
    .EXAMPLE
        PS C:\> Get-PnPTenanteSite | Get-SPSitePermission
 
        Retrieve all permissions for all sites in the tenant.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]]
        $Url,

        [ValidateSet('None', 'System', 'SPRole', 'SPUser', 'AAD', 'AADRole', 'Unknown')]
        [string[]]
        $Exclude = @('System', 'SPRole', 'SPUser'),

        [LogLevel]
        $LogLevel = 'Medium'
    )

    begin {
        if ($Exclude -contains 'None') {
            $Exclude = 'None'
        }
    }

    process {
        foreach ($link in $Url) {
            if ($LogLevel -gt 0) { Write-PSFMessage 'Retrieving permissions from site {0}' -StringValues $link }
            try { $session = Select-Site -Url $link }
            catch {
                Write-PSFMessage -Level Warning -Message 'Failed to connect to site: {0}' -StringValues $link -ErrorRecord $_ -Target $link
            }

            try { $web = Get-PnPWeb -Includes RoleAssignments -Connection $session -ErrorAction Stop }
            catch {
                if ($_ -like "*(404)*") { continue }
                Write-PSFMessage -Level Warning -Message 'Failed to access site: {0}' -StringValues $link -ErrorRecord $_ -Target $link
                continue
            }
            foreach ($roleAssignment in $web.RoleAssignments) {
                $members = $roleAssignment.Member
                Invoke-PSFProtectedCommand -Action "Retrieving properties for a member of roleassignment to site: $link" -Target $roleAssignment -ScriptBlock {
                    $null = Get-PnPProperty -ClientObject $members -Property LoginName, ID, PrincipalType -Connection $session -ErrorAction Stop
                    $null = Get-PnPProperty -ClientObject $roleAssignment -Property RoleDefinitionBindings -Connection $session -ErrorAction Stop
                } -PSCmdlet $PSCmdlet -EnableException $false -Continue -RetryCount 3 -RetryWait 1

                foreach ($member in $members) {
                    if ($LogLevel -gt 1) { Write-PSFMessage -Message "Processing $($member.LoginName) | $($member.TypedObject.ToString())" -Target $member }
                    switch ($member.TypedObject.ToString()) {
                        'Microsoft.SharePoint.Client.User' {
                            if ($Exclude -contains 'SPUser') { break }

                            [PSCustomObject]@{
                                Site         = $link
                                SiteIdentity = $member.LoginName
                                Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                Title        = $null
                                LoginName    = $null
                                EMail        = $null
                                ID           = $null
                                Type         = 'SPUser'
                            }
                        }
                        'Microsoft.SharePoint.Client.Group' {
                            $count = 0
                            do {
                                try {
                                    $spGroupMembers = Get-PnPGroupMember -Group $member.Id -Connection $session -ErrorAction Stop
                                    break
                                }
                                catch {
                                    $lastError = $_
                                    $count++
                                }
                            }
                            while ($count -lt 5)
                            if ($count -ge 5 -and -not $spGroupMembers) {
                                Write-PSFMessage -Level Warning -Message "Failed to retrieve members of group $($group.Id)" -ErrorRecord $lastError
                            }
                            foreach ($spGroupMember in $spGroupMembers) {
                                #region Process individual memberships
                                #region System
                                if ($spGroupMember.LoginName -like "SHAREPOINT\*") {
                                    if ($Exclude -contains 'System') { continue }

                                    [PSCustomObject]@{
                                        Site         = $link
                                        SiteIdentity = $member.LoginName
                                        Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                        Title        = $spGroupMember.Title
                                        LoginName    = $spGroupMember.LoginName
                                        EMail        = $spGroupMember.Email
                                        ID           = $null
                                        Type         = 'System'
                                    }
                                    continue
                                }
                                #endregion System

                                #region SPRole
                                if ($spGroupMember.LoginName -like "*|rolemanager|*") {
                                    if ($Exclude -contains 'SPRole') { continue }
                                    [PSCustomObject]@{
                                        Site         = $link
                                        SiteIdentity = $member.LoginName
                                        Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                        Title        = $spGroupMember.Title
                                        LoginName    = $spGroupMember.LoginName
                                        EMail        = $spGroupMember.Email
                                        ID           = $spGroupMember.LoginName.Split('|')[-1]
                                        Type         = 'SPRole'
                                    }
                                    continue
                                }
                                #endregion SPRole

                                #region AAD
                                if ($spGroupMember.LoginName -like "*|federateddirectoryclaimprovider|*") {
                                    if ($Exclude -contains 'AAD') { continue }
                                    [PSCustomObject]@{
                                        Site         = $link
                                        SiteIdentity = $member.LoginName
                                        Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                        Title        = $spGroupMember.Title
                                        LoginName    = $spGroupMember.LoginName
                                        EMail        = $spGroupMember.Email
                                        ID           = $spGroupMember.LoginName.Split('|')[-1] -replace '_o$'
                                        Type         = 'AAD'
                                    }
                                    continue
                                }
                                #endregion AAD

                                #region AADRole
                                if ($spGroupMember.LoginName -like "*|tenant|*") {
                                    if ($Exclude -contains 'AADRole') { continue }
                                    [PSCustomObject]@{
                                        Site         = $link
                                        SiteIdentity = $member.LoginName
                                        Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                        Title        = $spGroupMember.Title
                                        LoginName    = $spGroupMember.LoginName
                                        EMail        = $spGroupMember.Email
                                        ID           = $spGroupMember.LoginName.Split('|')[-1]
                                        Type         = 'AADRole'
                                    }
                                    continue
                                }
                                #endregion AADRole

                                #region Unknown
                                if ($Exclude -contains 'Unknown') { continue }
                                [PSCustomObject]@{
                                    Site         = $link
                                    SiteIdentity = $member.LoginName
                                    Permission   = $roleAssignment.RoleDefinitionBindings.Name
                                    Title        = $spGroupMember.Title
                                    LoginName    = $spGroupMember.LoginName
                                    EMail        = $spGroupMember.Email
                                    ID           = $null
                                    Type         = 'Unknown'
                                }
                                #endregion Unknown
                                #endregion Process individual memberships
                            }
                        }
                    }
                }
            }
        }
    }
}