241 lines
8.4 KiB
PowerShell
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<#
=============================================================================================
Name: Get SharePoint Files & Folders Created By External Users Using PowerShell
Version: 1.0
Website: o365reports.com
~~~~~~~~~~~~~~~~~~
Script Highlights:
~~~~~~~~~~~~~~~~~~
1. The script automatically verifies and installs the PnP module (if not installed already) upon your confirmation. 
2. Retrieves all files and folders created by external users for all sites. 
3. Gets files and folders created by external users on a specific site. 
4. Finds files and folders created by a specific external user. 
5. Allows to filter the data to display either files or folders created by external users. 
6. The script can be executed with an MFA-enabled account too. 
7. The script supports Certificate-based authentication (CBA) too. 
8. Exports the report results to a CSV file.
For detailed script execution: https://o365reports.com/2024/06/11/get-sharepoint-files-folders-created-by-external-users-using-powershell/
=============================================================================================
#>
param
(
[Parameter(Mandatory = $false)]
[Switch] $FoldersOnly,
[Switch] $FilesOnly,
[string] $CreatedBy ,
[String] $UserName,
[String] $Password,
[String] $ClientId,
[String] $CertificateThumbprint,
[String] $TenantName, #(Example : If your tenant name is 'contoso.com', then enter 'contoso' as a tenant name )
[String] $SiteAddress, #(Enter the specific site URL that you want to retrieve the data from.)
[String] $SitesCsv
)
#Check for SharePoint PnPPowerShellOnline module availability
$PnPOnline = (Get-Module PnP.PowerShell -ListAvailable).Name
if($PnPOnline -eq $null)
{
Write-Host "Important: SharePoint PnP PowerShell module is unavailable. It is mandatory to have this module installed in the system to run the script successfully."
$Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No
if($Confirm -match "[yY]")
{
Write-Host "Installing SharePoint PnP PowerShell module..." -ForegroundColor Magenta
Install-Module PnP.Powershell -Repository PsGallery -Force -AllowClobber -Scope CurrentUser
Import-Module PnP.Powershell -Force
#Register a new Azure AD Application and Grant Access to the tenant
Register-PnPManagementShellAccess
}
else
{
Write-Host "Exiting. `nNote: SharePoint PnP PowerShell module must be available in your system to run the script"
Exit
}
}
#Connecting to SharePoint PnPPowerShellOnline module.......
Write-Host "Connecting to SharePoint PnPPowerShellOnline module..." -ForegroundColor Cyan
function Connect_Sharepoint
{
param
(
[Parameter(Mandatory = $true)]
[String] $Url
)
try
{
if(($UserName -ne "") -and ($Password -ne "") -and ($TenantName -ne ""))
{
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword
Connect-PnPOnline -Url $Url -Credential $Credential
}
elseif($TenantName -ne "" -and $ClientId -ne "" -and $CertificateThumbprint -ne "")
{
Connect-PnPOnline -Url $Url -ClientId $ClientId -Thumbprint $CertificateThumbprint -Tenant "$TenantName.onmicrosoft.com"
}
else
{
Connect-PnPOnline -Url $Url -Interactive
}
}
catch
{
Write-Host "Error occured $($Url) : $_.Exception.Message" -Foreground Red;
}
}
if($TenantName -eq "")
{
$TenantName = Read-Host "Enter your Tenant Name to Connect SharePoint Online (Example : If your tenant name is 'contoso.com', then enter 'contoso' as a tenant name ) "
}
$AdminUrl = "https://$TenantName.sharepoint.com/"
connect_sharepoint -Url $AdminUrl
$OutputCSV = "./SPO - Files & Folders Created By External Users " + ((Get-Date -format "MMM-dd hh-mm-ss tt").ToString()) + ".csv"
#Collecting the data and exporting it to a CSV file
$global:Count = 0
function Export_Data
{
param
(
[Object] $ListItem,
[Object] $ExternalUserIds,
[String] $SiteUrl,
[String] $SiteTitle
)
$AuthorFieldValue = $ListItem.FieldValues["Author"]
$AuthorId = $AuthorFieldValue.LookupId
$AuthorName = $AuthorFieldValue.LookupValue
#Checking the resource created by an external user
if(($ExternalUserIds | where{($_.Id -eq $AuthorId )}).count -eq 1)
{
$global:Count++
$ExportResult =@{
'File/Folder Name' = $ListItem.FieldValues.FileLeafRef;
'Relative URL' = $AdminUrl + $ListItem.FieldValues.FileRef;
'Created On' = if ($ListItem.FieldValues.Created) {$ListItem.FieldValues.Created} else { "-" } ;
'Created By' = $AuthorName;
'Resource Type' = $ListItem.FileSystemObjectType;
'Site Name' = if ($SiteTitle) {$SiteTitle} else { "-" };
'Site Url' = $SiteUrl
}
$ExportResult = New-Object PSObject -Property $ExportResult
#Export result to csv
$ExportResult | Select-Object 'Site Name','Site Url','File/Folder Name','Created By','Resource Type','Created On','Relative URL' | Export-Csv -path $OutputCSV -Append -NoTypeInformation
}
}
#Collecting items created by external users
function Get_ExternalUserItems
{
param
(
[String] $ObjectType,
[String] $SiteUrl
)
try
{
$Web = Get-PnPWeb | Select Title
if($CreatedBy -eq "")
{
#Geting external Users present in site
$ExternalUserIds = Get-PnPUser | where{($_.IsShareByEmailGuestUser -eq "True" -or $_.IsHiddenInUI -eq "True" ) } | Select Id
}
else
{
$ExternalUserIds = Get-PnPUser | where{($_.IsShareByEmailGuestUser -eq "True" -or $_.IsHiddenInUI -eq "True" ) -and ($_.Email -eq $CreatedBy -or ($_.LoginName -split {$_ -eq "|"})[2] -eq $CreatedBy) } | Select Id
}
if(($ExternalUserIds).count -gt 0)
{
Get-PnPList | Where-Object {$_.Hidden -eq $false -and $_.BaseType -eq "DocumentLibrary"} | ForEach-Object{
if($ObjectType -eq "All"){
# Retrieves list items
Get-PnPListItem -List $_.Title -PageSize 2000 | ForEach-Object{
Export_Data -ListItem $_ -ExternalUserIds $ExternalUserIds -SiteUrl $SiteUrl -SiteTitle $Web.Title
}
}
else
{
# Retrieves list items for a specific object type.
Get-PnPListItem -List $_.Title -PageSize 2000 | where { $_.FileSystemObjectType -eq $ObjectType} |ForEach-Object{
Export_Data -ListItem $_ -ExternalUserIds $ExternalUserIds -SiteUrl $SiteUrl -SiteTitle $Web.Title
}
}
}
}
}
catch
{
Write-Host "Error occured $($SiteUrl) : $_" -Foreground Red;
}
}
if($FoldersOnly.IsPresent)
{
$ObjectType = "Folder"
}
elseif($FilesOnly.IsPresent)
{
$ObjectType = "File"
}
else
{
$ObjectType = "All"
}
#To Retrive Data From All Sites Present In The Tenant
if($SiteAddress -ne "")
{
Connect_Sharepoint -Url $SiteAddress
Get_ExternalUserItems -Objecttype $ObjectType -SiteUrl $SiteAddress
}
elseif($SitesCsv -ne "")
{
try
{
Import-Csv -path $SitesCsv | ForEach-Object{
Write-Progress -activity "Processing $($_.SitesUrl)"
Connect_Sharepoint -Url $_.SitesUrl
Get_ExternalUserItems -Objecttype $ObjectType -SiteUrl $_.SitesUrl
}
}
catch
{
Write-Host "Error occured : $_" -Foreground Red;
}
}
#To retrive the data for site presesent in our admin center
else
{
Get-PnPTenantSite | Select Url,Title | ForEach-Object{
Write-Progress -activity "Processing $($_.Url)"
Connect_Sharepoint -Url $_.Url
Get_ExternalUserItems -Objecttype $ObjectType -SiteUrl $_.Url
}
}
#Open output file after execution
if($Count -gt 0)
{
if((Test-Path -Path $OutputCSV) -eq "True")
{
$Prompt = New-Object -ComObject wscript.shell
$UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File", 4)
If ($UserInput -eq 6)
{
Invoke-Item $OutputCSV
}
}
}
else
{
Write-Host "No records found"
}
#Disconnect the sharePoint PnPOnline module
Disconnect-PnPOnline