Skip to content

Commit

Permalink
Examples & documentation updates
Browse files Browse the repository at this point in the history
  • Loading branch information
vgrem committed Jul 8, 2023
1 parent 1268e52 commit e8dde05
Show file tree
Hide file tree
Showing 40 changed files with 281 additions and 221 deletions.
91 changes: 60 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ pip install Office365-REST-Python-Client
>pip install git+https://github.com/vgrem/Office365-REST-Python-Client.git
>```

# Working with SharePoint API


## Authentication
# Authentication
For the following examples, relevant credentials can be found in the Azure Portal.

Steps to access:
Expand All @@ -49,42 +45,76 @@ Steps to access:
6. In the application's "Certificates & Secrets" page, the client secret can be found under the "Value" of the "Client Secrets." If there is no client secret yet, create one here.


The list of supported API versions:
- [SharePoint 2013 REST API](https://msdn.microsoft.com/en-us/library/office/jj860569.aspx) and above
- SharePoint Online & OneDrive for Business REST API
# Working with SharePoint API

#### Authentication
The `ClientContext` client provides the support for a legacy SharePoint REST and OneDrive for Business REST APIs,
the list of supported versions:
- [SharePoint 2013 REST API](https://msdn.microsoft.com/en-us/library/office/jj860569.aspx) and above
- [SharePoint Online REST API](https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service)
- OneDrive for Business REST API

### Authentication

The following auth flows are supported:
The following auth flows are supported:

- app principals flow:
`ClientContext.with_credentials(client_credentials)`
#### 1. Using a SharePoint App-Only principal (client credentials flow)

This auth method is compatible with SharePoint on-premises and still relevant
model in both SharePoint on-premises as SharePoint Online,
the following methods are available:

- `ClientContext.with_credentials(client_credentials)`
- `ClientContext.with_client_credentials(client_id, client_secret)`

Usage:
```
client_credentials = ClientCredential('{client_id}','{client_secret}')
ctx = ClientContext('{url}').with_credentials(client_credentials)
```
Documentation: refer [Granting access using SharePoint App-Only](https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azureacs) for a details
Usage:
```
client_credentials = ClientCredential('{client_id}','{client_secret}')
ctx = ClientContext('{url}').with_credentials(client_credentials)
```

Documentation:
- [Granting access using SharePoint App-Only](https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azureacs)
- [wiki](https://github.com/vgrem/Office365-REST-Python-Client/wiki/How-to-connect-to-SharePoint-Online-and-and-SharePoint-2013-2016-2019-on-premises--with-app-principal)

Example: [connect_with_app_principal.py](examples/sharepoint/connect_with_app_only_principal.py)
Example: [connect_with_app_principal.py](examples/sharepoint/connect_with_app_only_principal.py)

- user credentials flow: `ClientContext.with_credentials(user_credentials)`
#### 2. Using username and password

Usage:
```
user_credentials = UserCredential('{username}','{password}')
ctx = ClientContext('{url}').with_credentials(user_credentials)
```
Example: [connect_with_user_credential.py](examples/sharepoint/connect_with_user_credential.py)
Usage:
```
user_credentials = UserCredential('{username}','{password}')
ctx = ClientContext('{url}').with_credentials(user_credentials)
```

Example: [connect_with_user_credential.py](examples/sharepoint/connect_with_user_credential.py)

- certificate credentials flow: `ClientContext.with_certificate(tenant, client_id, thumbprint, cert_path)`
#### 3. Using an Azure AD application (certificate credentials flow)

Documentation: [Granting access via Azure AD App-Only](https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread)
Documentation:
- [Granting access via Azure AD App-Only](https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread)
- [wiki](https://github.com/vgrem/Office365-REST-Python-Client/wiki/How-to-connect-to-SharePoint-Online-with-certificate-credentials)

Example: [connect_with_client_certificate.py](examples/sharepoint/connect_with_client_certificate.py)

#### Examples
#### 4. interactive

to login interactively i.e. via a local browser

Prerequisite:

> In Azure Portal, configure the Redirect URI of your
"Mobile and Desktop application" as ``http://localhost``.

Example: [connect_interactive.py](examples/sharepoint/connect_interactive.py)

Usage:
```python
ctx = ClientContext(site_url).with_interactive(tenant_name_or_id, client_id)
me = ctx.web.current_user.get().execute_query()
print(me.login_name)
```

### Examples

There are **two approaches** available to perform API queries:

Expand Down Expand Up @@ -130,7 +160,6 @@ web_title = json['d']['Title']
print("Web title: {0}".format(web_title))
```


The list of examples:

- Working with files
Expand Down Expand Up @@ -160,7 +189,7 @@ the following clients are available:
~~- `OutlookClient` which targets Outlook API `v1.0` version (not recommended for usage since `v1.0` version is being deprecated.)~~


#### Authentication
### Authentication

[The Microsoft Authentication Library (MSAL) for Python](https://pypi.org/project/msal/) which comes as a dependency
is used as a default library to obtain tokens to call Microsoft Graph API.
Expand Down
32 changes: 0 additions & 32 deletions examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +0,0 @@
import os

import msal

from tests import load_settings

settings = load_settings()

# aliases
sample_client_id = settings.get('client_credentials', 'client_id')
sample_client_secret = settings.get('client_credentials', 'client_secret')
sample_user_principal_name = settings.get('users', 'test_user1')
sample_user_principal_name_alt = settings.get('users', 'test_user2')
sample_tenant_prefix = settings.get('default', 'tenant_prefix')
sample_tenant_name = settings.get('default', 'tenant')
sample_thumbprint = settings.get('certificate_credentials', 'thumbprint')
sample_cert_path = '{0}/selfsigncert.pem'.format(os.path.dirname(__file__))
sample_site_url = settings.get('default', 'site_url')
sample_username = settings.get('user_credentials', "username")
sample_password = settings.get('user_credentials', "password")


def acquire_token_by_username_password():
authority_url = 'https://login.microsoftonline.com/{0}'.format(sample_tenant_name)
app = msal.PublicClientApplication(
authority=authority_url,
client_id=sample_client_id
)
return app.acquire_token_by_username_password(username=settings.get('user_credentials', "username"),
password=settings.get('user_credentials', "password"),
scopes=["https://graph.microsoft.com/.default"])

11 changes: 5 additions & 6 deletions examples/auth/with_client_cert.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#certificates
"""

from examples import sample_tenant_name, sample_thumbprint, sample_cert_path
from office365.graph_client import GraphClient
from tests import test_client_id
from tests import test_client_id, test_tenant_name, test_cert_path, test_cert_thumbprint


def acquire_token():
with open(sample_cert_path, 'r') as f:
private_key = open(sample_cert_path).read()
with open(test_cert_path, 'r') as f:
private_key = open(test_cert_path).read()

authority_url = 'https://login.microsoftonline.com/{0}'.format(sample_tenant_name)
credentials = {"thumbprint": sample_thumbprint, "private_key": private_key}
authority_url = 'https://login.microsoftonline.com/{0}'.format(test_tenant_name)
credentials = {"thumbprint": test_cert_thumbprint, "private_key": private_key}
import msal
app = msal.ConfidentialClientApplication(
test_client_id,
Expand Down
6 changes: 3 additions & 3 deletions examples/onedrive/files/download_default.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Download the contents of a DriveItem (file)
https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http
https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0
"""
import os
import tempfile
Expand All @@ -12,10 +12,10 @@
client = GraphClient(acquire_token_by_username_password)
# 1. address file by path
# remote_path = "archive/countries.json"
remote_path = "archive/Sample.rtf"
remote_path = "archive/Financial Sample.xlsx"
remote_file = client.me.drive.root.get_by_path(remote_path)
# 2. download file content
with tempfile.TemporaryDirectory() as local_path:
with open(os.path.join(local_path, os.path.basename(remote_path)), 'wb') as local_file:
remote_file.download(local_file).execute_query()
print("File has been downloaded into {0}".format(local_file.name))
print("File has been downloaded into {0}".format(local_file.name))
8 changes: 6 additions & 2 deletions examples/onedrive/files/download_large.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""
Demonstrates how to download a large file
By default, file gets downloaded immediately.
The following example demonstrates how to download a large file without reading the whole content of a file
into memory.
"""

import os
Expand All @@ -9,7 +13,7 @@
from tests.graph_case import acquire_token_by_username_password


def print_download_progress(offset):
def print_progress(offset):
print("Downloaded '{0}' bytes...".format(offset))


Expand All @@ -19,5 +23,5 @@ def print_download_progress(offset):
# 2 download a large file (chunked file download)
with tempfile.TemporaryDirectory() as local_path:
with open(os.path.join(local_path, file_item.name), 'wb') as local_file:
file_item.download_session(local_file, print_download_progress, chunk_size=1024*512).execute_query()
file_item.download_session(local_file, print_progress, chunk_size=1024 * 512).execute_query()
print("File '{0}' has been downloaded into {1}".format(file_item.name, local_file.name))
3 changes: 2 additions & 1 deletion examples/onedrive/files/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

client = GraphClient(acquire_token_by_client_credentials)
folder = client.users.get_by_principal_name(test_user_principal_name_alt).drive.root.get_by_path("archive")
local_path = "../../../tests/data/SharePoint User Guide.docx"

local_path = "../../data/Financial Sample.xlsx"
file = folder.upload_file(local_path).execute_query()
print(f"File {file.web_url} has been uploaded")
7 changes: 6 additions & 1 deletion examples/onedrive/folders/download_files.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
Download the contents of the driveItem (folder facet)
https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0
"""

import os
import tempfile

Expand All @@ -6,7 +12,6 @@
from tests.graph_case import acquire_token_by_username_password

client = GraphClient(acquire_token_by_username_password)
# address folder by path
folder_item = client.me.drive.root.get_by_path("archive").get().execute_query()

with tempfile.TemporaryDirectory() as local_path:
Expand Down
6 changes: 5 additions & 1 deletion examples/outlook/events/delete.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from examples import acquire_token_by_username_password
"""
"""

from office365.graph_client import GraphClient
from office365.outlook.calendar.events.event import Event
from tests.graph_case import acquire_token_by_username_password

client = GraphClient(acquire_token_by_username_password)
event_id = '--event id goes here--'
Expand Down
7 changes: 6 additions & 1 deletion examples/outlook/events/list.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from examples import acquire_token_by_username_password
"""
Retrieve a list of events in a my calendar.
https://learn.microsoft.com/en-us/graph/api/calendar-list-events?view=graph-rest-1.0
"""
from office365.graph_client import GraphClient
from office365.outlook.calendar.events.event import Event
from tests.graph_case import acquire_token_by_username_password

client = GraphClient(acquire_token_by_username_password)
events = client.me.calendar.events.get_all().select(["subject", "body"]).execute_query()
Expand Down
2 changes: 1 addition & 1 deletion examples/outlook/messages/send_with_large_attachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
https://learn.microsoft.com/en-us/graph/api/attachment-createuploadsession?view=graph-rest-1.0
"""

from examples import acquire_token_by_username_password
from office365.graph_client import GraphClient
from tests.graph_case import acquire_token_by_username_password

client = GraphClient(acquire_token_by_username_password)

Expand Down
2 changes: 1 addition & 1 deletion examples/planner/create_task.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from examples import acquire_token_by_username_password
from office365.graph_client import GraphClient
from office365.planner.plans.plan import PlannerPlan
from tests.graph_case import acquire_token_by_username_password


def ensure_plan(planner, name):
Expand Down
10 changes: 5 additions & 5 deletions examples/sharepoint/connect_with_client_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@

import os

from examples import sample_client_id, sample_tenant_name, sample_thumbprint, sample_site_url
from office365.sharepoint.client_context import ClientContext
from tests import test_client_id, test_tenant_name, test_site_url, test_cert_thumbprint

cert_credentials = {
'tenant': sample_tenant_name,
'client_id': sample_client_id,
'thumbprint': sample_thumbprint,
'tenant': test_tenant_name,
'client_id': test_client_id,
'thumbprint': test_cert_thumbprint,
'cert_path': '{0}/selfsigncert.pem'.format(os.path.dirname(__file__)),
}
ctx = ClientContext(sample_site_url).with_client_certificate(**cert_credentials)
ctx = ClientContext(test_site_url).with_client_certificate(**cert_credentials)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))
29 changes: 23 additions & 6 deletions examples/sharepoint/connect_with_client_certificate_private_key.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
"""
Prerequisites:
Setting up an Azure AD app for app-only access:
- create a self signed certificate
- register an Azure AD application in the Azure Active Directory tenant that is linked to your Office 365 tenant
- grant the permissions once application is registered, for instance choose:
SharePoint
Application permissions
Sites
Sites.FullControl.All
- and finally upload the certificate to the application
Refer this article for a detailed instruction:
https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread
"""

import os

from examples import sample_tenant_name, sample_client_id, sample_thumbprint, sample_site_url
from office365.sharepoint.client_context import ClientContext

from tests import test_client_id, test_cert_thumbprint, test_site_url, test_tenant_name

cert_path = '{0}/selfsigncert.pem'.format(os.path.dirname(__file__))
with open(cert_path, 'r') as f:
private_key = open(cert_path).read()

cert_credentials = {
'tenant': sample_tenant_name,
'client_id': sample_client_id,
'thumbprint': sample_thumbprint,
'tenant': test_tenant_name,
'client_id': test_client_id,
'thumbprint': test_cert_thumbprint,
'private_key': private_key
}
ctx = ClientContext(sample_site_url).with_client_certificate(**cert_credentials)
ctx = ClientContext(test_site_url).with_client_certificate(**cert_credentials)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))
15 changes: 9 additions & 6 deletions examples/sharepoint/connect_with_client_certificate_scopes.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"""
"""
import os

from examples import sample_client_id, sample_thumbprint, sample_tenant_name, sample_site_url
from office365.sharepoint.client_context import ClientContext
from tests import test_tenant_name, test_client_id, test_cert_thumbprint, test_site_url

cert_credentials = {
'tenant': sample_tenant_name,
'client_id': sample_client_id,
'thumbprint': sample_thumbprint,
'tenant': test_tenant_name,
'client_id': test_client_id,
'thumbprint': test_cert_thumbprint,
'cert_path': '{0}/selfsigncert.pem'.format(os.path.dirname(__file__)),
'scopes': ['{0}/.default'.format(sample_site_url)]
'scopes': ['{0}/.default'.format(test_site_url)]
}

ctx = ClientContext(sample_site_url).with_client_certificate(**cert_credentials)
ctx = ClientContext(test_site_url).with_client_certificate(**cert_credentials)
current_web = ctx.web.get().execute_query()
print("{0}".format(current_web.url))
Loading

0 comments on commit e8dde05

Please sign in to comment.