Update code

* Update code
This commit is contained in:
abraunegg 2020-07-02 08:01:21 +10:00
parent 6b0d42faa1
commit 96e02a3e71
2 changed files with 137 additions and 23 deletions

View file

@ -105,8 +105,16 @@ final class OneDriveApi
private SysTime accessTokenExpiration;
private HTTP http;
// if true, every new access token is printed
// If true, every new access token is printed
bool printAccessToken;
// OneDrive Business External Shared Folder tenant handling
bool externalTenant = false;
string externalTenantID = "";
string externalTokenUrl = "";
string externalRefreshToken = "";
string externalAccessToken = "";
SysTime externalAccessTokenExpiration;
this(Config cfg)
{
@ -393,6 +401,50 @@ final class OneDriveApi
.retryAfterValue = 0;
}
void setExternalTenant(string externalTenantValue)
{
// Flag that we are using an external tenant
externalTenant = true;
externalTenantID = externalTenantValue;
// Configure externalTokenUrl for this external tenant
string azureConfigValue = cfg.getValueString("azure_ad_endpoint");
switch(azureConfigValue) {
case "":
externalTokenUrl = globalAuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
break;
case "USL4":
externalTokenUrl = usl4AuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
break;
case "USL5":
externalTokenUrl = usl5AuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
break;
case "DE":
externalTokenUrl = deAuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
break;
case "CN":
externalTokenUrl = cnAuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
tokenUrl = cnAuthEndpoint ~ "/common/oauth2/v2.0/token";
break;
// Default - all other entries
default:
externalTokenUrl = globalAuthEndpoint ~ "/" ~ externalTenantID ~ "/oauth2/v2.0/token";
}
// Get new token and configure this for use
newToken();
}
void clearExternalTenant()
{
// Clear any external tenant that was set
externalTenant = false;
externalTenantID = "";
externalTokenUrl = "";
externalRefreshToken = "";
externalAccessToken = "";
}
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/drive_get
JSONValue getDefaultDrive()
{
@ -576,8 +628,7 @@ final class OneDriveApi
return get(url);
}
// Return the requested details of the specified id
// Return the requested details of the specified file id
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_get
JSONValue getFileDetails(const(char)[] driveId, const(char)[] id)
{
@ -690,30 +741,49 @@ final class OneDriveApi
private void acquireToken(const(char)[] postData)
{
JSONValue response;
try {
response = post(tokenUrl, postData);
if (!externalTenant) {
// use normal token url
response = post(tokenUrl, postData);
} else {
// use external tenant token url
response = post(externalTokenUrl, postData);
}
} catch (OneDriveException e) {
// an error was generated
displayOneDriveErrorMessage(e.msg);
}
if (response.type() == JSONType.object) {
if ("access_token" in response){
accessToken = "bearer " ~ response["access_token"].str();
refreshToken = response["refresh_token"].str();
accessTokenExpiration = Clock.currTime() + dur!"seconds"(response["expires_in"].integer());
if (!.dryRun) {
std.file.write(cfg.refreshTokenFilePath, refreshToken);
// what sort of tenant token are we processing?
if (!externalTenant) {
// Normal tenant / token processing
if ("access_token" in response){
accessToken = "bearer " ~ response["access_token"].str();
refreshToken = response["refresh_token"].str();
accessTokenExpiration = Clock.currTime() + dur!"seconds"(response["expires_in"].integer());
if (!.dryRun) {
std.file.write(cfg.refreshTokenFilePath, refreshToken);
}
if (printAccessToken) writeln("New access token: ", accessToken);
} else {
log.error("\nInvalid authentication response from OneDrive. Please check the response uri\n");
// re-authorize
authorize();
}
if (printAccessToken) writeln("New access token: ", accessToken);
} else {
log.error("\nInvalid authentication response from OneDrive. Please check the response uri\n");
// re-authorize
authorize();
// External tenant token handling
if ("access_token" in response){
externalAccessToken = "bearer " ~ response["access_token"].str();
externalRefreshToken = response["refresh_token"].str();
externalAccessTokenExpiration = Clock.currTime() + dur!"seconds"(response["expires_in"].integer());
if (printAccessToken) writeln("New external access token: ", externalAccessToken);
} else {
log.error("\nInvalid authentication response from OneDrive. Please check the response uri\n");
}
}
} else {
log.vdebug("Invalid JSON response from OneDrive unable to initialize application");
log.vdebug("Invalid JSON response from OneDrive unable to aquire token to initialize application");
}
}
@ -732,7 +802,20 @@ final class OneDriveApi
private void addAccessTokenHeader()
{
http.addRequestHeader("Authorization", accessToken);
// Which access token header must we add?
if (!externalTenant) {
// Add the default client accessToken
http.addRequestHeader("Authorization", accessToken);
} else {
// Add the external tenant accessToken
if (externalAccessToken.empty) {
// if this is still empty, we are probably in the process of getting an updated external access token
// use our original one for the moment until this is set
http.addRequestHeader("Authorization", accessToken);
} else {
http.addRequestHeader("Authorization", externalAccessToken);
}
}
}
private JSONValue get(const(char)[] url, bool skipToken = false)

View file

@ -556,11 +556,24 @@ final class SyncEngine
// Check OneDrive Business Shared Folders, if configured to do so
if (syncBusinessFolders){
// Get My Tenent Details
string myTenantID;
JSONValue tenantDetailsResponse = onedrive.getTenantID();
if (tenantDetailsResponse.type() == JSONType.object) {
foreach (searchResult; tenantDetailsResponse["value"].array) {
myTenantID = searchResult["id"].str;
}
} else {
// Log that an invalid JSON object was returned
log.error("ERROR: onedrive.getTenantID call returned an invalid JSON Object");
}
// query OneDrive Business Shared Folders shared with me
log.vlog("Attempting to sync OneDrive Business Shared Folders");
JSONValue graphQuery = onedrive.getSharedWithMe();
if (graphQuery.type() == JSONType.object) {
string sharedFolderName;
bool isExternalTenant = false;
foreach (searchResult; graphQuery["value"].array) {
sharedFolderName = searchResult["name"].str;
// Compare this to values in business_shared_folders
@ -570,6 +583,7 @@ final class SyncEngine
bool itemInDatabase = false;
bool itemLocalDirExists = false;
bool itemPathIsLocal = false;
isExternalTenant = false;
// "what if" there are 2 or more folders shared with me have the "same" name?
// The folder name will be the same, but driveId will be different
@ -577,11 +591,19 @@ final class SyncEngine
log.vdebug("Shared Folder Name: ", sharedFolderName);
log.vdebug("Parent Drive Id: ", searchResult["remoteItem"]["parentReference"]["driveId"].str);
log.vdebug("Shared Item Id: ", searchResult["remoteItem"]["id"].str);
Item databaseItem;
// for each driveid in the existing driveIDsArray
// Is this OneDrive Shared Folder on an external tenant?
if (searchResult["remoteItem"]["sharepointIds"]["tenantId"].str != myTenantID) {
isExternalTenant = true;
log.vdebug("This shared folder is shared from an external organisation as the tenant is different");
// Have to configure the access to this tenant, which requires separate tokenUrl for that tenant
onedrive.setExternalTenant(searchResult["remoteItem"]["sharepointIds"]["tenantId"].str);
}
// for each driveid in the existing driveIDsArray
Item databaseItem;
foreach (searchDriveId; driveIDsArray) {
log.vdebug("searching database for: ", searchDriveId, " ", sharedFolderName);
log.vdebug("Searching database for: ", searchDriveId, ", ", sharedFolderName);
if (itemdb.selectByPath(sharedFolderName, searchDriveId, databaseItem)) {
log.vdebug("Found shared folder name in database");
itemInDatabase = true;
@ -666,7 +688,11 @@ final class SyncEngine
log.vlog("WARNING: Conflict Shared By: ", sharedByName);
}
}
}
}
}
if (isExternalTenant) {
// clear external tenant
onedrive.clearExternalTenant();
}
}
} else {
@ -5481,8 +5507,13 @@ final class SyncEngine
// Get My Tenent Details
string myTenantID;
JSONValue tenantDetailsResponse = onedrive.getTenantID();
foreach (searchResult; tenantDetailsResponse["value"].array) {
myTenantID = searchResult["id"].str;
if (tenantDetailsResponse.type() == JSONType.object) {
foreach (searchResult; tenantDetailsResponse["value"].array) {
myTenantID = searchResult["id"].str;
}
} else {
// Log that an invalid JSON object was returned
log.error("ERROR: onedrive.getTenantID call returned an invalid JSON Object");
}
// Query the GET /me/drive/sharedWithMe API