mirror of
https://github.com/abraunegg/onedrive
synced 2024-05-23 08:02:16 +02:00
Use 'nextLink' value if present when searching for specific SharePoint site names (#1329)
* Use 'nextLink' value if present when searching for specific SharePoint site names * Update error output to provide more details why an error occurred if a SharePoint site lacks the details we need to perform the match
This commit is contained in:
parent
cefb3169fa
commit
b8717fbc53
|
@ -33,7 +33,7 @@ This client is a 'fork' of the [skilion](https://github.com/skilion/onedrive) cl
|
||||||
## Frequently Asked Questions
|
## Frequently Asked Questions
|
||||||
Refer to [Frequently Asked Questions](https://github.com/abraunegg/onedrive/wiki/Frequently-Asked-Questions)
|
Refer to [Frequently Asked Questions](https://github.com/abraunegg/onedrive/wiki/Frequently-Asked-Questions)
|
||||||
|
|
||||||
## Have a question?
|
## Have a question
|
||||||
If you have a question or need something clarified, please raise a new disscussion post [here](https://github.com/abraunegg/onedrive/discussions)
|
If you have a question or need something clarified, please raise a new disscussion post [here](https://github.com/abraunegg/onedrive/discussions)
|
||||||
|
|
||||||
## Reporting an Issue or Bug
|
## Reporting an Issue or Bug
|
||||||
|
|
|
@ -780,10 +780,15 @@ final class OneDriveApi
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/site_search?view=odsp-graph-online
|
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/site_search?view=odsp-graph-online
|
||||||
JSONValue o365SiteSearch(){
|
JSONValue o365SiteSearch(const(char)[] nextLink){
|
||||||
checkAccessTokenExpired();
|
checkAccessTokenExpired();
|
||||||
const(char)[] url;
|
const(char)[] url;
|
||||||
url = siteSearchUrl ~ "=*";
|
// configure URL to query
|
||||||
|
if (nextLink.empty) {
|
||||||
|
url = siteSearchUrl ~ "=*";
|
||||||
|
} else {
|
||||||
|
url = nextLink;
|
||||||
|
}
|
||||||
return get(url);
|
return get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
211
src/sync.d
211
src/sync.d
|
@ -5393,90 +5393,155 @@ final class SyncEngine
|
||||||
string webUrl;
|
string webUrl;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
JSONValue siteQuery;
|
JSONValue siteQuery;
|
||||||
|
string nextLink;
|
||||||
|
string[] siteSearchResults;
|
||||||
|
|
||||||
log.log("Office 365 Library Name Query: ", o365SharedLibraryName);
|
log.log("Office 365 Library Name Query: ", o365SharedLibraryName);
|
||||||
|
|
||||||
try {
|
for (;;) {
|
||||||
siteQuery = onedrive.o365SiteSearch();
|
try {
|
||||||
} catch (OneDriveException e) {
|
siteQuery = onedrive.o365SiteSearch(nextLink);
|
||||||
log.error("ERROR: Query of OneDrive for Office 365 Library Name failed");
|
} catch (OneDriveException e) {
|
||||||
if (e.httpStatusCode == 403) {
|
log.error("ERROR: Query of OneDrive for Office 365 Library Name failed");
|
||||||
// Forbidden - most likely authentication scope needs to be updated
|
if (e.httpStatusCode == 403) {
|
||||||
log.error("ERROR: Authentication scope needs to be updated. Use --logout and re-authenticate client.");
|
// Forbidden - most likely authentication scope needs to be updated
|
||||||
return;
|
log.error("ERROR: Authentication scope needs to be updated. Use --logout and re-authenticate client.");
|
||||||
} else {
|
return;
|
||||||
// display what the error is
|
}
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
// HTTP request returned status code 429 (Too Many Requests)
|
||||||
return;
|
if (e.httpStatusCode == 429) {
|
||||||
}
|
// HTTP request returned status code 429 (Too Many Requests). We need to leverage the response Retry-After HTTP header to ensure minimum delay until the throttle is removed.
|
||||||
}
|
handleOneDriveThrottleRequest();
|
||||||
|
log.vdebug("Retrying original request that generated the OneDrive HTTP 429 Response Code (Too Many Requests) - attempting to query OneDrive drive children");
|
||||||
// is siteQuery a valid JSON object & contain data we can use?
|
}
|
||||||
if ((siteQuery.type() == JSONType.object) && ("value" in siteQuery)) {
|
// HTTP request returned status code 504 (Gateway Timeout) or 429 retry
|
||||||
// valid JSON object
|
if ((e.httpStatusCode == 429) || (e.httpStatusCode == 504)) {
|
||||||
log.vdebug("O365 Query Response: ", siteQuery);
|
// re-try the specific changes queries
|
||||||
|
if (e.httpStatusCode == 504) {
|
||||||
foreach (searchResult; siteQuery["value"].array) {
|
log.log("OneDrive returned a 'HTTP 504 - Gateway Timeout' when attempting to query Sharepoint Sites - retrying applicable request");
|
||||||
// Need an 'exclusive' match here with o365SharedLibraryName as entered
|
log.vdebug("siteQuery = onedrive.o365SiteSearch(nextLink) previously threw an error - retrying");
|
||||||
log.vdebug("Found O365 Site: ", searchResult);
|
// The server, while acting as a proxy, did not receive a timely response from the upstream server it needed to access in attempting to complete the request.
|
||||||
|
log.vdebug("Thread sleeping for 30 seconds as the server did not receive a timely response from the upstream server it needed to access in attempting to complete the request");
|
||||||
// 'displayName', 'id' and 'webUrl' have to be present in the search result record
|
Thread.sleep(dur!"seconds"(30));
|
||||||
if (("displayName" in searchResult) && ("id" in searchResult) && ("webUrl" in searchResult)) {
|
}
|
||||||
if (o365SharedLibraryName == searchResult["displayName"].str){
|
// re-try original request - retried for 429 and 504
|
||||||
// 'displayName' matches search request
|
try {
|
||||||
site_id = searchResult["id"].str;
|
log.vdebug("Retrying Query: siteQuery = onedrive.o365SiteSearch(nextLink)");
|
||||||
webUrl = searchResult["webUrl"].str;
|
siteQuery = onedrive.o365SiteSearch(nextLink);
|
||||||
JSONValue siteDriveQuery;
|
log.vdebug("Query 'siteQuery = onedrive.o365SiteSearch(nextLink)' performed successfully on re-try");
|
||||||
|
} catch (OneDriveException e) {
|
||||||
try {
|
// display what the error is
|
||||||
siteDriveQuery = onedrive.o365SiteDrives(site_id);
|
log.vdebug("Query Error: siteQuery = onedrive.o365SiteSearch(nextLink) on re-try after delay");
|
||||||
} catch (OneDriveException e) {
|
// error was not a 504 this time
|
||||||
log.error("ERROR: Query of OneDrive for Office Site ID failed");
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
// display what the error is
|
return;
|
||||||
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 'displayName' not present in JSON results
|
// display what the error is
|
||||||
log.error("ERROR: The results returned from OneDrive API do not contain the required items to match. Please check your permissions with your site administrator.");
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
log.error("ERROR: Your site security settings is preventing the following details from being accessed: 'displayName', 'id' and 'webUrl'");
|
|
||||||
log.error("ERROR: To debug this further, please use --verbose --verbose to provide insight as to what details are actually returned.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
// is siteQuery a valid JSON object & contain data we can use?
|
||||||
log.error("ERROR: The requested SharePoint site could not be found. Please check it's name and your permissions to access the site.");
|
if ((siteQuery.type() == JSONType.object) && ("value" in siteQuery)) {
|
||||||
// List all sites returned to assist user
|
// valid JSON object
|
||||||
log.log("\nThe following SharePoint site names were returned:");
|
log.vdebug("O365 Query Response: ", siteQuery);
|
||||||
|
|
||||||
foreach (searchResult; siteQuery["value"].array) {
|
foreach (searchResult; siteQuery["value"].array) {
|
||||||
// list the display name that we use to match against the user query
|
// Need an 'exclusive' match here with o365SharedLibraryName as entered
|
||||||
log.log(" * ", searchResult["displayName"].str);
|
log.vdebug("Found O365 Site: ", searchResult);
|
||||||
|
|
||||||
|
// 'displayName', 'id' and 'webUrl' have to be present in the search result record
|
||||||
|
if (("displayName" in searchResult) && ("id" in searchResult) && ("webUrl" in 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");
|
||||||
|
// display what the error is
|
||||||
|
displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 'displayName', 'id' or ''webUrl' not present in JSON results for a specific site
|
||||||
|
string siteNameAvailable = "Site 'name' was restricted by OneDrive API permissions";
|
||||||
|
bool displayNameAvailable = false;
|
||||||
|
bool idAvailable = false;
|
||||||
|
bool webUrlAvailable = false;
|
||||||
|
if ("name" in searchResult) siteNameAvailable = searchResult["name"].str;
|
||||||
|
if ("displayName" in searchResult) displayNameAvailable = true;
|
||||||
|
if ("id" in searchResult) idAvailable = true;
|
||||||
|
if ("webUrl" in searchResult) webUrlAvailable = true;
|
||||||
|
|
||||||
|
// Display error details for this site data
|
||||||
|
log.error("\nERROR: SharePoint Site details not provided for: ", siteNameAvailable);
|
||||||
|
log.error("ERROR: The SharePoint Site results returned from OneDrive API do not contain the required items to match. Please check your permissions with your site administrator.");
|
||||||
|
log.error("ERROR: Your site security settings is preventing the following details from being accessed: 'displayName', 'id' and 'webUrl'");
|
||||||
|
log.vlog(" - Is 'displayName' available = ", displayNameAvailable);
|
||||||
|
log.vlog(" - Is 'id' available = ", idAvailable);
|
||||||
|
log.vlog(" - Is 'webUrl' available = ", webUrlAvailable);
|
||||||
|
log.error("ERROR: To debug this further, please increase verbosity (--verbose or --verbose --verbose) to provide further insight as to what details are actually being returned.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
// The SharePoint site we are searching for was not found in this bundle set
|
||||||
|
// Add to siteSearchResults so we can display what we did find
|
||||||
|
string siteSearchResultsEntry;
|
||||||
|
foreach (searchResult; siteQuery["value"].array) {
|
||||||
|
siteSearchResultsEntry = " * " ~ searchResult["displayName"].str;
|
||||||
|
siteSearchResults ~= siteSearchResultsEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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 a collection exceeds the default page size (200 items), the @odata.nextLink property is returned in the response
|
||||||
|
// to indicate more items are available and provide the request URL for the next page of items.
|
||||||
|
if ("@odata.nextLink" in siteQuery) {
|
||||||
|
// Update nextLink to next set of SharePoint library names
|
||||||
|
nextLink = siteQuery["@odata.nextLink"].str;
|
||||||
|
log.vdebug("Setting nextLink to (@odata.nextLink): ", nextLink);
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was the intended target found?
|
||||||
|
if(!found) {
|
||||||
|
log.error("\nERROR: The requested SharePoint site could not be found. Please check it's name and your permissions to access the site.");
|
||||||
|
// List all sites returned to assist user
|
||||||
|
log.log("\nThe following SharePoint site names were returned:");
|
||||||
|
foreach (searchResultEntry; siteSearchResults) {
|
||||||
|
// list the display name that we use to match against the user query
|
||||||
|
log.log(searchResultEntry);
|
||||||
}
|
}
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6181,8 +6246,8 @@ final class SyncEngine
|
||||||
// to indicate more items are available and provide the request URL for the next page of items.
|
// to indicate more items are available and provide the request URL for the next page of items.
|
||||||
if ("@odata.nextLink" in thisLevelChildren) {
|
if ("@odata.nextLink" in thisLevelChildren) {
|
||||||
// Update nextLink to next changeSet bundle
|
// Update nextLink to next changeSet bundle
|
||||||
log.vdebug("Setting nextLink to (@odata.nextLink): ", nextLink);
|
|
||||||
nextLink = thisLevelChildren["@odata.nextLink"].str;
|
nextLink = thisLevelChildren["@odata.nextLink"].str;
|
||||||
|
log.vdebug("Setting nextLink to (@odata.nextLink): ", nextLink);
|
||||||
} else break;
|
} else break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue