Implement --get-O365-drive-id to get correct SharePoint Shared Library (Issue #248) (#260)

* Implement --get-O365-drive-id to return the correct drive_id of a SharePoint Shared Library to use for syncing that repository
This commit is contained in:
abraunegg 2018-12-04 10:59:23 +11:00 committed by GitHub
parent 56b63acede
commit 29808c905c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 70 deletions

View file

@ -1,79 +1,21 @@
# Show how to access a Sharepoint group drive in Office 365 business or education
## Obtaining the Sharepoint Site Details
When we click "sync" in a Sharepoint groups Documents page we get an "odopen" URL, for example:
```
odopen://sync?userId=97858aa6%2Dcd6a%2D4025%2Da6ee%2D29ba80bcbec5&siteId=%7B0936e7d2%2D1285%2D4c54%2D81f9%2D55e9c8b8613b%7D&webId=%7B345db3b7%2D1ebb%2D484f%2D85e3%2D31c785278051%7D&webTitle=FFCCTT%5FIET&listId=%7BA3913FAC%2D26F8%2D4436%2DA9F6%2DAA6B44776343%7D&listTitle=Documentos&userEmail=georg%2Elehner%40ucan%2Eedu%2Eni&listTemplateTypeId=101&webUrl=https%3A%2F%2Fucanedu%2Esharepoint%2Ecom%2Fsites%2FFFCCTT%5FIET&webLogoUrl=%2Fsites%2FFFCCTT%5FIET%2F%5Fapi%2FGroupService%2FGetGroupImage%3Fid%3D%270e6466dc%2D1d90%2D41b0%2D9c9d%2Df6a818721435%27%26hash%3D636549326262064339&isSiteAdmin=1&webTemplate=64&onPrem=0&scope=OPENLIST
```
When we decode this URL we get the following:
1. Login to OneDrive and under 'Shared Libraries' obtain the shared library name
2. Run the following command using the 'onedrive' client
```
userId=97858aa6-cd6a-4025-a6ee-29ba80bcbec5
siteId={0936e7d2-1285-4c54-81f9-55e9c8b8613b}
webId={345db3b7-1ebb-484f-85e3-31c785278051}
webTitle=FFCCTT_IET
listId={A3913FAC-26F8-4436-A9F6-AA6B44776343}
listTitle=Documentos
userEmail=georg.lehner@ucan.edu.ni
listTemplateTypeId=101
webUrl=https://ucanedu.sharepoint.com/sites/FFCCTT_IET
webLogoUrl=/sites/FFCCTT_IET/_api/GroupService/GetGroupImage?id='0e6466dc-1d90-41b0-9c9d-f6a818721435'&hash=636549326262064339
isSiteAdmin=1
webTemplate=64
onPrem=0
scope=OPENLIST
onedrive --get-O365-drive-id '<your library name>'
```
In the following we refer to these parameters with e.g. $userId - wherever there are enclosing braces {} you have to strip them off.
## Obtaining the Authorization Token
To get the 'authorization bearer', run the following command:
```
onedrive --monitor --print-token
```
This will print out something like the following:
3. This will return the following:
```
Initializing the Synchronization Engine ...
New access token: bearer EwBYA8l6......T51Ag==
Initializing monitor ...
OneDrive monitor interval (seconds): 45
Office 365 Library Name: ab-github-odtest
drive_id: b!6H.....l7vVxU5
```
Everything after 'New access token: bearer' is your authorization token.
## Obtaining the Drive ID
To sync an Office365 / Business Shared Folder we need the Drive ID for that shared folder.
1. Get site drive-id with:
```
https://graph.microsoft.com/v1.0/sites/$host,$SiteId,$webId/lists/$listId/drive
```
**Example:**
```
curl -i 'https://graph.microsoft.com/v1.0/sites/ucanedu.sharepoint.com,0936e7d2-1285-4c54-81f9-55e9c8b8613b,345db3b7-1ebb-484f-85e3-31c785278051/lists/A3913FAC-26F8-4436-A9F6-AA6B44776343/drive' -H "Authorization: bearer <your_token>"
```
where $host is the hostname in $webUrl. This should return the following response which is the drive id:
b!0uc2CYUSVEyB-VXpyLhhO7ezXTS7Hk9IheMxx4UngFGsP5Gj-CY2RKn2qmtEd2ND
2. Get root folder id via drive-id
```
GET https://graph.microsoft.com/v1.0/drives/$drive-id/root
```
**Example:**
```
curl -i 'https://graph.microsoft.com/v1.0/drives/b!0uc2CYUSVEyB-VXpyLhhO7ezXTS7Hk9IheMxx4UngFGsP5Gj-CY2RKn2qmtEd2ND/root' -H "Authorization: bearer <your_token>"
```
This should return the following response:
016SJBHDN6Y2GOVW7725BZO354PWSELRRZ
## Configuring the onedrive client
Once you have obtained the 'drive id', add to your 'onedrive' configuration file (`~/.config/onedrive/config`)the following:
Once you have obtained the 'drive_id' above, add to your 'onedrive' configuration file (`~/.config/onedrive/config`)the following:
```
drive_id = "insert the drive id from above here"
```
The OneDrive client will now sync this shared 'drive id'
The OneDrive client will now sync this SharePoint shared library to your local system.

View file

@ -7,7 +7,7 @@
* Resumable uploads
* Support OneDrive for Business (part of Office 365)
* Shared folders (OneDrive Personal)
* SharePoint / Office 365 Group Drives (refer to README.Office365.md to configure)
* SharePoint / Office 365 Shared Libraries (refer to README.Office365.md to configure)
### What's missing:
* While local changes are uploaded right away, remote changes are delayed
@ -39,7 +39,7 @@ curl -fsS https://dlang.org/install.sh | bash -s dmd
### Dependencies: Debian - i386 / i686
**Note:** Validated with `Linux debian-i386 4.9.0-7-686-pae #1 SMP Debian 4.9.110-1 (2018-07-05) i686 GNU/Linux` and LDC - the LLVM D compiler (1.8.0).
First install development dependancies as per below:
First install development dependencies as per below:
```
sudo apt install build-essential
sudo apt install libcurl4-openssl-dev
@ -423,6 +423,7 @@ no option No sync and exit
-d --download-only Only download remote changes
--disable-upload-validation Disable upload validation when uploading to OneDrive
--enable-logging Enable client activity to a separate log file
--get-O365-drive-id Query and return the Office 365 Drive ID for a given Office 365 SharePoint Shared Library
--local-first Synchronize from the local directory source first, before downloading changes from OneDrive.
--logout Logout the current user
-m --monitor Keep monitoring for local and remote changes

View file

@ -33,6 +33,9 @@ Disable upload validation when uploading to OneDrive
\fB\-\-enable\-logging\fP
Enable client activity to a separate log file
.TP
\fB\-\-get\-O365\-drive\-id\fP
Query and return the Office 365 Drive ID for a given Office 365 SharePoint Shared Library
.TP
\fB\-\-local\-first\fP
Synchronize from the local directory source first, before downloading changes from OneDrive.
.TP
@ -192,4 +195,4 @@ where \fB%username%\fP represents the user who ran the client.
Further examples and documentation is available in
\f[C]@DOCDIR@/README.md\f[]
\f[C]@DOCDIR@/README.Office365.md\f[]

View file

@ -88,6 +88,8 @@ int main(string[] args)
// Does the user want to disable upload validation - https://github.com/abraunegg/onedrive/issues/205
// SharePoint will associate some metadata from the library the file is uploaded to directly in the file - thus change file size & checksums
bool disableUploadValidation = false;
// SharePoint / Office 365 Shared Library name to query
string o365SharedLibraryName;
try {
auto opt = getopt(
@ -102,6 +104,7 @@ int main(string[] args)
"download-only|d", "Only download remote changes", &downloadOnly,
"disable-upload-validation", "Disable upload validation when uploading to OneDrive", &disableUploadValidation,
"enable-logging", "Enable client activity to a separate log file", &enableLogFile,
"get-O365-drive-id", "Query and return the Office 365 Drive ID for a given Office 365 SharePoint Shared Library", &o365SharedLibraryName,
"local-first", "Synchronize from the local directory source first, before downloading changes from OneDrive.", &localFirst,
"logout", "Logout the current user", &logout,
"monitor|m", "Keep monitoring for local and remote changes", &monitor,
@ -205,7 +208,7 @@ int main(string[] args)
// create-directory, remove-directory, source-directory, destination-directory
// are activities that dont perform a sync no error message for these items either
if (((createDirectory != "") || (removeDirectory != "")) || ((sourceDirectory != "") && (destinationDirectory != "")) ) {
if (((createDirectory != "") || (removeDirectory != "")) || ((sourceDirectory != "") && (destinationDirectory != "")) || (o365SharedLibraryName != "") ) {
performSyncOK = true;
}
@ -307,6 +310,11 @@ int main(string[] args)
sync.renameDirectoryNoSync(sourceDirectory, destinationDirectory);
}
// Are we obtaining the Office 365 Drive ID for a given Office 365 SharePoint Shared Library?
if (o365SharedLibraryName != ""){
sync.querySiteCollectionForDriveID(o365SharedLibraryName);
}
// Are we performing a sync, resync or monitor operation?
if ((synchronize) || (resync) || (monitor)) {

View file

@ -10,11 +10,18 @@ static import log;
shared bool debugResponse = false;
private immutable {
// Client Identifier
string clientId = "22c49a0d-d21c-4792-aed1-8f163c982546";
// Personal & Business Queries
string authUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
string redirectUrl = "https://login.microsoftonline.com/common/oauth2/nativeclient";
string tokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
string driveByIdUrl = "https://graph.microsoft.com/v1.0/drives/";
// Office 365 / SharePoint Queries
string siteSearchUrl = "https://graph.microsoft.com/v1.0/sites?search";
string siteDriveUrl = "https://graph.microsoft.com/v1.0/sites/";
}
private {
@ -303,6 +310,22 @@ final class OneDriveApi
return get(uploadUrl, true);
}
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/site_search?view=odsp-graph-online
JSONValue o365SiteSearch(string o365SharedLibraryName){
checkAccessTokenExpired();
const(char)[] url;
url = siteSearchUrl ~ "=" ~ o365SharedLibraryName;
return get(url);
}
// https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/drive_list?view=odsp-graph-online
JSONValue o365SiteDrives(string site_id){
checkAccessTokenExpired();
const(char)[] url;
url = siteDriveUrl ~ site_id ~ "/drives";
return get(url);
}
private void redeemToken(const(char)[] authCode)
{
const(char)[] postData =

View file

@ -1708,4 +1708,37 @@ final class SyncEngine
// Make the change on OneDrive
auto res = onedrive.moveByPath(sourcePath, moveData);
}
// Query Office 365 SharePoint Shared Library site to obtain it's Drive ID
void querySiteCollectionForDriveID(string o365SharedLibraryName){
// Steps to get the ID:
// 1. Query https://graph.microsoft.com/v1.0/sites?search= with the name entered
// 2. Evaluate the response. A valid response will contain the description and the id. If the response comes back with nothing, the site name cannot be found or no access
// 3. If valid, use the returned ID and query the site drives
// https://graph.microsoft.com/v1.0/sites/<site_id>/drives
// 4. Display Shared Library Name & Drive ID
string site_id;
string drive_id;
JSONValue siteQuery = onedrive.o365SiteSearch(o365SharedLibraryName);
foreach (searchResult; siteQuery["value"].array) {
// Need an 'exclusive' match here with as entered
if (o365SharedLibraryName == searchResult["description"].str){
// 'description' matches search request
site_id = searchResult["id"].str;
JSONValue siteDriveQuery = onedrive.o365SiteDrives(site_id);
foreach (driveResult; siteDriveQuery["value"].array) {
drive_id = driveResult["id"].str;
}
}
}
log.log("Office 365 Library Name: ", o365SharedLibraryName);
if(drive_id != null) {
log.log("drive_id: ", drive_id);
} else {
writeln("ERROR: This site could not be found. Please check it's name and your permissions to access the site.");
}
}
}