Skip to content

Commit 352c94e

Browse files
SharePoint API: introduced SearchService API support, bug fixes (#210 and #213)
1 parent 45f90b2 commit 352c94e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+507
-135
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,3 @@ jobs:
3434
tags: true
3535
python: 3.6
3636
repo: "vgrem/Office365-REST-Python-Client"
37-
twine_version: 3.1.1
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<AppPermissionRequests AllowAppOnlyPolicy="true">
2-
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="Read"/>
2+
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection" Right="FullControl" />
3+
<AppPermissionRequest Scope="http://sharepoint/search" Right="QueryAsUserIgnoreAppPrincipal"/>
34
</AppPermissionRequests>

examples/sharepoint/connect_with_app.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
from office365.sharepoint.client_context import ClientContext
33
from settings import settings
44

5-
ctx = ClientContext.connect_with_credentials(settings['url'],
6-
ClientCredential(settings['client_credentials']['client_id'],
7-
settings['client_credentials']['client_secret']))
5+
credentials = ClientCredential(settings['client_credentials']['client_id'],
6+
settings['client_credentials']['client_secret'])
7+
ctx = ClientContext(settings['url']).with_credentials(credentials)
8+
if not ctx.authentication_context.acquire_token():
9+
print("Acquire token failed")
10+
811

912
target_web = ctx.web
1013
ctx.load(target_web)
1114
ctx.execute_query()
12-
13-
15+
print(target_web.url)

examples/sharepoint/requirements.txt

Whitespace-only changes.

generator/generate.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import ast
2-
1+
from generator.typeBuilder import TypeBuilder
32
from office365.runtime.odata.odata_v3_reader import ODataV3Reader
43
from office365.runtime.odata.odata_v4_reader import ODataV4Reader
54

@@ -10,9 +9,9 @@ def generate_files(model):
109

1110

1211
def generate_type_file(type_schema):
13-
if type_schema['state'] == 'attached':
14-
tree = ast.parse(open(type_schema['file']).read())
15-
print(type_schema['file'])
12+
builder = TypeBuilder(type_schema)
13+
if builder.build():
14+
builder.save()
1615

1716

1817
def generate_sharepoint_model():

generator/metadata/SharePoint.xml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

generator/templates/__init__.py

Whitespace-only changes.

generator/typeBuilder.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import ast
2+
import astunparse
3+
4+
5+
class TypeBuilder(object):
6+
7+
def __init__(self, schema):
8+
self._schema = schema
9+
self._node = None
10+
11+
def build(self):
12+
if self._schema['state'] == 'attached':
13+
with open(self._schema['file']) as f:
14+
self._node = ast.parse(f.read())
15+
return True
16+
return False
17+
18+
def save(self):
19+
code = astunparse.unparse(self._node)
20+
with open(self._schema['file']) as f:
21+
f.write(code)

office365/outlookservices/outlook_client.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,38 @@
1010

1111
class OutlookClient(ClientRuntimeContext):
1212

13-
def __init__(self, ctx_auth):
13+
def __init__(self, auth_context):
1414
"""
1515
Office365 Outlook client context
1616
Status: deprecated, prefer GraphClient instead
1717
18-
:type ctx_auth: AuthenticationContext
18+
:type auth_context: AuthenticationContext
1919
"""
20-
self.__service_root_url = "https://outlook.office365.com/api/v1.0/"
21-
super(OutlookClient, self).__init__(self.__service_root_url, ctx_auth)
20+
self._resource = "https://outlook.office365.com"
21+
self.__service_root_url = "{resource}/api/v1.0/".format(resource=self._resource)
22+
super(OutlookClient, self).__init__(self.__service_root_url, auth_context)
2223
self._pendingRequest = ODataRequest(self, V4JsonFormat("minimal"))
2324
self._pendingRequest.beforeExecute += self._build_specific_query
25+
self._token_parameters = None
26+
27+
@classmethod
28+
def from_tenant(cls, tenant):
29+
return OutlookClient(AuthenticationContext(tenant))
30+
31+
def with_user_credentials(self, client_id, user_name, password):
32+
self._token_parameters = {
33+
"client_id": client_id,
34+
"username": user_name,
35+
"password": password,
36+
"resource": self._resource,
37+
"scope": ("openid", "profile", "offline_access")
38+
}
39+
return self
40+
41+
def authenticate_request(self, request):
42+
if not self._auth_context.is_authenticated:
43+
self._auth_context.acquire_token_password_grant(**self._token_parameters)
44+
super(OutlookClient, self).authenticate_request(request)
2445

2546
def get_pending_request(self):
2647
return self._pendingRequest

office365/runtime/auth/authentication_context.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class AuthenticationContext(BaseAuthenticationContext):
1212

1313
def __init__(self, url, credentials=None):
1414
"""
15-
Authentication context for SharePoint Online/One Drive
15+
Authentication context for SharePoint Online/OneDrive
1616
1717
:param str url: authority url
1818
:param ClientCredential or UserCredential credentials: credentials
@@ -33,9 +33,9 @@ def set_token(self, token):
3333

3434
def acquire_token(self):
3535
if isinstance(self.credentials, ClientCredential):
36-
self.acquire_token_for_app(self.credentials.clientId, self.credentials.clientSecret)
36+
return self.acquire_token_for_app(self.credentials.clientId, self.credentials.clientSecret)
3737
elif isinstance(self.credentials, UserCredential):
38-
self.acquire_token_for_user(self.credentials.userName, self.credentials.password)
38+
return self.acquire_token_for_user(self.credentials.userName, self.credentials.password)
3939
else:
4040
raise ValueError("Unknown credential type")
4141

@@ -48,19 +48,30 @@ def acquire_token_for_user(self, username, password):
4848
self.provider = SamlTokenProvider(self.url, username, password)
4949
if not self.provider.acquire_token():
5050
raise ValueError('Acquire token failed: {0}'.format(self.provider.error))
51+
return True
5152

5253
def acquire_token_for_app(self, client_id, client_secret):
5354
"""Acquire token via client credentials (SharePoint App Principal)"""
5455
self.provider = ACSTokenProvider(self.url, client_id, client_secret)
5556
if not self.provider.acquire_token():
5657
raise ValueError('Acquire token failed: {0}'.format(self.provider.error))
58+
return True
5759

58-
def acquire_token_password_grant(self, client_credentials, user_credentials):
59-
"""Acquire token via resource owner password credential (ROPC) grant"""
60+
def acquire_token_password_grant(self, client_id, username, password, resource, scope):
61+
"""
62+
Acquire token via resource owner password credential (ROPC) grant
63+
64+
:param str resource: A URI that identifies the resource for which the token is valid.
65+
:param str username: : The username of the user on behalf this application is authenticating.
66+
:param str password: The password of the user named in the username parameter.
67+
:param str client_id: str The OAuth client id of the calling application.
68+
:param list[str] scope:
69+
"""
6070
self.provider = OAuthTokenProvider(self.url)
61-
return self.provider.acquire_token_password_type("https://outlook.office365.com",
62-
client_credentials,
63-
user_credentials)
71+
return self.provider.acquire_token_password_type(resource=resource,
72+
client_id=client_id,
73+
user_credentials=UserCredential(username, password),
74+
scope=scope)
6475

6576
def authenticate_request(self, request_options):
6677
"""Authenticate request

0 commit comments

Comments
 (0)