diff --git a/src/onedrive.d b/src/onedrive.d index 0620bdb6..5b69c8aa 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -166,7 +166,7 @@ final class OneDriveApi { import std.stdio, std.regex; char[] response; - string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=files.readwrite%20files.readwrite.all%20offline_access&response_type=code&redirect_uri=" ~ redirectUrl; + string url = authUrl ~ "?client_id=" ~ clientId ~ "&scope=Files.ReadWrite%20Files.ReadWrite.all%20Sites.ReadWrite.All%20offline_access&response_type=code&redirect_uri=" ~ redirectUrl; string authFilesString = cfg.getValueString("auth_files"); if (authFilesString == "") { log.log("Authorize this app visiting:\n"); @@ -702,9 +702,15 @@ final class OneDriveApi case 400: // Bad Request .. how should we act? log.vlog("OneDrive returned a 'HTTP 400 - Bad Request' - gracefully handling error"); - break; + break; - // Item not found + // 403 - Forbidden + case 403: + // OneDrive responded that the user is forbidden + log.vlog("OneDrive returned a 'HTTP 403 - Forbidden' - gracefully handling error"); + break; + + // 404 - Item not found case 404: // Item was not found - do not throw an exception log.vlog("OneDrive returned a 'HTTP 404 - Item not found' - gracefully handling error"); @@ -774,12 +780,19 @@ final class OneDriveApi case 400: // Bad Request .. how should we act? log.vlog("OneDrive returned a 'HTTP 400 - Bad Request' - gracefully handling error"); - break; + break; + + // 403 - Forbidden + case 403: + // OneDrive responded that the user is forbidden + log.vlog("OneDrive returned a 'HTTP 403 - Forbidden' - gracefully handling error"); + // Throw this as a specific exception so this is caught when performing sync.o365SiteSearch + throw new OneDriveException(http.statusLine.code, http.statusLine.reason, response); // 412 - Precondition Failed case 412: log.vlog("OneDrive returned a 'HTTP 412 - Precondition Failed' - gracefully handling error"); - // Throw this as a specific exception so this is caught when performing uploadLastModifiedTime + // Throw this as a specific exception so this is caught when performing sync.uploadLastModifiedTime throw new OneDriveException(http.statusLine.code, http.statusLine.reason, response); // Server side (OneDrive) Errors diff --git a/src/sync.d b/src/sync.d index 70647ccc..459b7a8e 100644 --- a/src/sync.d +++ b/src/sync.d @@ -2608,30 +2608,80 @@ final class SyncEngine string drive_id; string webUrl; bool found = false; - JSONValue siteQuery = onedrive.o365SiteSearch(encodeComponent(o365SharedLibraryName)); + JSONValue siteQuery; log.log("Office 365 Library Name Query: ", o365SharedLibraryName); - foreach (searchResult; siteQuery["value"].array) { - // Need an 'exclusive' match here with o365SharedLibraryName as entered - log.vdebug("Found O365 Site: ", searchResult); - if (o365SharedLibraryName == searchResult["displayName"].str){ - // 'displayName' matches search request - site_id = searchResult["id"].str; - webUrl = searchResult["webUrl"].str; - JSONValue siteDriveQuery = onedrive.o365SiteDrives(site_id); - foreach (driveResult; siteDriveQuery["value"].array) { - // Display results - found = true; - writeln("SiteName: ", searchResult["displayName"].str); - writeln("drive_id: ", driveResult["id"].str); - writeln("URL: ", webUrl); - } + try { + siteQuery = onedrive.o365SiteSearch(encodeComponent(o365SharedLibraryName)); + } catch (OneDriveException e) { + log.error("ERROR: Query of OneDrive for Office 365 Library Name failed"); + if (e.httpStatusCode == 403) { + // Forbidden - most likely authentication scope needs to be updated + log.error("ERROR: Authentication scope needs to be updated. Use --logout and re-authenticate client."); + return; + } else { + // display what the error is + auto errorArray = splitLines(e.msg); + log.error("Error Message: ", errorArray[0]); + // extract 'message' as the reason + JSONValue errorMessage = parseJSON(replace(e.msg, errorArray[0], "")); + log.error("Error Reason: ", errorMessage["error"]["message"].str); + return; } } - if(!found) { - writeln("ERROR: This site could not be found. Please check it's name and your permissions to access the site."); + // is siteQuery a valid JSON object & contain data we can use? + if ((siteQuery.type() == JSONType.object) && ("value" in siteQuery)) { + // valid JSON object + foreach (searchResult; siteQuery["value"].array) { + // Need an 'exclusive' match here with o365SharedLibraryName as entered + log.vdebug("Found O365 Site: ", searchResult); + if (o365SharedLibraryName == searchResult["displayName"].str){ + // 'displayName' matches search request + site_id = searchResult["id"].str; + webUrl = searchResult["webUrl"].str; + JSONValue siteDriveQuery; + + try { + siteDriveQuery = onedrive.o365SiteDrives(site_id); + } catch (OneDriveException e) { + log.error("ERROR: Query of OneDrive for Office Site ID failed"); + auto errorArray = splitLines(e.msg); + log.error("Error Message: ", errorArray[0]); + // extract 'message' as the reason + JSONValue errorMessage = parseJSON(replace(e.msg, errorArray[0], "")); + log.error("Error Reason: ", errorMessage["error"]["message"].str); + return; + } + + // is siteDriveQuery a valid JSON object & contain data we can use? + if ((siteDriveQuery.type() == JSONType.object) && ("value" in siteDriveQuery)) { + // valid JSON object + foreach (driveResult; siteDriveQuery["value"].array) { + // Display results + found = true; + writeln("SiteName: ", searchResult["displayName"].str); + writeln("drive_id: ", driveResult["id"].str); + writeln("URL: ", webUrl); + } + } else { + // not a valid JSON object + log.error("ERROR: There was an error performing this operation on OneDrive"); + log.error("ERROR: Increase logging verbosity to assist determining why."); + return; + } + } + } + + if(!found) { + log.error("ERROR: This site could not be found. Please check it's name and your permissions to access the site."); + } + } else { + // not a valid JSON object + log.error("ERROR: There was an error performing this operation on OneDrive"); + log.error("ERROR: Increase logging verbosity to assist determining why."); + return; } }