Skip to content

Commit

Permalink
Examples & documentation updates, fix for SiteProperties type
Browse files Browse the repository at this point in the history
  • Loading branch information
vgrem committed Jul 8, 2023
1 parent 9b866ef commit 1268e52
Show file tree
Hide file tree
Showing 17 changed files with 203 additions and 56 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ pip install Office365-REST-Python-Client
>pip install git+https://github.com/vgrem/Office365-REST-Python-Client.git
>```
# Authentication Credentials

# Working with SharePoint API


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

Steps to access:
Expand All @@ -44,7 +48,6 @@ Steps to access:
5. In the application's "Overview" page, the client id can be found under "Application (client) id"
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.

# Working with SharePoint API

The list of supported API versions:
- [SharePoint 2013 REST API](https://msdn.microsoft.com/en-us/library/office/jj860569.aspx) and above
Expand Down
10 changes: 0 additions & 10 deletions examples/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@
sample_password = settings.get('user_credentials', "password")


def acquire_token_by_client_credentials():
authority_url = 'https://login.microsoftonline.com/{0}'.format(sample_tenant_name)
app = msal.ConfidentialClientApplication(
authority=authority_url,
client_id=sample_client_id,
client_credential=settings.get('client_credentials', 'client_secret')
)
return app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])


def acquire_token_by_username_password():
authority_url = 'https://login.microsoftonline.com/{0}'.format(sample_tenant_name)
app = msal.PublicClientApplication(
Expand Down
6 changes: 5 additions & 1 deletion examples/onenote/create_page.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
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
22 changes: 18 additions & 4 deletions examples/sharepoint/connect_with_app_only_principal.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
"""
Example: SharePoint App-Only auth flow
There are two approaches for doing app-only for SharePoint:
- Using an Azure AD application: this is the preferred method when using SharePoint Online because you can also
grant permissions to other Office 365 services (if needed) + you’ve a user interface (Azure portal) to maintain
your app principals.
- Using a SharePoint App-Only principal: this method is older and only works for SharePoint access,
but is still relevant. This method is also the recommended model when you’re still working in SharePoint
on-premises since this model works in both SharePoint on-premises as SharePoint Online.
Important:
Please safeguard the created client id/secret combination as would it be your administrator account.
Using this client id/secret one can read/update all data in your SharePoint Online environment!
The example demonstrates how to use SharePoint App-Only principal (second option)
https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azureacs
"""
from examples import sample_site_url, sample_client_id, sample_client_secret
from office365.runtime.auth.client_credential import ClientCredential
from office365.sharepoint.client_context import ClientContext
from tests import test_site_url, test_client_id, test_client_secret

ctx = ClientContext(sample_site_url).with_credentials(ClientCredential(sample_client_id, sample_client_secret))
ctx = ClientContext(test_site_url).with_client_credentials(test_client_id, test_client_secret)
target_web = ctx.web.get().execute_query()
print(target_web.url)
7 changes: 6 additions & 1 deletion examples/sharepoint/connect_with_client_certificate.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"""
Example: Azure AD App-Only auth flow
When using SharePoint Online you can define applications in Azure AD and these applications can
be granted permissions to SharePoint, but also to all the other services in Office 365.
This model is the preferred model in case you're using SharePoint Online, if you're using SharePoint on-premises
you have to use the SharePoint Only model via based Azure ACS as described in here:
Demonstrates how to use Azure AD App-Only auth flow
https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread
"""
Expand Down
19 changes: 16 additions & 3 deletions examples/sharepoint/tenant/allow_custom_script.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
"""
Allow or prevent custom script
Demonstrates how to determine whether custom script on SharePoint site is enabled and enable it if disabled
https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script
"""

from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.tenant.administration.deny_add_and_customize_pages_status import \
DenyAddAndCustomizePagesStatus
from tests import test_admin_site_url, test_admin_credentials, test_team_site_url

client = ClientContext(test_admin_site_url).with_credentials(test_admin_credentials)
site_props = client.tenant.get_site_properties_by_url(test_team_site_url, True).execute_query()
if site_props.deny_add_and_customize_pages:
if site_props.deny_add_and_customize_pages == DenyAddAndCustomizePagesStatus.Disabled:
print("Enabling custom script on site: {0}...".format(test_team_site_url))
site_props.deny_add_and_customize_pages = False
site_props.deny_add_and_customize_pages = DenyAddAndCustomizePagesStatus.Enabled
site_props.update().execute_query()
print("Done.")
elif site_props.deny_add_and_customize_pages == DenyAddAndCustomizePagesStatus.Enabled:
print("Skipping. Custom script has already been allowed on site: {0}".format(test_team_site_url))
else:
print("Custom script has already been allowed on site: {0}".format(test_team_site_url))
print("Unknown status detected")
6 changes: 3 additions & 3 deletions generator/import_metadata.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from xml.dom import minidom
from argparse import ArgumentParser

from examples import acquire_token_by_client_credentials
from office365.graph_client import GraphClient
from office365.sharepoint.client_context import ClientContext
from tests import test_site_url, test_client_credentials
from tests.graph_case import acquire_token_by_client_credentials


def export_to_file(path, content):
Expand All @@ -15,9 +15,9 @@ def export_to_file(path, content):

parser = ArgumentParser()
parser.add_argument("-e", "--endpoint", dest="endpoint",
help="Import metadata endpoint", default="sharepoint")
help="Import metadata endpoint", default="microsoftgraph")
parser.add_argument("-p", "--path",
dest="path", default="./metadata/SharePoint.xml",
dest="path", default="./metadata/MicrosoftGraph.xml",
help="Import metadata endpoint")

args = parser.parse_args()
Expand Down
99 changes: 98 additions & 1 deletion generator/metadata/MicrosoftGraph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20276,6 +20276,10 @@
<NavigationProperty Name="assignments" Type="Collection(graph.accessPackageAssignment)" ContainsTarget="true"/>
<NavigationProperty Name="catalogs" Type="Collection(graph.accessPackageCatalog)" ContainsTarget="true"/>
<NavigationProperty Name="connectedOrganizations" Type="Collection(graph.connectedOrganization)" ContainsTarget="true"/>
<NavigationProperty Name="resourceEnvironments" Type="Collection(graph.accessPackageResourceEnvironment)" ContainsTarget="true"/>
<NavigationProperty Name="resourceRequests" Type="Collection(graph.accessPackageResourceRequest)" ContainsTarget="true"/>
<NavigationProperty Name="resourceRoleScopes" Type="Collection(graph.accessPackageResourceRoleScope)" ContainsTarget="true"/>
<NavigationProperty Name="resources" Type="Collection(graph.accessPackageResource)" ContainsTarget="true"/>
<NavigationProperty Name="settings" Type="graph.entitlementManagementSettings" ContainsTarget="true"/>
</EntityType>
<EntityType Name="user" BaseType="graph.directoryObject" OpenType="true">
Expand Down Expand Up @@ -25218,6 +25222,7 @@
<NavigationProperty Name="catalog" Type="graph.accessPackageCatalog"/>
<NavigationProperty Name="incompatibleAccessPackages" Type="Collection(graph.accessPackage)"/>
<NavigationProperty Name="incompatibleGroups" Type="Collection(graph.group)" ContainsTarget="true"/>
<NavigationProperty Name="resourceRoleScopes" Type="Collection(graph.accessPackageResourceRoleScope)" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageAssignmentPolicy" BaseType="graph.entity">
<Property Name="allowedTargetScope" Type="graph.allowedTargetScope"/>
Expand Down Expand Up @@ -25269,6 +25274,9 @@
<Property Name="state" Type="graph.accessPackageCatalogState"/>
<NavigationProperty Name="accessPackages" Type="Collection(graph.accessPackage)" ContainsTarget="true"/>
<NavigationProperty Name="customWorkflowExtensions" Type="Collection(graph.customCalloutExtension)" ContainsTarget="true"/>
<NavigationProperty Name="resourceRoles" Type="Collection(graph.accessPackageResourceRole)" ContainsTarget="true"/>
<NavigationProperty Name="resources" Type="Collection(graph.accessPackageResource)" ContainsTarget="true"/>
<NavigationProperty Name="resourceScopes" Type="Collection(graph.accessPackageResourceScope)" ContainsTarget="true"/>
</EntityType>
<EntityType Name="connectedOrganization" BaseType="graph.entity">
<Property Name="createdDateTime" Type="Edm.DateTimeOffset"/>
Expand All @@ -25280,6 +25288,39 @@
<NavigationProperty Name="externalSponsors" Type="Collection(graph.directoryObject)" ContainsTarget="true"/>
<NavigationProperty Name="internalSponsors" Type="Collection(graph.directoryObject)" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageResourceEnvironment" BaseType="graph.entity">
<Property Name="createdDateTime" Type="Edm.DateTimeOffset"/>
<Property Name="description" Type="Edm.String"/>
<Property Name="displayName" Type="Edm.String"/>
<Property Name="isDefaultEnvironment" Type="Edm.Boolean"/>
<Property Name="modifiedDateTime" Type="Edm.DateTimeOffset"/>
<Property Name="originId" Type="Edm.String"/>
<Property Name="originSystem" Type="Edm.String"/>
<NavigationProperty Name="resources" Type="Collection(graph.accessPackageResource)" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageResourceRequest" BaseType="graph.entity">
<Property Name="createdDateTime" Type="Edm.DateTimeOffset"/>
<Property Name="requestType" Type="graph.accessPackageRequestType"/>
<Property Name="state" Type="graph.accessPackageRequestState"/>
<NavigationProperty Name="catalog" Type="graph.accessPackageCatalog" ContainsTarget="true"/>
<NavigationProperty Name="resource" Type="graph.accessPackageResource" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageResourceRoleScope" BaseType="graph.entity">
<Property Name="createdDateTime" Type="Edm.DateTimeOffset"/>
<NavigationProperty Name="role" Type="graph.accessPackageResourceRole" ContainsTarget="true"/>
<NavigationProperty Name="scope" Type="graph.accessPackageResourceScope" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageResource" BaseType="graph.entity">
<Property Name="createdDateTime" Type="Edm.DateTimeOffset"/>
<Property Name="description" Type="Edm.String"/>
<Property Name="displayName" Type="Edm.String"/>
<Property Name="modifiedDateTime" Type="Edm.DateTimeOffset"/>
<Property Name="originId" Type="Edm.String"/>
<Property Name="originSystem" Type="Edm.String"/>
<NavigationProperty Name="environment" Type="graph.accessPackageResourceEnvironment"/>
<NavigationProperty Name="roles" Type="Collection(graph.accessPackageResourceRole)" ContainsTarget="true"/>
<NavigationProperty Name="scopes" Type="Collection(graph.accessPackageResourceScope)" ContainsTarget="true"/>
</EntityType>
<EntityType Name="entitlementManagementSettings" BaseType="graph.entity">
<Property Name="durationUntilExternalUserDeletedAfterBlocked" Type="Edm.Duration"/>
<Property Name="externalUserLifecycleAction" Type="graph.accessPackageExternalUserLifecycleAction"/>
Expand Down Expand Up @@ -25677,6 +25718,21 @@
<Property Name="lastModifiedBy" Type="Edm.String"/>
<Property Name="lastModifiedDateTime" Type="Edm.DateTimeOffset"/>
</EntityType>
<EntityType Name="accessPackageResourceRole" BaseType="graph.entity">
<Property Name="description" Type="Edm.String"/>
<Property Name="displayName" Type="Edm.String"/>
<Property Name="originId" Type="Edm.String"/>
<Property Name="originSystem" Type="Edm.String"/>
<NavigationProperty Name="resource" Type="graph.accessPackageResource" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageResourceScope" BaseType="graph.entity">
<Property Name="description" Type="Edm.String"/>
<Property Name="displayName" Type="Edm.String"/>
<Property Name="isRootScope" Type="Edm.Boolean"/>
<Property Name="originId" Type="Edm.String"/>
<Property Name="originSystem" Type="Edm.String"/>
<NavigationProperty Name="resource" Type="graph.accessPackageResource" ContainsTarget="true"/>
</EntityType>
<EntityType Name="accessPackageMultipleChoiceQuestion" BaseType="graph.accessPackageQuestion">
<Property Name="choices" Type="Collection(graph.accessPackageAnswerChoice)"/>
<Property Name="isMultipleSelectionAllowed" Type="Edm.Boolean"/>
Expand Down Expand Up @@ -36154,6 +36210,19 @@
<Member Name="allCaseNoncustodialDataSources" Value="8"/>
<Member Name="unknownFutureValue" Value="16"/>
</EnumType>
<EnumType Name="exportFileStructure">
<Member Name="none" Value="0"/>
<Member Name="directory" Value="1"/>
<Member Name="pst" Value="2"/>
<Member Name="unknownFutureValue" Value="3"/>
</EnumType>
<EnumType Name="exportOptions" IsFlags="true">
<Member Name="originalFiles" Value="1"/>
<Member Name="text" Value="2"/>
<Member Name="pdfReplacement" Value="4"/>
<Member Name="tags" Value="16"/>
<Member Name="unknownFutureValue" Value="32"/>
</EnumType>
<EnumType Name="purgeAreas" IsFlags="true">
<Member Name="mailboxes" Value="1"/>
<Member Name="teamsMessages" Value="2"/>
Expand Down Expand Up @@ -36467,6 +36536,11 @@
<NavigationProperty Name="passiveDnsRecords" Type="Collection(microsoft.graph.security.passiveDnsRecord)" ContainsTarget="true"/>
<NavigationProperty Name="vulnerabilities" Type="Collection(microsoft.graph.security.vulnerability)" ContainsTarget="true"/>
</EntityType>
<ComplexType Name="exportFileMetadata">
<Property Name="downloadUrl" Type="Edm.String"/>
<Property Name="fileName" Type="Edm.String"/>
<Property Name="size" Type="Edm.Int64"/>
</ComplexType>
<ComplexType Name="ocrSettings">
<Property Name="isEnabled" Type="Edm.Boolean"/>
<Property Name="maxImageSize" Type="Edm.Int32"/>
Expand Down Expand Up @@ -36607,9 +36681,18 @@
<Property Name="unindexedItemsSize" Type="Edm.Int64"/>
<NavigationProperty Name="search" Type="microsoft.graph.security.ediscoverySearch"/>
</EntityType>
<EntityType Name="ediscoveryExportOperation" BaseType="microsoft.graph.security.caseOperation">
<Property Name="description" Type="Edm.String"/>
<Property Name="exportFileMetadata" Type="Collection(microsoft.graph.security.exportFileMetadata)"/>
<Property Name="exportOptions" Type="microsoft.graph.security.exportOptions"/>
<Property Name="exportStructure" Type="microsoft.graph.security.exportFileStructure"/>
<Property Name="outputName" Type="Edm.String"/>
<NavigationProperty Name="reviewSet" Type="microsoft.graph.security.ediscoveryReviewSet"/>
<NavigationProperty Name="reviewSetQuery" Type="microsoft.graph.security.ediscoveryReviewSetQuery"/>
</EntityType>
<EntityType Name="ediscoveryReviewSetQuery" BaseType="microsoft.graph.security.search"/>
<EntityType Name="ediscoveryHoldOperation" BaseType="microsoft.graph.security.caseOperation"/>
<EntityType Name="ediscoveryPurgeDataOperation" BaseType="microsoft.graph.security.caseOperation"/>
<EntityType Name="ediscoveryReviewSetQuery" BaseType="microsoft.graph.security.search"/>
<EntityType Name="ediscoveryTagOperation" BaseType="microsoft.graph.security.caseOperation"/>
<ComplexType Name="alertComment">
<Property Name="comment" Type="Edm.String"/>
Expand Down Expand Up @@ -37021,6 +37104,20 @@
<Parameter Name="search" Type="microsoft.graph.security.ediscoverySearch"/>
<Parameter Name="additionalDataOptions" Type="microsoft.graph.security.additionalDataOptions"/>
</Action>
<Action Name="export" IsBound="true">
<Parameter Name="bindingParameter" Type="microsoft.graph.security.ediscoveryReviewSet"/>
<Parameter Name="outputName" Type="Edm.String" Unicode="false"/>
<Parameter Name="description" Type="Edm.String" Unicode="false"/>
<Parameter Name="exportOptions" Type="microsoft.graph.security.exportOptions"/>
<Parameter Name="exportStructure" Type="microsoft.graph.security.exportFileStructure"/>
</Action>
<Action Name="export" IsBound="true">
<Parameter Name="bindingParameter" Type="microsoft.graph.security.ediscoveryReviewSetQuery"/>
<Parameter Name="outputName" Type="Edm.String" Unicode="false"/>
<Parameter Name="description" Type="Edm.String" Unicode="false"/>
<Parameter Name="exportOptions" Type="microsoft.graph.security.exportOptions"/>
<Parameter Name="exportStructure" Type="microsoft.graph.security.exportFileStructure"/>
</Action>
<Action Name="applyTags" IsBound="true">
<Parameter Name="bindingParameter" Type="microsoft.graph.security.ediscoveryReviewSetQuery"/>
<Parameter Name="tagsToAdd" Type="Collection(microsoft.graph.security.ediscoveryReviewTag)"/>
Expand Down
4 changes: 2 additions & 2 deletions office365/runtime/auth/client_credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ def __init__(self, client_id, client_secret):
"""
Client credentials
:type client_secret: str
:type client_id: str
:param str client_secret:
:param str client_id:
"""
self.clientId = client_id
self.clientSecret = client_secret
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from office365.runtime.paths.resource_path import ResourcePath


class EntityPath(ResourcePath):
"""Path for addressing a single SharePoint entity"""
class KeyPath(ResourcePath):
"""Path for addressing a single entity by key"""

@property
def segment(self):
if isinstance(self.key, int):
if self.key is None:
return "(<key>)"
elif isinstance(self.key, int):
return "({0})".format(self.key)
return "('{0}')".format(self.key)

Expand Down
Loading

0 comments on commit 1268e52

Please sign in to comment.