1

SCENARIO:

In my sharepoint online tenant I have a lot of subsites. One external user has access to some resources (list, document library ecc) given via a shared link. I need to delete this user from azure ad, and recreate it with a different email.


MY TWO GOALS:

GOAL1) Before deleting the user I would like to get all its shared links across all sites of the tenant given to it via sharepoint interface.

GOAL2) After deleting the user I want to share all these links again


What I try until now:

  1. A power shell script to get all shared links, something like this:
$sharedLinks = Get-PnPSiteUserInvitations -Site "https://mytenant.sharepoint.com/" -EmailAddress "[email protected]"
foreach ($link in $sharedLinks) {
         Write-Host "URL: $($link.Url)"
         Write-Host "Permission Type: $($link.SharingLinkType)"
         Write-Host "Expiration Date: $($link.ExpirationDate)"
         Write-Host "-----------------------------"
     }

Unfortunately, $sharedLinks is empty

  1. A power shell script to get all shared link in a list. Something like this: https://www.sharepointdiary.com/2020/11/find-all-shared-links-in-sharepoint-online-document-library.html

Kinda good but I get only the shared link of the element of a single list.


Do you have any idea how to achieve this? Any help would be appreciated.

2 Answers 2

1

Here are three methods for you to try get external sharing report.

1.Go to a SharePoint Online site -> Click on the Settings gear -> Site usage -> Sharing with external users -> Run report.

enter image description here

2.Go to Microsoft 365 admin center -> Compliance -> Aduit -> Classic search -> Set Date and time range (Audit supports searching data within six months) -> Choose Activities like following pictures show -> Choose the external user in the Users section.

enter image description here

enter image description here

enter image description here

3.Using PnP PowerShell.

https://www.sharepointdiary.com/2017/11/sharepoint-online-find-all-external-users-using-powershell.html

0

Thanks Emily,

you help me a lot. I delve into method 2 and 3.

2 Audit
In the classic search, I use audit and I filter with Action = "User added to secure link"

enter image description here

Then I download the csv, in the AuditData column there is an info TargetUserOrGroupName that contains the User principal name of the target of the shared link.


3 Powershell script

I write a powershell script. It is not a thunder but it works. I put it here

<#
This powershell script loop through all site and subsite in your tenant.
It saves all the shared links of a specific user with other metadata in a csv
#>

#input to change
$mailUserInput = "[email protected]"   #user that we want to search for sharedlink
$ReportOutput = "C:\tempoo\SharedLinkDestination.csv"

$username = "[email protected]"     #your sharepoint admin usermail
$password = ConvertTo-SecureString "adminsharepointpass" -AsPlainText -Force    #your sharepoint admin password

$siteUrl = ""
$AdminUrl = "https://mytenant.sharepoint.com/"      #your sharepoint root tenant



[switch]$deleteOldLinks = $false
$daysToDelete = 365
$daysToDisable = 180
[switch]$recursive = $true
$cred = New-Object Management.Automation.PSCredential ($username, $password)
# Initialize an empty array to store shared link objects
$Result = @()


# Connect to your SharePoint Online site using credentials
Connect-PnPOnline -Url $AdminUrl -Credentials $cred

# Get all site collections
$SiteColl = Get-PnPTenantSite




Function Get-PnPSharingLinks($web, $list, $item) {
     Get-PnPProperty -ClientObject $item -Property HasUniqueRoleAssignments |Out-Null

    if ($item.HasUniqueRoleAssignments) {  
        # Find all the documents which have unique permissions  
        #  write-host    $item.FieldValues["FileRef"] 
        $sharingSettings = Invoke-PnPSPRestMethod -Method Post -Url "$($web.Url)/_api/web/Lists(@a1)/GetItemById(@a2)/GetSharingInformation?@a1='{$($list.Id)}'&@a2='$($item.Id)'&`$Expand=permissionsInformation,pickerSettings"  -ContentType "application/json;odata=verbose" -Content "{}"
        ForEach ($shareLink in $sharingSettings.permissionsInformation.links) {
            $linkDetails = $shareLink.linkDetails
            if ($linkDetails.Url) {
 
                $linkAccess = "ViewOnly"
                if ($linkDetails.IsEditLink) {
                    $linkAccess = "Edit"
                }
                elseif ($linkDetails.IsReviewLink) {
                    $linkAccess = "Review"
                }
                $dateMinToDelete = $(Get-Date).AddDays(-90);
                $deleted = $false;
                $LastModified = Get-Date -Date $linkDetails.LastModified 
                if (
                    $LastModified -lt $dateMinToDelete -and `
                        $linkDetails.HasExternalGuestInvitees -and `
                        $deleteOldLinks) {
                    Invoke-PnPSPRestMethod -Method Post -Url "$($web.Url)/_api/web/Lists(@a1)/GetItemById(@a2)/UnshareLink?@a1='{$($list.Id)}'&@a2='$($item.Id)'"  -ContentType "application/json;odata=verbose" -Content "{'linkKind':$($linkDetails.LinkKind),'shareId':'$($linkDetails.ShareId)'}"
                    $deleted = $true;
                    
                }
                
                $invitees = (
                    $linkDetails.Invitations | 
                    ForEach-Object { $_.Invitee.email   }
                ) -join '|'


                $sharedLinkObject = New-Object PSObject -property $([ordered]@{ 
                    FileID   = $item.FieldValues["UniqueId"]
                    ShareLink = $linkDetails.Url
                    Invitees  = $invitees
                    Name = $item.FieldValues["FileLeafRef"]        
                    FileType = $item.FieldValues["File_x0020_Type"]
                    RelativeURL = $item.FieldValues["FileRef"]
                    LinkAccess = $linkAccess
                    # Add other properties as needed
                })

                # Initialize $Result as an array if it's not already an array
                if (-not $Result) {
                    $Result = @()
                }

                
                if ($invitees -like "*$($mailUserInput)*") {
                    # Initialize $Result as an array if it's not already an array
                    if (-not $Result) {
                        $Result = @()
                    }

                    # Add the shared link object to the array
                    $Result += $sharedLinkObject

                    write-host $linkAccess
                    write-host $linkDetails.Url
                    write-host $item.FieldValues["FileLeafRef"]
                    write-host $invitees
                    write-host

                    $Result | Export-CSV $ReportOutput -NoTypeInformation -Encoding UTF8  -Append 
                }
            }
        }
         write-host   "---------------------------------------------------"  
    } 
}

 
#Function to Get Permissions of Folders in a given List
Function Get-PnPItemsPermission($web, $List) {
    Write-host -f Yellow "`t `t Getting Permissions of items in the List:"$List.Title
        
    #Get All Folders from List
    $items = Get-PnPListItem -List $List -PageSize 2000  
 
    $ItemCounter = 0
    #Loop through each Folder
    ForEach ($item in $items) {
            
        $ItemCounter++
        Write-Progress -PercentComplete ($ItemCounter / ($items.Count) * 100) -Activity "Getting Permissions of items in List '$($List.Title)'" -Status "Processing items '$($item.FieldValues.FileLeafRef)'  ($ItemCounter of $($items.Count))" -Id 2 -ParentId 1
   
        #Call the function to generate Permission report
        Get-PnPSharingLinks $web $list $item
    }
}


#Function to Get Permissions of all lists from the given web
Function Get-PnPListSharingLinks($Web) {
    #Get All Lists from the web
    Connect-PnPOnline -Url $web.Url -Credentials $cred
    $Lists = Get-PnPList 

    #Exclude system lists
    $ExcludedLists = @("Bibliothèque de styles", "Access Requests", "App Packages", "appdata", "appfiles", "Apps in Testing", "Cache Profiles", "Composed Looks", "Content and Structure Reports", "Content type publishing error log", "Converted Forms",
        "Device Channels", "Form Templates", "fpdatasources", "Get started with Apps for Office and SharePoint", "List Template Gallery", "Long Running Operation Status", "Maintenance Log Library", "Images", "site collection images"
        , "Master Docs", "Master Page Gallery", "MicroFeed", "NintexFormXml", "Quick Deploy Items", "Relationships List", "Reusable Content", "Reporting Metadata", "Reporting Templates", "Search Config List", "Site Assets", "Preservation Hold Library",
        "Site Pages", "Solution Gallery", "Style Library", "Suggested Content Browser Locations", "Theme Gallery", "TaxonomyHiddenList", "User Information List", "Web Part Gallery", "wfpub", "wfsvc", "Workflow History", "Workflow Tasks", "Pages")
      
    $Counter = 0
    
    #Get all lists from the web  
    ForEach ($List in $Lists) {
        #Exclude System Lists
        If ($List.Hidden -eq $False -and $ExcludedLists -notcontains $List.Title -and $List.BaseType -eq "DocumentLibrary") {
            $Counter++
            Write-Progress -PercentComplete ($Counter / ($Lists.Count) * 100) -Activity "Exporting Permissions from List '$($List.Title)' in $($Web.URL)" -Status "Processing Lists $Counter of $($Lists.Count)" -Id 1
            #Get Folder Permissions
            Get-PnPItemsPermission -web $Web -List $List
        }
    }
}


#Function to Get Webs's Permissions from given URL
Function Get-PnPWebSharingLinks($Web) {
    #Iterate through each subsite in the current web
    Foreach ($Subweb in $Subwebs) {        
        Get-PnPListSharingLinks($Subweb)
    }
}
  




$Result = @()

# Iterate through all site collections
ForEach ($Site in $SiteColl) {
    Write-Host "FATHER SITE:" $Site.Url  #print the siteurl currently analyzing
    $siteUrl = $Site.Url  

    Connect-PnpOnline -url $siteUrl  -Credentials $cred    
    $Web = get-pnpweb

    #Call the function with RootWeb to get site collection permissions
    If ($Recursive) {
        #Get Subwebs of the Web
        $Subwebs = Get-PnPSubWeb -Recurse -IncludeRootWeb
    }
    
    Write-Host "CHILD SITE:"   $Subwebs.Url
    Get-PnPWebSharingLinks $Subwebs  #TODO DECOMMENT
}


# Disconnect from SharePoint
Disconnect-PnPOnline

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.