Office365-REST-Python-Client 2.5.14__py3-none-any.whl → 2.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/METADATA +2 -2
  2. {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/RECORD +210 -112
  3. office365/admin/__init__.py +0 -0
  4. office365/admin/admin.py +69 -0
  5. office365/admin/microsoft365_apps.py +5 -0
  6. office365/admin/people_settings.py +5 -0
  7. office365/admin/report_settings.py +5 -0
  8. office365/{onedrive → admin}/sharepoint.py +1 -1
  9. office365/azure_env.py +60 -0
  10. office365/directory/applications/app_ids.py +6 -0
  11. office365/directory/authentication/authentication.py +16 -0
  12. office365/directory/authentication/method_target.py +2 -1
  13. office365/directory/authentication/methods/microsoft_authenticator.py +6 -0
  14. office365/directory/authentication/methods/root.py +11 -0
  15. office365/directory/authentication/methods/sms.py +9 -0
  16. office365/directory/certificates/self_signed.py +31 -2
  17. office365/directory/identities/conditional_access_root.py +14 -0
  18. office365/directory/identitygovernance/privilegedaccess/approval.py +8 -0
  19. office365/directory/identitygovernance/privilegedaccess/group.py +30 -0
  20. office365/directory/identitygovernance/privilegedaccess/group_assignment_schedule_instance.py +7 -0
  21. office365/directory/identitygovernance/privilegedaccess/unified_role_assignment_schedule_request.py +7 -0
  22. office365/directory/identitygovernance/userconsent/request_collection.py +10 -0
  23. office365/directory/identitygovernance/workflow/__init__.py +0 -0
  24. office365/directory/identitygovernance/workflow/base.py +5 -0
  25. office365/directory/policies/cross_tenant_access.py +13 -0
  26. office365/directory/policies/feature_rollout.py +16 -0
  27. office365/directory/policies/root.py +39 -23
  28. office365/directory/policies/template.py +5 -0
  29. office365/directory/protection/threatassessment/email_file_request.py +20 -0
  30. office365/directory/protection/threatassessment/request.py +25 -0
  31. office365/directory/rolemanagement/application.py +15 -0
  32. office365/directory/rolemanagement/resource_action.py +8 -4
  33. office365/directory/rolemanagement/role_permission.py +3 -3
  34. office365/directory/security/alerts/collection.py +49 -0
  35. office365/directory/security/scorecontrol/__init__.py +0 -0
  36. office365/directory/security/scorecontrol/profile.py +6 -0
  37. office365/directory/security/security.py +17 -4
  38. office365/directory/serviceprincipals/service_principal.py +36 -28
  39. office365/directory/tenantinformation/__init__.py +0 -0
  40. office365/directory/tenantinformation/multi_organization.py +11 -0
  41. office365/directory/tenantinformation/relationship.py +61 -0
  42. office365/directory/users/insights_settings.py +5 -0
  43. office365/graph_client.py +52 -132
  44. office365/graph_request.py +78 -19
  45. office365/intune/servicecommunications/health/health.py +1 -1
  46. office365/intune/servicecommunications/issues/issue.py +2 -2
  47. office365/onedrive/columns/definition.py +1 -1
  48. office365/onedrive/contenttypes/content_type.py +1 -1
  49. office365/onedrive/driveitems/driveItem.py +13 -1
  50. office365/onedrive/drives/drive.py +1 -1
  51. office365/onedrive/filestorage/__init__.py +0 -0
  52. office365/onedrive/filestorage/container.py +7 -0
  53. office365/onedrive/filestorage/file_storage.py +20 -0
  54. office365/onedrive/listitems/field_value_set.py +1 -1
  55. office365/onedrive/listitems/list_item.py +1 -1
  56. office365/onedrive/lists/list.py +1 -1
  57. office365/onedrive/recyclebin/__init__.py +0 -0
  58. office365/onedrive/recyclebin/item.py +6 -0
  59. office365/onedrive/recyclebin/recyclebin.py +29 -0
  60. office365/onedrive/recyclebin/settings.py +13 -0
  61. office365/onedrive/shares/drive_item.py +1 -1
  62. office365/onedrive/sitepages/base.py +1 -1
  63. office365/onedrive/sitepages/canvas_layout.py +2 -2
  64. office365/onedrive/sitepages/sections/__init__.py +0 -0
  65. office365/onedrive/sitepages/{horizontal_section.py → sections/horizontal.py} +1 -1
  66. office365/onedrive/sitepages/webparts/data.py +5 -0
  67. office365/onedrive/sitepages/webparts/position.py +5 -0
  68. office365/onedrive/sitepages/webparts/standard.py +9 -0
  69. office365/onedrive/sitepages/webparts/web_part.py +12 -0
  70. office365/onedrive/sites/site.py +1 -1
  71. office365/onedrive/storage/storage.py +10 -0
  72. office365/onedrive/workbooks/charts/axes.py +41 -1
  73. office365/onedrive/workbooks/charts/axis.py +5 -0
  74. office365/onedrive/workbooks/charts/chart.py +64 -5
  75. office365/onedrive/workbooks/charts/fill.py +5 -0
  76. office365/onedrive/workbooks/charts/font.py +5 -0
  77. office365/onedrive/workbooks/charts/legend/__init__.py +0 -0
  78. office365/onedrive/workbooks/charts/legend/format.py +5 -0
  79. office365/onedrive/workbooks/charts/legend/legend.py +26 -0
  80. office365/onedrive/workbooks/charts/point.py +5 -0
  81. office365/onedrive/workbooks/charts/series/__init__.py +0 -0
  82. office365/onedrive/workbooks/charts/series/format.py +5 -0
  83. office365/onedrive/workbooks/charts/series/series.py +31 -0
  84. office365/onedrive/workbooks/charts/title.py +5 -0
  85. office365/onedrive/workbooks/filter.py +10 -0
  86. office365/onedrive/workbooks/filter_criteria.py +3 -3
  87. office365/onedrive/workbooks/ranges/fill.py +11 -1
  88. office365/onedrive/workbooks/ranges/range.py +26 -0
  89. office365/onedrive/workbooks/ranges/view.py +14 -0
  90. office365/onedrive/workbooks/sort_field.py +8 -3
  91. office365/onedrive/workbooks/tables/sort.py +20 -0
  92. office365/onedrive/workbooks/worksheets/worksheet.py +11 -0
  93. office365/partners/billing/azure_usage.py +17 -0
  94. office365/partners/billing/billed_usage.py +21 -0
  95. office365/partners/billing/billing.py +17 -0
  96. office365/partners/billing/operation.py +5 -0
  97. office365/partners/partners.py +17 -0
  98. office365/reports/root.py +9 -0
  99. office365/reports/userregistration/feature_summary.py +5 -0
  100. office365/runtime/auth/auth_cookies.py +48 -0
  101. office365/runtime/auth/authentication_context.py +36 -19
  102. office365/runtime/auth/entra/__init__.py +0 -0
  103. office365/runtime/auth/entra/authentication_context.py +165 -0
  104. office365/runtime/auth/providers/acs_token_provider.py +12 -27
  105. office365/runtime/auth/providers/saml_token_provider.py +41 -54
  106. office365/runtime/auth/sts_profile.py +8 -8
  107. office365/runtime/auth/token_response.py +4 -0
  108. office365/sharepoint/administration/custom_fonts_resource.py +5 -0
  109. office365/sharepoint/administration/sitemove/__init__.py +0 -0
  110. office365/sharepoint/administration/sitemove/service.py +68 -0
  111. office365/sharepoint/administration/sitemove/service_info.py +11 -0
  112. office365/sharepoint/changes/item.py +15 -0
  113. office365/sharepoint/client_context.py +61 -37
  114. office365/sharepoint/directory/group.py +2 -0
  115. office365/sharepoint/directory/helper.py +2 -0
  116. office365/sharepoint/directory/provider/provider.py +6 -0
  117. office365/sharepoint/directory/user.py +20 -0
  118. office365/sharepoint/files/publish/__init__.py +0 -0
  119. office365/sharepoint/files/publish/status.py +9 -0
  120. office365/sharepoint/flows/connector_result.py +17 -0
  121. office365/sharepoint/flows/permissions.py +11 -7
  122. office365/sharepoint/fontpackages/__init__.py +0 -0
  123. office365/sharepoint/fontpackages/collection.py +26 -0
  124. office365/sharepoint/fontpackages/creation_parameters.py +5 -0
  125. office365/sharepoint/fontpackages/font_package.py +5 -0
  126. office365/sharepoint/fontpackages/oob_settings.py +5 -0
  127. office365/sharepoint/forms/customization.py +26 -0
  128. office365/sharepoint/ir/__init__.py +0 -0
  129. office365/sharepoint/ir/migration.py +5 -0
  130. office365/sharepoint/lists/list.py +30 -0
  131. office365/sharepoint/marketplace/app_metadata.py +12 -1
  132. office365/sharepoint/marketplace/app_metadata_collection.py +8 -0
  133. office365/sharepoint/marketplace/corporatecuratedgallery/addins/instance_info.py +22 -0
  134. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_failed_info.py +5 -0
  135. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_info.py +12 -0
  136. office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_response.py +15 -0
  137. office365/sharepoint/marketplace/corporatecuratedgallery/addins/principals_response.py +5 -0
  138. office365/sharepoint/marketplace/corporatecuratedgallery/app_request_information.py +9 -0
  139. office365/sharepoint/marketplace/corporatecuratedgallery/app_response_information.py +9 -0
  140. office365/sharepoint/marketplace/corporatecuratedgallery/available_addins_response.py +4 -0
  141. office365/sharepoint/marketplace/corporatecuratedgallery/card_design.py +9 -0
  142. office365/sharepoint/marketplace/corporatecuratedgallery/card_designs.py +9 -0
  143. office365/sharepoint/marketplace/corporatecuratedgallery/teams_package_download.py +14 -0
  144. office365/sharepoint/marketplace/tenant/appcatalog/accessor.py +62 -3
  145. office365/sharepoint/multigeo/services.py +14 -0
  146. office365/sharepoint/multigeo/storage_quota.py +9 -0
  147. office365/sharepoint/policy/license_utilities.py +27 -0
  148. office365/sharepoint/principal/principal.py +6 -0
  149. office365/sharepoint/request.py +95 -10
  150. office365/sharepoint/search/administration/document_crawl_log.py +16 -2
  151. office365/sharepoint/search/administration/tenant_crawl_versions_info_provider.py +1 -1
  152. office365/sharepoint/search/reports/abandoned_queries.py +11 -1
  153. office365/sharepoint/search/reports/abandonedqueries/item.py +7 -1
  154. office365/sharepoint/sharing/domain_restriction_settings.py +5 -0
  155. office365/sharepoint/sharing/information.py +12 -0
  156. office365/sharepoint/sitehealth/result.py +4 -4
  157. office365/sharepoint/sitehealth/summary.py +5 -5
  158. office365/sharepoint/sites/copy_job_progress.py +5 -0
  159. office365/sharepoint/sites/copy_migration_iInfo.py +5 -0
  160. office365/sharepoint/sites/home/__init__.py +0 -0
  161. office365/sharepoint/sites/{sph_site.py → home/site.py} +1 -1
  162. office365/sharepoint/sites/site.py +26 -1
  163. office365/sharepoint/tenant/administration/app_service_principal_public.py +17 -0
  164. office365/sharepoint/tenant/administration/audit/data.py +12 -0
  165. office365/sharepoint/tenant/administration/audit/unified_record.py +18 -0
  166. office365/sharepoint/tenant/administration/coms/__init__.py +0 -0
  167. office365/sharepoint/tenant/administration/coms/messages_fields_data.py +5 -0
  168. office365/sharepoint/tenant/administration/coms/messages_service_proxy.py +16 -0
  169. office365/sharepoint/tenant/administration/copilot/__init__.py +0 -0
  170. office365/sharepoint/tenant/administration/copilot/adaptive_card_config.py +11 -0
  171. office365/sharepoint/tenant/administration/datagovernance/__init__.py +0 -0
  172. office365/sharepoint/tenant/administration/datagovernance/client_base.py +9 -0
  173. office365/sharepoint/tenant/administration/datagovernance/insight_client.py +82 -0
  174. office365/sharepoint/tenant/administration/datagovernance/insight_metadata.py +5 -0
  175. office365/sharepoint/tenant/administration/default_time_zone_id.py +11 -0
  176. office365/sharepoint/tenant/administration/endpoints.py +53 -2
  177. office365/sharepoint/tenant/administration/insights/onedrive_site_sharing.py +4 -0
  178. office365/sharepoint/tenant/administration/internal/appservice/permission_request.py +4 -0
  179. office365/sharepoint/tenant/administration/malware/__init__.py +0 -0
  180. office365/sharepoint/tenant/administration/malware/file.py +18 -0
  181. office365/sharepoint/tenant/administration/modified_property.py +5 -0
  182. office365/sharepoint/tenant/administration/policies/content_security_configuration.py +9 -0
  183. office365/sharepoint/tenant/administration/recent_action.py +9 -0
  184. office365/sharepoint/tenant/administration/reports/__init__.py +0 -0
  185. office365/sharepoint/tenant/administration/settings_service.py +38 -5
  186. office365/sharepoint/tenant/administration/sites/properties.py +78 -0
  187. office365/sharepoint/tenant/administration/sites/properties_collection.py +19 -0
  188. office365/sharepoint/tenant/administration/tenant.py +134 -7
  189. office365/sharepoint/tenant/administration/types.py +76 -1
  190. office365/sharepoint/tenant/insights/report_manager.py +29 -0
  191. office365/sharepoint/tenant/management/office365_tenant.py +7 -4
  192. office365/sharepoint/translation/job_status.py +22 -0
  193. office365/sharepoint/userprofiles/user_profile.py +6 -0
  194. office365/sharepoint/webparts/tile_data.py +21 -0
  195. office365/sharepoint/webs/dataleakage_prevention_status_info.py +5 -0
  196. office365/sharepoint/webs/web.py +80 -1
  197. office365/teams/chats/event_message_detail.py +8 -0
  198. office365/teams/deleted.py +24 -0
  199. office365/teams/work.py +35 -0
  200. office365/directory/tenant_relationship.py +0 -23
  201. office365/onedrive/admin.py +0 -32
  202. office365/onedrive/workbooks/charts/legend.py +0 -7
  203. office365/onedrive/workbooks/charts/series.py +0 -5
  204. {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/LICENSE +0 -0
  205. {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/WHEEL +0 -0
  206. {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.0.dist-info}/top_level.txt +0 -0
  207. /office365/{onedrive → admin}/sharepoint_settings.py +0 -0
  208. /office365/directory/{tenant_information.py → tenantinformation/information.py} +0 -0
  209. /office365/{base_item.py → onedrive/base_item.py} +0 -0
  210. /office365/onedrive/sitepages/{horizontal_section_column.py → sections/horizontal_column.py} +0 -0
  211. /office365/onedrive/sitepages/{vertical_section.py → sections/vertical.py} +0 -0
  212. /office365/sharepoint/sites/{home_sites_details.py → home/details.py} +0 -0
  213. /office365/sharepoint/sites/{home_site_reference.py → home/reference.py} +0 -0
  214. /office365/sharepoint/tenant/administration/{app_billing_properties.py → policies/app_billing_properties.py} +0 -0
@@ -0,0 +1,165 @@
1
+ from typing import Optional
2
+
3
+ from office365.azure_env import AzureEnvironment
4
+ from office365.runtime.auth.token_response import TokenResponse
5
+
6
+
7
+ class AuthenticationContext(object):
8
+ """Provides authentication context for Microsoft Graph client"""
9
+
10
+ def __init__(
11
+ self,
12
+ tenant=None,
13
+ scopes=None,
14
+ token_cache=None,
15
+ environment=AzureEnvironment.Global,
16
+ ):
17
+ """
18
+ :param str tenant: Tenant name, for example: contoso.onmicrosoft.com
19
+ :param list[str] or None scopes: Scopes requested to access an API
20
+ :param Any token_cache: Default cache is in memory only,
21
+ Refer https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
22
+ """
23
+ self._tenant = tenant
24
+ if scopes is None:
25
+ scopes = [
26
+ "{0}/.default".format(AzureEnvironment.get_graph_authority(environment))
27
+ ]
28
+ self._scopes = scopes
29
+ self._token_cache = token_cache
30
+ self._token_callback = None
31
+ self._environment = environment
32
+
33
+ def acquire_token(self):
34
+ # type: () -> TokenResponse
35
+ """Acquire access token"""
36
+ if not self._token_callback:
37
+ raise ValueError("Token callback is not set.")
38
+ token_resp = self._token_callback()
39
+ token = TokenResponse.from_json(token_resp)
40
+ return token
41
+
42
+ def with_access_token(self, token_callback):
43
+ """"""
44
+ self._token_callback = token_callback
45
+ return self
46
+
47
+ def with_certificate(self, client_id, thumbprint, private_key):
48
+ """
49
+ Initializes the confidential client with client certificate
50
+
51
+ :param str client_id: The OAuth client id of the calling application.
52
+ :param str thumbprint: Thumbprint
53
+ :param str private_key: Private key
54
+ """
55
+ import msal
56
+
57
+ app = msal.ConfidentialClientApplication(
58
+ client_id,
59
+ authority=self.authority_url,
60
+ client_credential={
61
+ "thumbprint": thumbprint,
62
+ "private_key": private_key,
63
+ },
64
+ token_cache=self._token_cache, # Default cache is in memory only.
65
+ # You can learn how to use SerializableTokenCache from
66
+ # https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
67
+ )
68
+
69
+ def _acquire_token():
70
+ return app.acquire_token_for_client(scopes=self._scopes)
71
+
72
+ return self.with_access_token(_acquire_token)
73
+
74
+ def with_client_secret(self, client_id, client_secret):
75
+ # type: (str, str) -> "AuthenticationContext"
76
+ """
77
+ Initializes the confidential client with client secret
78
+
79
+ :param str client_id: The OAuth client id of the calling application.
80
+ :param str client_secret: Client secret
81
+ """
82
+ import msal
83
+
84
+ app = msal.ConfidentialClientApplication(
85
+ client_id,
86
+ authority=self.authority_url,
87
+ client_credential=client_secret,
88
+ token_cache=self._token_cache,
89
+ )
90
+
91
+ def _acquire_token():
92
+ return app.acquire_token_for_client(scopes=self._scopes)
93
+
94
+ return self.with_access_token(_acquire_token)
95
+
96
+ def with_token_interactive(self, client_id, username=None):
97
+ # type: (str, Optional[str]) -> "AuthenticationContext"
98
+ """
99
+ Initializes the client via user credentials
100
+ Note: only works if your app is registered with redirect_uri as http://localhost
101
+
102
+ :param str client_id: The OAuth client id of the calling application.
103
+ :param str username: Typically a UPN in the form of an email address.
104
+ """
105
+ import msal
106
+
107
+ app = msal.PublicClientApplication(client_id, authority=self.authority_url)
108
+
109
+ def _acquire_token():
110
+ # The pattern to acquire a token looks like this.
111
+ result = None
112
+
113
+ # Firstly, check the cache to see if this end user has signed in before
114
+ accounts = app.get_accounts(username=username)
115
+ if accounts:
116
+ chosen = accounts[0] # Assuming the end user chose this one to proceed
117
+ # Now let's try to find a token in cache for this account
118
+ result = app.acquire_token_silent(self._scopes, account=chosen)
119
+
120
+ if not result:
121
+ result = app.acquire_token_interactive(
122
+ self._scopes,
123
+ login_hint=username,
124
+ )
125
+ return result
126
+
127
+ return self.with_access_token(_acquire_token)
128
+
129
+ def with_username_and_password(self, client_id, username, password):
130
+ # type: (str, str, str) -> "AuthenticationContext"
131
+ """
132
+ Initializes the client via user credentials
133
+
134
+ :param str client_id: The OAuth client id of the calling application.
135
+ :param str username: Typically a UPN in the form of an email address.
136
+ :param str password: The password.
137
+ """
138
+ import msal
139
+
140
+ app = msal.PublicClientApplication(
141
+ authority=self.authority_url,
142
+ client_id=client_id,
143
+ )
144
+
145
+ def _acquire_token():
146
+ result = None
147
+ accounts = app.get_accounts(username=username)
148
+ if accounts:
149
+ result = app.acquire_token_silent(self._scopes, account=accounts[0])
150
+
151
+ if not result:
152
+ result = app.acquire_token_by_username_password(
153
+ username=username,
154
+ password=password,
155
+ scopes=self._scopes,
156
+ )
157
+ return result
158
+
159
+ return self.with_access_token(_acquire_token)
160
+
161
+ @property
162
+ def authority_url(self):
163
+ return "{0}/{1}".format(
164
+ AzureEnvironment.get_login_authority(self._environment), self._tenant
165
+ )
@@ -3,6 +3,7 @@ from typing import Optional
3
3
  import requests
4
4
 
5
5
  import office365.logger
6
+ from office365.azure_env import AzureEnvironment
6
7
  from office365.runtime.auth.authentication_provider import AuthenticationProvider
7
8
  from office365.runtime.auth.token_response import TokenResponse
8
9
  from office365.runtime.compat import urlparse
@@ -10,7 +11,7 @@ from office365.runtime.http.request_options import RequestOptions
10
11
 
11
12
 
12
13
  class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
13
- def __init__(self, url, client_id, client_secret, environment="commercial"):
14
+ def __init__(self, url, client_id, client_secret, environment=None):
14
15
  """
15
16
  Provider to acquire the access token from a Microsoft Azure Access Control Service (ACS)
16
17
 
@@ -18,7 +19,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
18
19
  :param str client_secret: Secret string that the application uses to prove its identity when requesting a token
19
20
  :param str url: SharePoint web or site url
20
21
  :param str environment: The Office 365 Cloud Environment endpoint used for authentication
21
- defaults to 'commercial'.
22
+ defaults to 'Azure Global'.
22
23
  """
23
24
  self.url = url
24
25
  self.redirect_url = None
@@ -26,18 +27,14 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
26
27
  self.SharePointPrincipal = "00000003-0000-0ff1-ce00-000000000000"
27
28
  self._client_id = client_id
28
29
  self._client_secret = client_secret
29
- self._cached_token = None
30
+ self._cached_token = None # type: Optional[TokenResponse]
30
31
  self._environment = environment
31
32
 
32
33
  def authenticate_request(self, request):
33
34
  # type: (RequestOptions) -> None
34
- self.ensure_app_only_access_token()
35
- request.set_header("Authorization", self._get_authorization_header())
36
-
37
- def ensure_app_only_access_token(self):
38
35
  if self._cached_token is None:
39
36
  self._cached_token = self.get_app_only_access_token()
40
- return self._cached_token and self._cached_token.is_valid
37
+ request.set_header("Authorization", self._cached_token.authorization_header)
41
38
 
42
39
  def get_app_only_access_token(self):
43
40
  """Retrieves an app-only access token from ACS"""
@@ -65,9 +62,7 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
65
62
  self.SharePointPrincipal, target_host, target_realm
66
63
  )
67
64
  principal_id = self.get_formatted_principal(self._client_id, None, target_realm)
68
- sts_url = self.get_security_token_service_url(
69
- target_realm, environment=self._environment
70
- )
65
+ sts_url = self.get_security_token_service_url(target_realm)
71
66
  oauth2_request = {
72
67
  "grant_type": "client_credentials",
73
68
  "client_id": principal_id,
@@ -86,11 +81,6 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
86
81
  def _get_realm_from_target_url(self):
87
82
  """Get the realm for the URL"""
88
83
  response = requests.head(url=self.url, headers={"Authorization": "Bearer"})
89
- return self.process_realm_response(response)
90
-
91
- @staticmethod
92
- def process_realm_response(response):
93
- # type: (requests.Response) -> Optional[str]
94
84
  header_key = "WWW-Authenticate"
95
85
  if header_key in response.headers:
96
86
  auth_values = response.headers[header_key].split(",")
@@ -105,20 +95,15 @@ class ACSTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
105
95
  return "{0}/{1}@{2}".format(principal_name, host_name, realm)
106
96
  return "{0}@{1}".format(principal_name, realm)
107
97
 
108
- @staticmethod
109
- def get_security_token_service_url(realm, environment):
110
- # type: (str, str) -> str
111
- if environment == "GCCH":
112
- return "https://login.microsoftonline.us/{0}/tokens/OAuth/2".format(realm)
98
+ def get_security_token_service_url(self, realm):
99
+ # type: (str) -> str
100
+ if self._environment:
101
+ return "{0}/{1}/tokens/OAuth/2".format(
102
+ AzureEnvironment.get_login_authority(self._environment), realm
103
+ )
113
104
  else:
114
105
  return (
115
106
  "https://accounts.accesscontrol.windows.net/{0}/tokens/OAuth/2".format(
116
107
  realm
117
108
  )
118
109
  )
119
-
120
- def _get_authorization_header(self):
121
- return "Bearer {0}".format(self._cached_token.accessToken)
122
-
123
- def get_last_error(self):
124
- return self.error
@@ -1,5 +1,7 @@
1
1
  import os
2
2
  import uuid
3
+ from datetime import datetime, timezone
4
+ from typing import Optional
3
5
  from xml.dom import minidom
4
6
  from xml.etree import ElementTree
5
7
 
@@ -7,6 +9,7 @@ import requests
7
9
  import requests.utils
8
10
 
9
11
  import office365.logger
12
+ from office365.runtime.auth.auth_cookies import AuthCookies
10
13
  from office365.runtime.auth.authentication_provider import AuthenticationProvider
11
14
  from office365.runtime.auth.sts_profile import STSProfile
12
15
  from office365.runtime.auth.user_realm_info import UserRealmInfo
@@ -20,23 +23,17 @@ def resolve_base_url(url):
20
23
  return parts[0] + "://" + host_name
21
24
 
22
25
 
23
- def xml_escape(s_val):
24
- s_val = s_val.replace("&", "&")
25
- s_val = s_val.replace("<", "&lt;")
26
- s_val = s_val.replace(">", "&gt;")
27
- s_val = s_val.replace('"', "&quot;")
28
- s_val = s_val.replace("'", "&apos;")
29
- return s_val
26
+ def string_escape(value):
27
+ value = value.replace("&", "&amp;")
28
+ value = value.replace("<", "&lt;")
29
+ value = value.replace(">", "&gt;")
30
+ value = value.replace('"', "&quot;")
31
+ value = value.replace("'", "&apos;")
32
+ return value
30
33
 
31
34
 
32
- def is_valid_auth_cookies(values):
33
- """
34
- Validates authorization cookies
35
- """
36
- return any(values) and (
37
- values.get("FedAuth", None) is not None
38
- or values.get("SPOIDCRL", None) is not None
39
- )
35
+ def datetime_escape(value):
36
+ return value.isoformat("T")[:-9] + "Z"
40
37
 
41
38
 
42
39
  class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
@@ -60,7 +57,7 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
60
57
  self.error = ""
61
58
  self._username = username
62
59
  self._password = password
63
- self._cached_auth_cookies = None
60
+ self._cached_auth_cookies = None # type: Optional[AuthCookies]
64
61
  self.__ns_prefixes = {
65
62
  "S": "{http://www.w3.org/2003/05/soap-envelope}",
66
63
  "s": "{http://www.w3.org/2003/05/soap-envelope}",
@@ -82,24 +79,20 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
82
79
  Authenticate request handler
83
80
  """
84
81
  logger = self.logger(self.authenticate_request.__name__)
85
- self.ensure_authentication_cookie()
86
- logger.debug_secrets(self._cached_auth_cookies)
87
- cookie_header_value = "; ".join(
88
- [
89
- "=".join([key, str(val)])
90
- for key, val in self._cached_auth_cookies.items()
91
- ]
92
- )
93
- request.set_header("Cookie", cookie_header_value)
94
82
 
95
- def ensure_authentication_cookie(self):
96
- if self._cached_auth_cookies is None:
83
+ request_time = datetime.now(timezone.utc)
84
+ if (
85
+ self._cached_auth_cookies is None
86
+ or request_time >= self._sts_profile.expires
87
+ ):
88
+ self._sts_profile.reset()
97
89
  self._cached_auth_cookies = self.get_authentication_cookie()
98
- return True
90
+ logger.debug_secrets(self._cached_auth_cookies)
91
+ request.set_header("Cookie", self._cached_auth_cookies.cookie_header)
99
92
 
100
93
  def get_authentication_cookie(self):
101
94
  """Acquire authentication cookie"""
102
- logger = self.logger(self.ensure_authentication_cookie.__name__)
95
+ logger = self.logger(self.get_authentication_cookie.__name__)
103
96
  logger.debug("get_authentication_cookie called")
104
97
 
105
98
  try:
@@ -132,9 +125,6 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
132
125
  return info
133
126
  return None
134
127
 
135
- def get_last_error(self):
136
- return self.error
137
-
138
128
  def _acquire_service_token_from_adfs(self, adfs_url):
139
129
  logger = self.logger(self._acquire_service_token_from_adfs.__name__)
140
130
 
@@ -143,10 +133,10 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
143
133
  {
144
134
  "auth_url": adfs_url,
145
135
  "message_id": str(uuid.uuid4()),
146
- "username": xml_escape(self._username),
147
- "password": xml_escape(self._password),
148
- "created": self._sts_profile.created,
149
- "expires": self._sts_profile.expires,
136
+ "username": string_escape(self._username),
137
+ "password": string_escape(self._password),
138
+ "created": datetime_escape(self._sts_profile.created),
139
+ "expires": datetime_escape(self._sts_profile.expires),
150
140
  "issuer": self._sts_profile.tokenIssuer,
151
141
  },
152
142
  )
@@ -195,11 +185,11 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
195
185
  "SAML.xml",
196
186
  {
197
187
  "auth_url": self._sts_profile.authorityUrl,
198
- "username": xml_escape(self._username),
199
- "password": xml_escape(self._password),
188
+ "username": string_escape(self._username),
189
+ "password": string_escape(self._password),
200
190
  "message_id": str(uuid.uuid4()),
201
- "created": self._sts_profile.created,
202
- "expires": self._sts_profile.expires,
191
+ "created": datetime_escape(self._sts_profile.created),
192
+ "expires": datetime_escape(self._sts_profile.expires),
203
193
  "issuer": self._sts_profile.tokenIssuer,
204
194
  },
205
195
  )
@@ -300,9 +290,9 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
300
290
  },
301
291
  )
302
292
  logger.debug_secrets("session.cookies: %s", session.cookies)
303
- cookies = requests.utils.dict_from_cookiejar(session.cookies)
293
+ cookies = AuthCookies(requests.utils.dict_from_cookiejar(session.cookies))
304
294
  logger.debug_secrets("cookies: %s", cookies)
305
- if not is_valid_auth_cookies(cookies):
295
+ if not cookies.is_valid:
306
296
  self.error = (
307
297
  "An error occurred while retrieving auth cookies from {0}".format(
308
298
  self._sts_profile.signin_page_url
@@ -312,19 +302,16 @@ class SamlTokenProvider(AuthenticationProvider, office365.logger.LoggerContext):
312
302
  raise ValueError(self.error)
313
303
  return cookies
314
304
 
315
- @staticmethod
316
- def _prepare_request_from_template(template_name, params):
305
+ def _prepare_request_from_template(self, template_name, params):
317
306
  """Construct the request body to acquire security token from STS endpoint"""
318
- logger = SamlTokenProvider.logger()
307
+ logger = self.logger(self._prepare_request_from_template.__name__)
319
308
  logger.debug_secrets("params: %s", params)
320
- f = open(
321
- os.path.join(os.path.dirname(__file__), "templates", template_name),
322
- encoding="utf8",
309
+
310
+ template_path = os.path.join(
311
+ os.path.dirname(__file__), "templates", template_name
323
312
  )
324
- try:
313
+
314
+ with open(template_path, encoding="utf8") as f:
325
315
  data = f.read()
326
- for key in params:
327
- data = data.replace("{" + key + "}", str(params[key]))
328
- return data
329
- finally:
330
- f.close()
316
+
317
+ return data.format(**params)
@@ -5,9 +5,7 @@ from office365.runtime.compat import timezone, urlparse
5
5
 
6
6
  class STSProfile(object):
7
7
  def __init__(self, authority_url, environment):
8
- """
9
- :type authority_url: str
10
- """
8
+ # type: (str, str) -> None
11
9
  self.authorityUrl = authority_url
12
10
  if environment == "GCCH":
13
11
  self.serviceUrl = "https://login.microsoftonline.us"
@@ -16,13 +14,15 @@ class STSProfile(object):
16
14
  self.securityTokenServicePath = "extSTS.srf"
17
15
  self.userRealmServicePath = "GetUserRealm.srf"
18
16
  self.tokenIssuer = "urn:federation:MicrosoftOnline"
19
- now = datetime.now(tz=timezone.utc)
20
- self.created = now.astimezone(timezone.utc).isoformat("T")[:-9] + "Z"
21
- self.expires = (now + timedelta(minutes=10)).astimezone(timezone.utc).isoformat(
22
- "T"
23
- )[:-9] + "Z"
17
+ self.created = datetime.now(tz=timezone.utc)
18
+ self.expires = self.created + timedelta(minutes=30)
24
19
  self.signInPage = "_forms/default.aspx?wa=wsignin1.0"
25
20
 
21
+ def reset(self):
22
+ """Renew the expiration time."""
23
+ self.created = datetime.now(tz=timezone.utc)
24
+ self.expires = self.created + timedelta(minutes=30)
25
+
26
26
  @property
27
27
  def tenant(self):
28
28
  return urlparse(self.authorityUrl).netloc
@@ -9,6 +9,10 @@ class TokenResponse(object):
9
9
  def is_valid(self):
10
10
  return self.accessToken is not None and self.tokenType == "Bearer"
11
11
 
12
+ @property
13
+ def authorization_header(self):
14
+ return "Bearer {0}".format(self.accessToken)
15
+
12
16
  @staticmethod
13
17
  def from_json(value):
14
18
  error = value.get("error", None)
@@ -0,0 +1,5 @@
1
+ from office365.runtime.client_value import ClientValue
2
+
3
+
4
+ class CustomFontsResource(ClientValue):
5
+ """ """
@@ -0,0 +1,68 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from office365.runtime.client_result import ClientResult
4
+ from office365.runtime.client_value import ClientValue
5
+ from office365.runtime.paths.service_operation import ServiceOperationPath
6
+ from office365.runtime.queries.service_operation import ServiceOperationQuery
7
+ from office365.sharepoint.entity import Entity
8
+
9
+ if TYPE_CHECKING:
10
+ from office365.sharepoint.client_context import ClientContext
11
+
12
+
13
+ class SystemSiteLockExpirationResult(ClientValue):
14
+ """"""
15
+
16
+ def __init__(self, error=None, expiration=None):
17
+ self.Error = error
18
+ self.Expiration = expiration
19
+
20
+
21
+ class SiteMoveService(Entity):
22
+ """ """
23
+
24
+ def __init__(
25
+ self,
26
+ context,
27
+ site_id,
28
+ site_subscription_id=None,
29
+ source_database_id=None,
30
+ target_database_id=None,
31
+ ):
32
+ # type: (ClientContext, str, str, str, str) -> None
33
+ """"""
34
+ static_path = ServiceOperationPath(
35
+ "Microsoft.SharePoint.Administration.SiteMove.Service.SiteMoveService",
36
+ {
37
+ "siteId": site_id,
38
+ "siteSubscriptionId": site_subscription_id,
39
+ "sourceDatabaseId": source_database_id,
40
+ "targetDatabaseId": target_database_id,
41
+ },
42
+ )
43
+ super(SiteMoveService, self).__init__(context, static_path)
44
+
45
+ def acquire_system_site_lock(
46
+ self, lock_requestor, lock_type, lease_duration_in_minutes
47
+ ):
48
+ """"""
49
+ return_type = ClientResult(self.context, SystemSiteLockExpirationResult())
50
+ payload = {
51
+ "lockRequestor": lock_requestor,
52
+ "lockType": lock_type,
53
+ "leaseDurationInMinutes": lease_duration_in_minutes,
54
+ }
55
+ qry = ServiceOperationQuery(
56
+ self,
57
+ "AcquireSystemSiteLock",
58
+ None,
59
+ payload,
60
+ None,
61
+ return_type,
62
+ )
63
+ self.context.add_query(qry)
64
+ return return_type
65
+
66
+ @property
67
+ def entity_type_name(self):
68
+ return "Microsoft.SharePoint.Administration.SiteMove.Service.SiteMoveService"
@@ -0,0 +1,11 @@
1
+ from office365.runtime.client_value import ClientValue
2
+
3
+
4
+ class SiteMoveServiceInfo(ClientValue):
5
+ """ """
6
+
7
+ @property
8
+ def entity_type_name(self):
9
+ return (
10
+ "Microsoft.SharePoint.Administration.SiteMove.Service.SiteMoveServiceInfo"
11
+ )
@@ -20,6 +20,21 @@ class ChangeItem(Change):
20
20
  """Specifies an identifier for the content type"""
21
21
  return self.properties.get("ContentTypeId", ContentTypeId())
22
22
 
23
+ @property
24
+ def editor(self):
25
+ """Specifies the editor of the changed item."""
26
+ return self.properties.get("Editor", None)
27
+
28
+ @property
29
+ def editor_email_hint(self):
30
+ """Returns the email corresponding to Editor."""
31
+ return self.properties.get("EditorEmailHint", None)
32
+
33
+ @property
34
+ def editor_login_name(self):
35
+ """Returns login name of the Editor."""
36
+ return self.properties.get("EditorLoginName", None)
37
+
23
38
  @property
24
39
  def file_type(self):
25
40
  # type: () -> Optional[str]