From 83cc2e419b50431ae9819c1dcd72e9b7b241c6d9 Mon Sep 17 00:00:00 2001 From: abraunegg Date: Sat, 19 Jan 2019 12:59:39 +1100 Subject: [PATCH] Add business retention policy handler (Issue #338) * When OneDrive Business is configured with Retention Policies, attempts to delete a 'non empty' folder results in an an error response. Correctly handle the error response to print a warning message that OneDrive content must be manually deleted. **Note:** A future version of this client will handle the removal of 'non empty' folders when Retention Policies are enabled. --- src/sync.d | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/sync.d b/src/sync.d index 6efcdad8..8d97abde 100644 --- a/src/sync.d +++ b/src/sync.d @@ -1735,7 +1735,10 @@ final class SyncEngine if ((item.driveId == "") && (item.id == "") && (item.eTag == "")){ // These are empty ... we cannot delete if this is empty .... + log.vdebug("item.driveId, item.id & item.eTag are empty ... need to query OneDrive for values"); + log.vdebug("Checking OneDrive for path: ", path); JSONValue onedrivePathDetails = onedrive.getPathDetails(path); // Returns a JSON String for the OneDrive Path + log.vdebug("OneDrive path details: ", onedrivePathDetails); item.driveId = onedrivePathDetails["parentReference"]["driveId"].str; // Should give something like 12345abcde1234a1 item.id = onedrivePathDetails["id"].str; // This item's ID. Should give something like 12345ABCDE1234A1!101 item.eTag = onedrivePathDetails["eTag"].str; // Should be something like aNjM2NjJFRUVGQjY2NjJFMSE5MzUuMA @@ -1744,11 +1747,41 @@ final class SyncEngine try { onedrive.deleteById(item.driveId, item.id, item.eTag); } catch (OneDriveException e) { - if (e.httpStatusCode == 404) log.vlog("OneDrive reported: The resource could not be found."); - else throw e; + if (e.httpStatusCode == 404) { + // item.id, item.eTag could not be found on driveId + log.vlog("OneDrive reported: The resource could not be found."); + } + + else { + // Not a 404 response .. is this a 403 response due to OneDrive Business Retention Policy being enabled? + if ((e.httpStatusCode == 403) && (accountType != "personal")) { + auto errorArray = splitLines(e.msg); + JSONValue errorMessage = parseJSON(replace(e.msg, errorArray[0], "")); + if (errorMessage["error"]["message"].str == "Request was cancelled by event received. If attempting to delete a non-empty folder, it's possible that it's on hold") { + // Issue #338 - Unable to delete OneDrive content when OneDrive Business Retention Policy is enabled + // TODO: We have to recursively delete all files & folders from this path to delete + // WARN: + log.error("\nERROR: Unable to delete the requested remote path from OneDrive: ", path); + log.error("ERROR: This error is due to OneDrive Business Retention Policy being applied"); + log.error("WORKAROUND: Manually delete all files and folders from the above path as per Business Retention Policy\n"); + } + } else { + // Not a 403 response & OneDrive Business Account / O365 Shared Folder / Library + log.log("\n\nOneDrive returned an error with the following message:\n"); + auto errorArray = splitLines(e.msg); + log.log("Error Message: ", errorArray[0]); + // extract 'message' as the reason + JSONValue errorMessage = parseJSON(replace(e.msg, errorArray[0], "")); + log.log("Error Reason: ", errorMessage["error"]["message"].str); + return; + } + } } + + // delete the reference in the local database itemdb.deleteById(item.driveId, item.id); if (item.remoteId != null) { + // If the item is a remote item, delete the reference in the local database itemdb.deleteById(item.remoteDriveId, item.remoteId); } }