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 {
|
try {
|
||||||
# Assumes that the timestamp is at the end and starts with yyyy-mm-ddT and is ISO8601
|
# 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)
|
$timestamp = [System.Convert]::ToDatetime($Matches.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,21 +226,31 @@ function Get-FoldersToPurge {
|
|||||||
| Select-Object -ExpandProperty Value
|
| Select-Object -ExpandProperty Value
|
||||||
| Get-Date
|
| Get-Date
|
||||||
|
|
||||||
$IsNameMatchParams = @{
|
if ($FolderNamePurgeList.count -gt 0) {
|
||||||
'FolderName' = $folderName;
|
$IsNameMatchParams = @{
|
||||||
'FolderNamePurgeList' = $FolderNamePurgeList
|
'FolderName' = $folderName;
|
||||||
}
|
'FolderNamePurgeList' = $FolderNamePurgeList
|
||||||
|
}
|
||||||
|
|
||||||
$IsPrefixAndAgeMatchParams = @{
|
if ((IsNameMatch @IsNameMatchParams)) {
|
||||||
'FolderName' = $folderName;
|
Write-Host "• Found name match: $folderName ($folderCreateTime)"
|
||||||
'FolderCreateTime' = $folderCreateTime;
|
$foldersToDelete += $folder
|
||||||
'FolderPrefixPurgeList' = $FolderPrefixPurgeList;
|
continue
|
||||||
'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((IsNameMatch @IsNameMatchParams) -or (IsPrefixAndAgeMatch @IsPrefixAndAgeMatchParams)) {
|
if ($FolderPrefixPurgeList.count -gt 0) {
|
||||||
Write-Host "• Found: $folderName ($folderCreateTime)"
|
$IsPrefixAndAgeMatchParams = @{
|
||||||
$foldersToDelete += $folder
|
'FolderName' = $folderName;
|
||||||
|
'FolderCreateTime' = $folderCreateTime;
|
||||||
|
'FolderPrefixPurgeList' = $FolderPrefixPurgeList;
|
||||||
|
'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((IsPrefixAndAgeMatch @IsPrefixAndAgeMatchParams)) {
|
||||||
|
Write-Host "• Found prefix match: $folderName ($folderCreateTime)"
|
||||||
|
$foldersToDelete += $folder
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,6 +409,8 @@ function Purge-Folders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Create-Contact {
|
function Create-Contact {
|
||||||
|
[CmdletBinding(SupportsShouldProcess)]
|
||||||
|
|
||||||
$now = (Get-Date (Get-Date).ToUniversalTime() -Format "o")
|
$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
|
#used to create a recent seed contact that will be shielded from cleanup. CI tests rely on this
|
||||||
$body = @"
|
$body = @"
|
||||||
@ -419,14 +431,16 @@ function Create-Contact {
|
|||||||
</t:PhoneNumbers>
|
</t:PhoneNumbers>
|
||||||
<t:Birthday>2000-01-01T11:59:00Z</t:Birthday>
|
<t:Birthday>2000-01-01T11:59:00Z</t:Birthday>
|
||||||
<t:JobTitle>Tester</t:JobTitle>
|
<t:JobTitle>Tester</t:JobTitle>
|
||||||
<t:Surname>Plate</t:Surname>
|
|
||||||
</t:Contact>
|
</t:Contact>
|
||||||
</Items>
|
</Items>
|
||||||
</CreateItem>
|
</CreateItem>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
$createContactMsg = Initialize-SOAPMessage -User $User -Body $body
|
if ($PSCmdlet.ShouldProcess("Creating seed contact...", "", "Create contact")) {
|
||||||
$response = Invoke-SOAPRequest -Token $Token -Message $createContactMsg
|
Write-Host "`nCreating seed contact..."
|
||||||
|
$createContactMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||||
|
$response = Invoke-SOAPRequest -Token $Token -Message $createContactMsg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-ItemsToPurge {
|
function Get-ItemsToPurge {
|
||||||
@ -434,11 +448,33 @@ function Get-ItemsToPurge {
|
|||||||
[Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
|
[Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
|
||||||
[String]$WellKnownRoot,
|
[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)")]
|
[Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
|
||||||
[datetime]$PurgeBeforeTimestamp
|
[datetime]$PurgeBeforeTimestamp
|
||||||
)
|
)
|
||||||
|
|
||||||
$itemsToDelete = @()
|
$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
|
# SOAP message for getting the folder id
|
||||||
$body = @"
|
$body = @"
|
||||||
@ -450,12 +486,12 @@ function Get-ItemsToPurge {
|
|||||||
</t:AdditionalProperties>
|
</t:AdditionalProperties>
|
||||||
</ItemShape>
|
</ItemShape>
|
||||||
<ParentFolderIds>
|
<ParentFolderIds>
|
||||||
<t:DistinguishedFolderId Id="$WellKnownRoot"/>
|
$FoldersToSearchBody
|
||||||
</ParentFolderIds>
|
</ParentFolderIds>
|
||||||
</FindItem>
|
</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
|
$getItemsMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||||
$response = Invoke-SOAPRequest -Token $Token -Message $getItemsMsg
|
$response = Invoke-SOAPRequest -Token $Token -Message $getItemsMsg
|
||||||
|
|
||||||
@ -468,15 +504,24 @@ function Get-ItemsToPurge {
|
|||||||
Select-Object -ExpandProperty Node
|
Select-Object -ExpandProperty Node
|
||||||
$moreToList = ![System.Convert]::ToBoolean($rootFolder.IncludesLastItemInRange)
|
$moreToList = ![System.Convert]::ToBoolean($rootFolder.IncludesLastItemInRange)
|
||||||
|
|
||||||
|
Write-Host "Total items under $WellKnownRoot/$SubFolderName"$rootFolder.TotalItemsInView
|
||||||
|
|
||||||
foreach ($item in $items) {
|
foreach ($item in $items) {
|
||||||
$itemId = $item.ItemId.Id
|
$itemId = $item.ItemId.Id
|
||||||
$changeKey = $item.ItemId.Changekey
|
$changeKey = $item.ItemId.Changekey
|
||||||
$itemName = $item.DisplayName
|
$itemName = ""
|
||||||
$itemCreateTime = $item.ExtendedProperty
|
$itemCreateTime = $item.ExtendedProperty
|
||||||
| Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
|
| Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
|
||||||
| Select-Object -ExpandProperty Value
|
| Select-Object -ExpandProperty Value
|
||||||
| Get-Date
|
| 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)) {
|
if ([String]::IsNullOrEmpty($itemId) -or [String]::IsNullOrEmpty($changeKey)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -491,33 +536,51 @@ function Get-ItemsToPurge {
|
|||||||
$itemsToDelete += $item
|
$itemsToDelete += $item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($WhatIfPreference) {
|
||||||
|
# not actually deleting items so only do a single iteration
|
||||||
|
$moreToList = $false
|
||||||
|
}
|
||||||
|
|
||||||
return $itemsToDelete, $moreToList
|
return $itemsToDelete, $moreToList
|
||||||
}
|
}
|
||||||
|
|
||||||
function Purge-Contacts {
|
function Purge-Items {
|
||||||
[CmdletBinding(SupportsShouldProcess)]
|
[CmdletBinding(SupportsShouldProcess)]
|
||||||
Param(
|
Param(
|
||||||
[Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
|
[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"
|
$additionalAttributes = "SendMeetingCancellations='SendToNone'"
|
||||||
Write-Host "-------------------------------------------------------"
|
|
||||||
|
|
||||||
# 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"
|
||||||
# This is needed since tests rely on some contact data being present
|
Write-Host "-----------------------------------------------------------------------------"
|
||||||
Write-Host "`nCreating seed contact"
|
|
||||||
Create-Contact
|
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
|
||||||
|
Create-Contact
|
||||||
|
}
|
||||||
|
|
||||||
$moreToList = $True
|
$moreToList = $True
|
||||||
# only get max of 1000 results so we may need to iterate over eligible contacts
|
# only get max of 1000 results so we may need to iterate over eligible contacts
|
||||||
while ($moreToList) {
|
while ($moreToList) {
|
||||||
$itemsToDelete, $moreToList = Get-ItemsToPurge -WellKnownRoot "contacts" -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
$itemsToDelete, $moreToList = Get-ItemsToPurge -WellKnownRoot $ItemsFolder -SubFolderName $ItemsSubFolder -PurgeBeforeTimestamp $PurgeBeforeTimestamp
|
||||||
$itemsToDeleteCount = $itemsToDelete.count
|
$itemsToDeleteCount = $itemsToDelete.count
|
||||||
$itemsToDeleteBody = ""
|
$itemsToDeleteBody = ""
|
||||||
|
|
||||||
if ($itemsToDeleteCount -eq 0) {
|
if ($itemsToDeleteCount -eq 0) {
|
||||||
Write-Host "`nNo more contacts to delete matching criteria"
|
Write-Host "`nNo more items to delete matching criteria"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,21 +594,23 @@ function Purge-Contacts {
|
|||||||
# Do the actual deletion in a batch request
|
# Do the actual deletion in a batch request
|
||||||
# DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
|
# DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
|
||||||
$body = @"
|
$body = @"
|
||||||
<m:DeleteItem DeleteType="HardDelete">
|
<m:DeleteItem DeleteType="HardDelete" $additionalAttributes>
|
||||||
<m:ItemIds>
|
<m:ItemIds>
|
||||||
$itemsToDeleteBody
|
$itemsToDeleteBody
|
||||||
</m:ItemIds>
|
</m:ItemIds>
|
||||||
</m:DeleteItem>
|
</m:DeleteItem>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
if ($PSCmdlet.ShouldProcess("Deleting $itemsToDeleteCount items...", "$itemsToDeleteCount items", "Delete items")) {
|
if ($PSCmdlet.ShouldProcess("Deleting $itemsToDeleteCount items...", "$itemsToDeleteCount items", "Delete items")) {
|
||||||
Write-Host "`nDeleting $itemsToDeleteCount items..."
|
Write-Host "`nDeleting $itemsToDeleteCount items..."
|
||||||
|
|
||||||
$emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
|
$emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
|
||||||
$response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
|
$response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
|
||||||
|
|
||||||
|
Write-Verbose "Delete response:`n"
|
||||||
|
Write-Verbose $response.OuterXml
|
||||||
|
|
||||||
Write-Host "`nDeleted $itemsToDeleteCount items..."
|
Write-Host "`nDeleted $itemsToDeleteCount items..."
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,7 +629,10 @@ $purgeFolderParams = @{
|
|||||||
Purge-Folders @purgeFolderParams
|
Purge-Folders @purgeFolderParams
|
||||||
|
|
||||||
#purge older contacts
|
#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
|
# Empty Deleted Items and then purge all recoverable items. Deletes the following
|
||||||
# -/Recoverable Items/Audits
|
# -/Recoverable Items/Audits
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user