Cleanup birthday events for old contacts (#3019)
Purge events birthdays corresponding to old contacts --- #### Does this PR need a docs update or release note? - [ ] ✅ Yes, it's included - [ ] 🕐 Yes, but in a later PR - [x] ⛔ No #### Type of change <!--- Please check the type of change your PR introduces: ---> - [ ] 🌻 Feature - [x] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Supportability/Tests - [x] 💻 CI/Deployment - [ ] 🧹 Tech Debt/Cleanup #### Issue(s) <!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. --> * #<issue> #### Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual - [ ] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
c696e7b7ff
commit
ce755ecf3c
@ -129,7 +129,7 @@ function Get-TimestampFromName {
|
||||
|
||||
try {
|
||||
# Assumes that the timestamp is at the end and starts with yyyy-mm-ddT and is ISO8601
|
||||
if ($name -imatch "(\d{4}}-\d{2}-\d{2}T.*)") {
|
||||
if ($name -imatch "(\d{4}-\d{2}-\d{2}T[\S]*)") {
|
||||
$timestamp = [System.Convert]::ToDatetime($Matches.0)
|
||||
}
|
||||
|
||||
@ -226,11 +226,20 @@ function Get-FoldersToPurge {
|
||||
| Select-Object -ExpandProperty Value
|
||||
| Get-Date
|
||||
|
||||
if ($FolderNamePurgeList.count -gt 0) {
|
||||
$IsNameMatchParams = @{
|
||||
'FolderName' = $folderName;
|
||||
'FolderNamePurgeList' = $FolderNamePurgeList
|
||||
}
|
||||
|
||||
if ((IsNameMatch @IsNameMatchParams)) {
|
||||
Write-Host "• Found name match: $folderName ($folderCreateTime)"
|
||||
$foldersToDelete += $folder
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if ($FolderPrefixPurgeList.count -gt 0) {
|
||||
$IsPrefixAndAgeMatchParams = @{
|
||||
'FolderName' = $folderName;
|
||||
'FolderCreateTime' = $folderCreateTime;
|
||||
@ -238,11 +247,12 @@ function Get-FoldersToPurge {
|
||||
'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp;
|
||||
}
|
||||
|
||||
if ((IsNameMatch @IsNameMatchParams) -or (IsPrefixAndAgeMatch @IsPrefixAndAgeMatchParams)) {
|
||||
Write-Host "• Found: $folderName ($folderCreateTime)"
|
||||
if ((IsPrefixAndAgeMatch @IsPrefixAndAgeMatchParams)) {
|
||||
Write-Host "• Found prefix match: $folderName ($folderCreateTime)"
|
||||
$foldersToDelete += $folder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# powershel does not do well when returning empty arrays
|
||||
return $foldersToDelete, $moreToList
|
||||
@ -399,6 +409,8 @@ function Purge-Folders {
|
||||
}
|
||||
|
||||
function Create-Contact {
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
|
||||
$now = (Get-Date (Get-Date).ToUniversalTime() -Format "o")
|
||||
#used to create a recent seed contact that will be shielded from cleanup. CI tests rely on this
|
||||
$body = @"
|
||||
@ -419,26 +431,50 @@ function Create-Contact {
|
||||
</t:PhoneNumbers>
|
||||
<t:Birthday>2000-01-01T11:59:00Z</t:Birthday>
|
||||
<t:JobTitle>Tester</t:JobTitle>
|
||||
<t:Surname>Plate</t:Surname>
|
||||
</t:Contact>
|
||||
</Items>
|
||||
</CreateItem>
|
||||
"@
|
||||
|
||||
if ($PSCmdlet.ShouldProcess("Creating seed contact...", "", "Create contact")) {
|
||||
Write-Host "`nCreating seed contact..."
|
||||
$createContactMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||
$response = Invoke-SOAPRequest -Token $Token -Message $createContactMsg
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ItemsToPurge {
|
||||
Param(
|
||||
[Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
|
||||
[String]$WellKnownRoot,
|
||||
|
||||
[Parameter(Mandatory = $False, HelpMessage = "Immediate subfolder within well known folder")]
|
||||
[String]$SubFolderName = $null,
|
||||
|
||||
[Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
|
||||
[datetime]$PurgeBeforeTimestamp
|
||||
)
|
||||
|
||||
$itemsToDelete = @()
|
||||
$foldersToSearchBody = "<t:DistinguishedFolderId Id='$WellKnownRoot'/>"
|
||||
|
||||
if (![String]::IsNullOrEmpty($SubFolderName)) {
|
||||
$subFolders, $moreToList = Get-FoldersToPurge -WellKnownRoot $WellKnownRoot -FolderNamePurgeList $SubFolderName -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
|
||||
if ($subFolders.count -gt 0 ) {
|
||||
$foldersToSearchBody = ""
|
||||
foreach ($sub in $subFolders) {
|
||||
$subName = $sub.DisplayName
|
||||
$subId = $sub.FolderId.Id
|
||||
Write-Host "Found subfolder from which to purge items: $subName"
|
||||
$foldersToSearchBody = "<t:FolderId Id='$subId'/>`n"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host "Requested subfolder $SubFolderName in folder $WellKnownRoot was not found"
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
# SOAP message for getting the folder id
|
||||
$body = @"
|
||||
@ -450,12 +486,12 @@ function Get-ItemsToPurge {
|
||||
</t:AdditionalProperties>
|
||||
</ItemShape>
|
||||
<ParentFolderIds>
|
||||
<t:DistinguishedFolderId Id="$WellKnownRoot"/>
|
||||
$FoldersToSearchBody
|
||||
</ParentFolderIds>
|
||||
</FindItem>
|
||||
"@
|
||||
|
||||
Write-Host "`nLooking for items under well-known folder: $WellKnownRoot older than $PurgeBeforeTimestamp for user: $User"
|
||||
Write-Host "`nLooking for items under well-known folder: $WellKnownRoot($SubFolderName) older than $PurgeBeforeTimestamp for user: $User"
|
||||
$getItemsMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||
$response = Invoke-SOAPRequest -Token $Token -Message $getItemsMsg
|
||||
|
||||
@ -468,15 +504,24 @@ function Get-ItemsToPurge {
|
||||
Select-Object -ExpandProperty Node
|
||||
$moreToList = ![System.Convert]::ToBoolean($rootFolder.IncludesLastItemInRange)
|
||||
|
||||
Write-Host "Total items under $WellKnownRoot/$SubFolderName"$rootFolder.TotalItemsInView
|
||||
|
||||
foreach ($item in $items) {
|
||||
$itemId = $item.ItemId.Id
|
||||
$changeKey = $item.ItemId.Changekey
|
||||
$itemName = $item.DisplayName
|
||||
$itemName = ""
|
||||
$itemCreateTime = $item.ExtendedProperty
|
||||
| Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
|
||||
| Select-Object -ExpandProperty Value
|
||||
| Get-Date
|
||||
|
||||
# can be improved to pass the field to use as a name as a parameter but this is good for now
|
||||
switch -casesensitive ($WellKnownRoot) {
|
||||
"calendar" { $itemName = $item.Subject }
|
||||
"contacts" { $itemName = $item.DisplayName }
|
||||
Default { $itemName = $item.DisplayName }
|
||||
}
|
||||
|
||||
if ([String]::IsNullOrEmpty($itemId) -or [String]::IsNullOrEmpty($changeKey)) {
|
||||
continue
|
||||
}
|
||||
@ -491,33 +536,51 @@ function Get-ItemsToPurge {
|
||||
$itemsToDelete += $item
|
||||
}
|
||||
|
||||
if ($WhatIfPreference) {
|
||||
# not actually deleting items so only do a single iteration
|
||||
$moreToList = $false
|
||||
}
|
||||
|
||||
return $itemsToDelete, $moreToList
|
||||
}
|
||||
|
||||
function Purge-Contacts {
|
||||
function Purge-Items {
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
Param(
|
||||
[Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
|
||||
[datetime]$PurgeBeforeTimestamp
|
||||
[datetime]$PurgeBeforeTimestamp,
|
||||
|
||||
[Parameter(Mandatory = $True, HelpMessage = "Items folder")]
|
||||
[string]$ItemsFolder,
|
||||
|
||||
[Parameter(Mandatory = $False, HelpMessage = "Items sub-folder")]
|
||||
[string]$ItemsSubFolder = $null
|
||||
|
||||
)
|
||||
|
||||
Write-Host "`nCleaning up contacts older than $PurgeBeforeTimestamp"
|
||||
Write-Host "-------------------------------------------------------"
|
||||
$additionalAttributes = "SendMeetingCancellations='SendToNone'"
|
||||
|
||||
# Create one seed contact which will have recent create date and will not be swept
|
||||
Write-Host "`nCleaning up items from folder $ItemsFolder($ItemsSubFolder) older than $PurgeBeforeTimestamp"
|
||||
Write-Host "-----------------------------------------------------------------------------"
|
||||
|
||||
if ($ItemsFolder -eq "contacts") {
|
||||
$ItemsSubFolder = $null
|
||||
$additionalAttributes = ""
|
||||
|
||||
# Create one seed contact which will have recent create date and will not be sweapt
|
||||
# This is needed since tests rely on some contact data being present
|
||||
Write-Host "`nCreating seed contact"
|
||||
Create-Contact
|
||||
}
|
||||
|
||||
$moreToList = $True
|
||||
# only get max of 1000 results so we may need to iterate over eligible contacts
|
||||
while ($moreToList) {
|
||||
$itemsToDelete, $moreToList = Get-ItemsToPurge -WellKnownRoot "contacts" -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
$itemsToDelete, $moreToList = Get-ItemsToPurge -WellKnownRoot $ItemsFolder -SubFolderName $ItemsSubFolder -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
$itemsToDeleteCount = $itemsToDelete.count
|
||||
$itemsToDeleteBody = ""
|
||||
|
||||
if ($itemsToDeleteCount -eq 0) {
|
||||
Write-Host "`nNo more contacts to delete matching criteria"
|
||||
Write-Host "`nNo more items to delete matching criteria"
|
||||
break
|
||||
}
|
||||
|
||||
@ -531,7 +594,7 @@ function Purge-Contacts {
|
||||
# Do the actual deletion in a batch request
|
||||
# DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
|
||||
$body = @"
|
||||
<m:DeleteItem DeleteType="HardDelete">
|
||||
<m:DeleteItem DeleteType="HardDelete" $additionalAttributes>
|
||||
<m:ItemIds>
|
||||
$itemsToDeleteBody
|
||||
</m:ItemIds>
|
||||
@ -544,8 +607,10 @@ function Purge-Contacts {
|
||||
$emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||
$response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
|
||||
|
||||
Write-Host "`nDeleted $itemsToDeleteCount items..."
|
||||
Write-Verbose "Delete response:`n"
|
||||
Write-Verbose $response.OuterXml
|
||||
|
||||
Write-Host "`nDeleted $itemsToDeleteCount items..."
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -564,7 +629,10 @@ $purgeFolderParams = @{
|
||||
Purge-Folders @purgeFolderParams
|
||||
|
||||
#purge older contacts
|
||||
Purge-Contacts -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
Purge-Items -ItemsFolder "contacts" -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
|
||||
#purge older contact birthday events
|
||||
Purge-Items -ItemsFolder "calendar" -ItemsSubFolder "Birthdays" -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||
|
||||
# Empty Deleted Items and then purge all recoverable items. Deletes the following
|
||||
# -/Recoverable Items/Audits
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user