Office365-REST-Python-Client 2.5.14__py3-none-any.whl → 2.6.1__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.
- {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.1.dist-info}/METADATA +21 -30
- {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.1.dist-info}/RECORD +210 -112
- office365/admin/__init__.py +0 -0
- office365/admin/admin.py +69 -0
- office365/admin/microsoft365_apps.py +5 -0
- office365/admin/people_settings.py +5 -0
- office365/admin/report_settings.py +5 -0
- office365/{onedrive → admin}/sharepoint.py +1 -1
- office365/azure_env.py +60 -0
- office365/directory/applications/app_ids.py +6 -0
- office365/directory/authentication/authentication.py +16 -0
- office365/directory/authentication/method_target.py +2 -1
- office365/directory/authentication/methods/microsoft_authenticator.py +6 -0
- office365/directory/authentication/methods/root.py +11 -0
- office365/directory/authentication/methods/sms.py +9 -0
- office365/directory/certificates/self_signed.py +31 -2
- office365/directory/identities/conditional_access_root.py +14 -0
- office365/directory/identitygovernance/privilegedaccess/approval.py +8 -0
- office365/directory/identitygovernance/privilegedaccess/group.py +30 -0
- office365/directory/identitygovernance/privilegedaccess/group_assignment_schedule_instance.py +7 -0
- office365/directory/identitygovernance/privilegedaccess/unified_role_assignment_schedule_request.py +7 -0
- office365/directory/identitygovernance/userconsent/request_collection.py +10 -0
- office365/directory/identitygovernance/workflow/__init__.py +0 -0
- office365/directory/identitygovernance/workflow/base.py +5 -0
- office365/directory/policies/cross_tenant_access.py +13 -0
- office365/directory/policies/feature_rollout.py +16 -0
- office365/directory/policies/root.py +39 -23
- office365/directory/policies/template.py +5 -0
- office365/directory/protection/threatassessment/email_file_request.py +20 -0
- office365/directory/protection/threatassessment/request.py +25 -0
- office365/directory/rolemanagement/application.py +15 -0
- office365/directory/rolemanagement/resource_action.py +8 -4
- office365/directory/rolemanagement/role_permission.py +3 -3
- office365/directory/security/alerts/collection.py +49 -0
- office365/directory/security/scorecontrol/__init__.py +0 -0
- office365/directory/security/scorecontrol/profile.py +6 -0
- office365/directory/security/security.py +17 -4
- office365/directory/serviceprincipals/service_principal.py +36 -28
- office365/directory/tenantinformation/__init__.py +0 -0
- office365/directory/tenantinformation/multi_organization.py +11 -0
- office365/directory/tenantinformation/relationship.py +61 -0
- office365/directory/users/insights_settings.py +5 -0
- office365/graph_client.py +52 -132
- office365/graph_request.py +78 -19
- office365/intune/servicecommunications/health/health.py +1 -1
- office365/intune/servicecommunications/issues/issue.py +2 -2
- office365/onedrive/columns/definition.py +1 -1
- office365/onedrive/contenttypes/content_type.py +1 -1
- office365/onedrive/driveitems/driveItem.py +13 -1
- office365/onedrive/drives/drive.py +1 -1
- office365/onedrive/filestorage/__init__.py +0 -0
- office365/onedrive/filestorage/container.py +7 -0
- office365/onedrive/filestorage/file_storage.py +20 -0
- office365/onedrive/listitems/field_value_set.py +1 -1
- office365/onedrive/listitems/list_item.py +1 -1
- office365/onedrive/lists/list.py +1 -1
- office365/onedrive/recyclebin/__init__.py +0 -0
- office365/onedrive/recyclebin/item.py +6 -0
- office365/onedrive/recyclebin/recyclebin.py +29 -0
- office365/onedrive/recyclebin/settings.py +13 -0
- office365/onedrive/shares/drive_item.py +1 -1
- office365/onedrive/sitepages/base.py +1 -1
- office365/onedrive/sitepages/canvas_layout.py +2 -2
- office365/onedrive/sitepages/sections/__init__.py +0 -0
- office365/onedrive/sitepages/{horizontal_section.py → sections/horizontal.py} +1 -1
- office365/onedrive/sitepages/webparts/data.py +5 -0
- office365/onedrive/sitepages/webparts/position.py +5 -0
- office365/onedrive/sitepages/webparts/standard.py +9 -0
- office365/onedrive/sitepages/webparts/web_part.py +12 -0
- office365/onedrive/sites/site.py +1 -1
- office365/onedrive/storage/storage.py +10 -0
- office365/onedrive/workbooks/charts/axes.py +41 -1
- office365/onedrive/workbooks/charts/axis.py +5 -0
- office365/onedrive/workbooks/charts/chart.py +64 -5
- office365/onedrive/workbooks/charts/fill.py +5 -0
- office365/onedrive/workbooks/charts/font.py +5 -0
- office365/onedrive/workbooks/charts/legend/__init__.py +0 -0
- office365/onedrive/workbooks/charts/legend/format.py +5 -0
- office365/onedrive/workbooks/charts/legend/legend.py +26 -0
- office365/onedrive/workbooks/charts/point.py +5 -0
- office365/onedrive/workbooks/charts/series/__init__.py +0 -0
- office365/onedrive/workbooks/charts/series/format.py +5 -0
- office365/onedrive/workbooks/charts/series/series.py +31 -0
- office365/onedrive/workbooks/charts/title.py +5 -0
- office365/onedrive/workbooks/filter.py +10 -0
- office365/onedrive/workbooks/filter_criteria.py +3 -3
- office365/onedrive/workbooks/ranges/fill.py +11 -1
- office365/onedrive/workbooks/ranges/range.py +26 -0
- office365/onedrive/workbooks/ranges/view.py +14 -0
- office365/onedrive/workbooks/sort_field.py +8 -3
- office365/onedrive/workbooks/tables/sort.py +20 -0
- office365/onedrive/workbooks/worksheets/worksheet.py +11 -0
- office365/partners/billing/azure_usage.py +17 -0
- office365/partners/billing/billed_usage.py +21 -0
- office365/partners/billing/billing.py +17 -0
- office365/partners/billing/operation.py +5 -0
- office365/partners/partners.py +17 -0
- office365/reports/root.py +9 -0
- office365/reports/userregistration/feature_summary.py +5 -0
- office365/runtime/auth/auth_cookies.py +48 -0
- office365/runtime/auth/authentication_context.py +36 -19
- office365/runtime/auth/entra/__init__.py +0 -0
- office365/runtime/auth/entra/authentication_context.py +165 -0
- office365/runtime/auth/providers/acs_token_provider.py +12 -27
- office365/runtime/auth/providers/saml_token_provider.py +46 -67
- office365/runtime/auth/sts_profile.py +37 -22
- office365/runtime/auth/token_response.py +4 -0
- office365/sharepoint/administration/custom_fonts_resource.py +5 -0
- office365/sharepoint/administration/sitemove/__init__.py +0 -0
- office365/sharepoint/administration/sitemove/service.py +68 -0
- office365/sharepoint/administration/sitemove/service_info.py +11 -0
- office365/sharepoint/changes/item.py +15 -0
- office365/sharepoint/client_context.py +61 -37
- office365/sharepoint/directory/group.py +2 -0
- office365/sharepoint/directory/helper.py +2 -0
- office365/sharepoint/directory/provider/provider.py +6 -0
- office365/sharepoint/directory/user.py +20 -0
- office365/sharepoint/files/publish/__init__.py +0 -0
- office365/sharepoint/files/publish/status.py +9 -0
- office365/sharepoint/flows/connector_result.py +17 -0
- office365/sharepoint/flows/permissions.py +11 -7
- office365/sharepoint/fontpackages/__init__.py +0 -0
- office365/sharepoint/fontpackages/collection.py +26 -0
- office365/sharepoint/fontpackages/creation_parameters.py +5 -0
- office365/sharepoint/fontpackages/font_package.py +5 -0
- office365/sharepoint/fontpackages/oob_settings.py +5 -0
- office365/sharepoint/forms/customization.py +26 -0
- office365/sharepoint/ir/__init__.py +0 -0
- office365/sharepoint/ir/migration.py +5 -0
- office365/sharepoint/lists/list.py +30 -0
- office365/sharepoint/marketplace/app_metadata.py +12 -1
- office365/sharepoint/marketplace/app_metadata_collection.py +8 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/instance_info.py +22 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_failed_info.py +5 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_info.py +12 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/permission_response.py +15 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/addins/principals_response.py +5 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/app_request_information.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/app_response_information.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/available_addins_response.py +4 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/card_design.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/card_designs.py +9 -0
- office365/sharepoint/marketplace/corporatecuratedgallery/teams_package_download.py +14 -0
- office365/sharepoint/marketplace/tenant/appcatalog/accessor.py +62 -3
- office365/sharepoint/multigeo/services.py +14 -0
- office365/sharepoint/multigeo/storage_quota.py +9 -0
- office365/sharepoint/policy/license_utilities.py +27 -0
- office365/sharepoint/principal/principal.py +6 -0
- office365/sharepoint/request.py +95 -10
- office365/sharepoint/search/administration/document_crawl_log.py +16 -2
- office365/sharepoint/search/administration/tenant_crawl_versions_info_provider.py +1 -1
- office365/sharepoint/search/reports/abandoned_queries.py +11 -1
- office365/sharepoint/search/reports/abandonedqueries/item.py +7 -1
- office365/sharepoint/sharing/domain_restriction_settings.py +5 -0
- office365/sharepoint/sharing/information.py +12 -0
- office365/sharepoint/sitehealth/result.py +4 -4
- office365/sharepoint/sitehealth/summary.py +5 -5
- office365/sharepoint/sites/copy_job_progress.py +5 -0
- office365/sharepoint/sites/copy_migration_iInfo.py +5 -0
- office365/sharepoint/sites/home/__init__.py +0 -0
- office365/sharepoint/sites/{sph_site.py → home/site.py} +1 -1
- office365/sharepoint/sites/site.py +26 -1
- office365/sharepoint/tenant/administration/app_service_principal_public.py +17 -0
- office365/sharepoint/tenant/administration/audit/data.py +12 -0
- office365/sharepoint/tenant/administration/audit/unified_record.py +18 -0
- office365/sharepoint/tenant/administration/coms/__init__.py +0 -0
- office365/sharepoint/tenant/administration/coms/messages_fields_data.py +5 -0
- office365/sharepoint/tenant/administration/coms/messages_service_proxy.py +16 -0
- office365/sharepoint/tenant/administration/copilot/__init__.py +0 -0
- office365/sharepoint/tenant/administration/copilot/adaptive_card_config.py +11 -0
- office365/sharepoint/tenant/administration/datagovernance/__init__.py +0 -0
- office365/sharepoint/tenant/administration/datagovernance/client_base.py +9 -0
- office365/sharepoint/tenant/administration/datagovernance/insight_client.py +82 -0
- office365/sharepoint/tenant/administration/datagovernance/insight_metadata.py +5 -0
- office365/sharepoint/tenant/administration/default_time_zone_id.py +11 -0
- office365/sharepoint/tenant/administration/endpoints.py +53 -2
- office365/sharepoint/tenant/administration/insights/onedrive_site_sharing.py +4 -0
- office365/sharepoint/tenant/administration/internal/appservice/permission_request.py +4 -0
- office365/sharepoint/tenant/administration/malware/__init__.py +0 -0
- office365/sharepoint/tenant/administration/malware/file.py +18 -0
- office365/sharepoint/tenant/administration/modified_property.py +5 -0
- office365/sharepoint/tenant/administration/policies/content_security_configuration.py +9 -0
- office365/sharepoint/tenant/administration/recent_action.py +9 -0
- office365/sharepoint/tenant/administration/reports/__init__.py +0 -0
- office365/sharepoint/tenant/administration/settings_service.py +38 -5
- office365/sharepoint/tenant/administration/sites/properties.py +78 -0
- office365/sharepoint/tenant/administration/sites/properties_collection.py +19 -0
- office365/sharepoint/tenant/administration/tenant.py +134 -7
- office365/sharepoint/tenant/administration/types.py +76 -1
- office365/sharepoint/tenant/insights/report_manager.py +29 -0
- office365/sharepoint/tenant/management/office365_tenant.py +7 -4
- office365/sharepoint/translation/job_status.py +22 -0
- office365/sharepoint/userprofiles/user_profile.py +6 -0
- office365/sharepoint/webparts/tile_data.py +21 -0
- office365/sharepoint/webs/dataleakage_prevention_status_info.py +5 -0
- office365/sharepoint/webs/web.py +80 -1
- office365/teams/chats/event_message_detail.py +8 -0
- office365/teams/deleted.py +24 -0
- office365/teams/work.py +35 -0
- office365/directory/tenant_relationship.py +0 -23
- office365/onedrive/admin.py +0 -32
- office365/onedrive/workbooks/charts/legend.py +0 -7
- office365/onedrive/workbooks/charts/series.py +0 -5
- {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.1.dist-info}/LICENSE +0 -0
- {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.1.dist-info}/WHEEL +0 -0
- {Office365_REST_Python_Client-2.5.14.dist-info → Office365_REST_Python_Client-2.6.1.dist-info}/top_level.txt +0 -0
- /office365/{onedrive → admin}/sharepoint_settings.py +0 -0
- /office365/directory/{tenant_information.py → tenantinformation/information.py} +0 -0
- /office365/{base_item.py → onedrive/base_item.py} +0 -0
- /office365/onedrive/sitepages/{horizontal_section_column.py → sections/horizontal_column.py} +0 -0
- /office365/onedrive/sitepages/{vertical_section.py → sections/vertical.py} +0 -0
- /office365/sharepoint/sites/{home_sites_details.py → home/details.py} +0 -0
- /office365/sharepoint/sites/{home_site_reference.py → home/reference.py} +0 -0
- /office365/sharepoint/tenant/administration/{app_billing_properties.py → policies/app_billing_properties.py} +0 -0
|
@@ -4,7 +4,7 @@ from office365.runtime.client_value_collection import ClientValueCollection
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class RolePermission(ClientValue):
|
|
7
|
-
""" """
|
|
7
|
+
"""Contains the set of ResourceActions determining the allowed and not allowed permissions for each role."""
|
|
8
8
|
|
|
9
|
-
def __init__(self,
|
|
10
|
-
self.resourceActions = ClientValueCollection(ResourceAction,
|
|
9
|
+
def __init__(self, resource_actions=None):
|
|
10
|
+
self.resourceActions = ClientValueCollection(ResourceAction, resource_actions)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from office365.directory.security.alerts.alert import Alert
|
|
2
|
+
from office365.entity_collection import EntityCollection
|
|
3
|
+
from office365.runtime.http.request_options import RequestOptions
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AlertCollection(EntityCollection[Alert]):
|
|
7
|
+
"""Service Principal's collection"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, context, resource_path=None):
|
|
10
|
+
super(AlertCollection, self).__init__(context, Alert, resource_path)
|
|
11
|
+
|
|
12
|
+
def add(
|
|
13
|
+
self,
|
|
14
|
+
title,
|
|
15
|
+
description=None,
|
|
16
|
+
severity=None,
|
|
17
|
+
category=None,
|
|
18
|
+
status=None,
|
|
19
|
+
source=None,
|
|
20
|
+
vendor_information=None,
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Creates an alert object.
|
|
24
|
+
:param str title:
|
|
25
|
+
:param str description:
|
|
26
|
+
:param str severity:
|
|
27
|
+
:param str category:
|
|
28
|
+
:param str status:
|
|
29
|
+
:param str source:
|
|
30
|
+
:param str vendor_information:
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def _construct_request(request):
|
|
34
|
+
# type: (RequestOptions) -> None
|
|
35
|
+
request.set_header("Content-Type", "application/json")
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
super(AlertCollection, self)
|
|
39
|
+
.add(
|
|
40
|
+
title=title,
|
|
41
|
+
description=description,
|
|
42
|
+
severity=severity,
|
|
43
|
+
category=category,
|
|
44
|
+
status=status,
|
|
45
|
+
source=source,
|
|
46
|
+
vendorInformation=vendor_information,
|
|
47
|
+
)
|
|
48
|
+
.before_execute(_construct_request)
|
|
49
|
+
)
|
|
File without changes
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from office365.directory.security.alerts.alert import Alert
|
|
2
|
+
from office365.directory.security.alerts.collection import AlertCollection
|
|
2
3
|
from office365.directory.security.attacksimulations.root import AttackSimulationRoot
|
|
3
4
|
from office365.directory.security.cases.root import CasesRoot
|
|
4
5
|
from office365.directory.security.hunting_query_results import HuntingQueryResults
|
|
5
6
|
from office365.directory.security.incidents.incident import Incident
|
|
7
|
+
from office365.directory.security.scorecontrol.profile import SecureScoreControlProfile
|
|
6
8
|
from office365.directory.security.threatintelligence.threat_intelligence import (
|
|
7
9
|
ThreatIntelligence,
|
|
8
10
|
)
|
|
@@ -35,12 +37,10 @@ class Security(Entity):
|
|
|
35
37
|
|
|
36
38
|
@property
|
|
37
39
|
def alerts(self):
|
|
38
|
-
# type: () ->
|
|
40
|
+
# type: () -> AlertCollection
|
|
39
41
|
return self.properties.get(
|
|
40
42
|
"alerts",
|
|
41
|
-
|
|
42
|
-
self.context, Alert, ResourcePath("alerts", self.resource_path)
|
|
43
|
-
),
|
|
43
|
+
AlertCollection(self.context, ResourcePath("alerts", self.resource_path)),
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
@property
|
|
@@ -83,6 +83,18 @@ class Security(Entity):
|
|
|
83
83
|
),
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
+
@property
|
|
87
|
+
def secure_score_control_profiles(self):
|
|
88
|
+
""""""
|
|
89
|
+
return self.properties.get(
|
|
90
|
+
"secureScoreControlProfiles",
|
|
91
|
+
EntityCollection(
|
|
92
|
+
self.context,
|
|
93
|
+
SecureScoreControlProfile,
|
|
94
|
+
ResourcePath("secureScoreControlProfiles", self.resource_path),
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
|
|
86
98
|
@property
|
|
87
99
|
def triggers(self):
|
|
88
100
|
""""""
|
|
@@ -106,6 +118,7 @@ class Security(Entity):
|
|
|
106
118
|
property_mapping = {
|
|
107
119
|
"alerts_v2": self.alerts_v2,
|
|
108
120
|
"attackSimulation": self.attack_simulation,
|
|
121
|
+
"secureScoreControlProfiles": self.secure_score_control_profiles,
|
|
109
122
|
"threatIntelligence": self.threat_intelligence,
|
|
110
123
|
}
|
|
111
124
|
default_value = property_mapping.get(name, None)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
1
|
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from typing_extensions import Self
|
|
@@ -103,31 +102,20 @@ class ServicePrincipal(DirectoryObject):
|
|
|
103
102
|
self.context.add_query(qry)
|
|
104
103
|
return return_type
|
|
105
104
|
|
|
106
|
-
def _get_service_principal_by_app(self, app, action):
|
|
107
|
-
# type: (Application|str, Callable[[Application], None]) -> None
|
|
108
|
-
if isinstance(app, Application):
|
|
109
|
-
|
|
110
|
-
def _after():
|
|
111
|
-
action(app)
|
|
112
|
-
|
|
113
|
-
app.ensure_property("id", _after)
|
|
114
|
-
else:
|
|
115
|
-
self.context.service_principals.get_by_app(app).get().after_execute(action)
|
|
116
|
-
|
|
117
105
|
def get_delegated_permissions(self, app, principal=None):
|
|
118
106
|
# type: (Application|str, User|str) -> ClientResult[StringCollection]
|
|
119
107
|
"""Gets a delegated API permission"""
|
|
120
108
|
|
|
109
|
+
consent_type = "Principal" if principal else "AllPrincipals"
|
|
110
|
+
|
|
121
111
|
return_type = ClientResult(self.context, StringCollection())
|
|
122
112
|
|
|
123
113
|
def _get_delegated_permissions(client_id, principal_id=None):
|
|
124
114
|
# type: (str, str) -> None
|
|
125
115
|
|
|
126
116
|
if principal_id is None:
|
|
127
|
-
query_text = (
|
|
128
|
-
|
|
129
|
-
client_id
|
|
130
|
-
)
|
|
117
|
+
query_text = "clientId eq '{0}' and consentType eq '{1}'".format(
|
|
118
|
+
client_id, consent_type
|
|
131
119
|
)
|
|
132
120
|
else:
|
|
133
121
|
query_text = "principalId eq '{0}' and clientId eq '{1}'".format(
|
|
@@ -171,14 +159,16 @@ class ServicePrincipal(DirectoryObject):
|
|
|
171
159
|
return return_type
|
|
172
160
|
|
|
173
161
|
def grant_delegated_permissions(self, app, principal, scope):
|
|
174
|
-
# type: (Application|str, User|str, AppRole|str) -> Self
|
|
162
|
+
# type: (Application|str, User|str|None, AppRole|str) -> Self
|
|
175
163
|
"""Grants a delegated permission to the client service principal on behalf of a user"""
|
|
176
164
|
|
|
165
|
+
consent_type = "Principal" if principal else "AllPrincipals"
|
|
166
|
+
|
|
177
167
|
def _grant_delegated(principal_id, client_id):
|
|
178
168
|
# type: (str, str) -> None
|
|
179
169
|
self.context.oauth2_permission_grants.add(
|
|
180
170
|
clientId=client_id,
|
|
181
|
-
consentType=
|
|
171
|
+
consentType=consent_type,
|
|
182
172
|
resourceId=self.id,
|
|
183
173
|
principalId=principal_id,
|
|
184
174
|
scope=scope,
|
|
@@ -206,34 +196,51 @@ class ServicePrincipal(DirectoryObject):
|
|
|
206
196
|
self.ensure_property("id", _resource_resolved)
|
|
207
197
|
return self
|
|
208
198
|
|
|
209
|
-
def revoke_delegated_permissions(self, app, principal, scope):
|
|
199
|
+
def revoke_delegated_permissions(self, app, principal=None, scope=None):
|
|
210
200
|
# type: (Application|str, User|str, AppRole|str) -> Self
|
|
211
201
|
""""""
|
|
212
202
|
|
|
213
|
-
def _revoke_delegated_permissions(
|
|
203
|
+
def _revoke_delegated_permissions(principal_id, client_id):
|
|
214
204
|
# type: (str, str) -> None
|
|
215
205
|
|
|
216
206
|
def _after(return_type):
|
|
217
|
-
|
|
207
|
+
if len(return_type) > 0:
|
|
208
|
+
return_type[0].delete_object()
|
|
209
|
+
|
|
210
|
+
if principal:
|
|
211
|
+
query_text = "clientId eq '{0}' and principalId eq '{1}' and resourceId eq '{2}'".format(
|
|
212
|
+
client_id, principal_id, self.id
|
|
213
|
+
)
|
|
214
|
+
else:
|
|
215
|
+
query_text = "clientId eq '{0}' and consentType eq 'AllPrincipals' and resourceId eq '{1}'".format(
|
|
216
|
+
client_id, self.id
|
|
217
|
+
)
|
|
218
218
|
|
|
219
|
-
query_text = "clientId eq '{0}' and principalId eq '{1}'".format(
|
|
220
|
-
app_id, principal_id
|
|
221
|
-
)
|
|
222
219
|
self.context.oauth2_permission_grants.filter(
|
|
223
220
|
query_text
|
|
224
221
|
).get().after_execute(_after)
|
|
225
222
|
|
|
226
|
-
def
|
|
223
|
+
def _principal_resolved(principal_id):
|
|
224
|
+
# type: (str) -> None
|
|
225
|
+
def _client_loaded(return_type):
|
|
226
|
+
# type: (ServicePrincipal) -> None
|
|
227
|
+
_revoke_delegated_permissions(principal_id, return_type.id)
|
|
228
|
+
|
|
229
|
+
self.context.service_principals.get_by_app(app).get().after_execute(
|
|
230
|
+
_client_loaded
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def _resource_resolved():
|
|
227
234
|
if isinstance(principal, User):
|
|
228
235
|
|
|
229
236
|
def _after():
|
|
230
|
-
|
|
237
|
+
_principal_resolved(principal.id)
|
|
231
238
|
|
|
232
239
|
principal.ensure_property("id", _after)
|
|
233
240
|
else:
|
|
234
|
-
|
|
241
|
+
_principal_resolved(principal)
|
|
235
242
|
|
|
236
|
-
self.
|
|
243
|
+
self.ensure_property("id", _resource_resolved)
|
|
237
244
|
return self
|
|
238
245
|
|
|
239
246
|
def get_application_permissions(self, app):
|
|
@@ -241,6 +248,7 @@ class ServicePrincipal(DirectoryObject):
|
|
|
241
248
|
return_type = ClientResult(self.context, AppRoleCollection())
|
|
242
249
|
|
|
243
250
|
def _get_application_permissions(app_id):
|
|
251
|
+
# type: (str) -> None
|
|
244
252
|
app_role_ids = [
|
|
245
253
|
app_role.app_role_id
|
|
246
254
|
for app_role in self.app_role_assigned_to
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from office365.entity import Entity
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MultiTenantOrganization(Entity):
|
|
5
|
+
"""
|
|
6
|
+
Defines an organization with more than one instance of Microsoft Entra ID. A multitenant organization enables
|
|
7
|
+
multiple tenants to collaborate like a single entity.
|
|
8
|
+
|
|
9
|
+
There can only be one multitenant organization per active tenant. It is not possible to be part of multiple
|
|
10
|
+
multitenant organizations.
|
|
11
|
+
"""
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from office365.directory.tenantinformation.information import TenantInformation
|
|
2
|
+
from office365.directory.tenantinformation.multi_organization import (
|
|
3
|
+
MultiTenantOrganization,
|
|
4
|
+
)
|
|
5
|
+
from office365.entity import Entity
|
|
6
|
+
from office365.runtime.client_result import ClientResult
|
|
7
|
+
from office365.runtime.paths.resource_path import ResourcePath
|
|
8
|
+
from office365.runtime.queries.function import FunctionQuery
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TenantRelationship(Entity):
|
|
12
|
+
"""Represent the various type of tenant relationships."""
|
|
13
|
+
|
|
14
|
+
def find_tenant_information_by_domain_name(self, domain_name):
|
|
15
|
+
"""Given a domain name, search for a tenant and read its tenantInformation. You can use this API to
|
|
16
|
+
validate tenant information and use their tenantId to configure cross-tenant access settings between you
|
|
17
|
+
and the tenant.
|
|
18
|
+
|
|
19
|
+
:param str domain_name: Primary domain name of an Azure AD tenant.
|
|
20
|
+
"""
|
|
21
|
+
return_type = ClientResult(self.context, TenantInformation())
|
|
22
|
+
params = {"domainName": domain_name}
|
|
23
|
+
qry = FunctionQuery(
|
|
24
|
+
self, "findTenantInformationByDomainName", params, return_type
|
|
25
|
+
)
|
|
26
|
+
self.context.add_query(qry)
|
|
27
|
+
return return_type
|
|
28
|
+
|
|
29
|
+
def find_tenant_information_by_tenant_id(self, tenant_id):
|
|
30
|
+
"""Given a tenant ID, search for a tenant and read its tenantInformation. You can use this API to validate
|
|
31
|
+
tenant information and use the tenantId to configure cross-tenant cross-tenant access settings between you
|
|
32
|
+
and the tenant.
|
|
33
|
+
|
|
34
|
+
:param str tenant_id: Unique tenant identifier of a Microsoft Entra tenant.
|
|
35
|
+
"""
|
|
36
|
+
return_type = ClientResult(self.context, TenantInformation())
|
|
37
|
+
params = {"tenantId": tenant_id}
|
|
38
|
+
qry = FunctionQuery(
|
|
39
|
+
self, "findTenantInformationByTenantId", params, return_type
|
|
40
|
+
)
|
|
41
|
+
self.context.add_query(qry)
|
|
42
|
+
return return_type
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def multi_tenant_organization(self):
|
|
46
|
+
"""Represents a setting to control people-related admin settings in the tenant."""
|
|
47
|
+
return self.properties.get(
|
|
48
|
+
"multiTenantOrganization",
|
|
49
|
+
MultiTenantOrganization(
|
|
50
|
+
self.context,
|
|
51
|
+
ResourcePath("multiTenantOrganization", self.resource_path),
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def get_property(self, name, default_value=None):
|
|
56
|
+
if default_value is None:
|
|
57
|
+
property_mapping = {
|
|
58
|
+
"multiTenantOrganization": self.multi_tenant_organization,
|
|
59
|
+
}
|
|
60
|
+
default_value = property_mapping.get(name, None)
|
|
61
|
+
return super(TenantRelationship, self).get_property(name, default_value)
|
office365/graph_client.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Any, Callable, List, Optional
|
|
2
2
|
|
|
3
|
+
from office365.admin.admin import Admin
|
|
4
|
+
from office365.azure_env import AzureEnvironment
|
|
3
5
|
from office365.booking.solutions.root import SolutionsRoot
|
|
4
6
|
from office365.communications.cloud_communications import CloudCommunications
|
|
5
7
|
from office365.delta_collection import DeltaCollection
|
|
@@ -36,7 +38,7 @@ from office365.directory.rolemanagement.management import RoleManagement
|
|
|
36
38
|
from office365.directory.rolemanagement.role import DirectoryRole
|
|
37
39
|
from office365.directory.security.security import Security
|
|
38
40
|
from office365.directory.serviceprincipals.collection import ServicePrincipalCollection
|
|
39
|
-
from office365.directory.
|
|
41
|
+
from office365.directory.tenantinformation.relationship import TenantRelationship
|
|
40
42
|
from office365.directory.users.collection import UserCollection
|
|
41
43
|
from office365.directory.users.user import User
|
|
42
44
|
from office365.education.root import EducationRoot
|
|
@@ -47,15 +49,14 @@ from office365.intune.devices.collection import DeviceCollection
|
|
|
47
49
|
from office365.intune.devices.management.management import DeviceManagement
|
|
48
50
|
from office365.intune.organizations.contact import OrgContact
|
|
49
51
|
from office365.intune.organizations.organization import Organization
|
|
50
|
-
from office365.onedrive.admin import Admin
|
|
51
52
|
from office365.onedrive.drives.drive import Drive
|
|
52
53
|
from office365.onedrive.shares.collection import SharesCollection
|
|
53
54
|
from office365.onedrive.sites.sites_with_root import SitesWithRoot
|
|
55
|
+
from office365.onedrive.storage.storage import Storage
|
|
54
56
|
from office365.outlook.calendar.place import Place
|
|
55
57
|
from office365.outlook.calendar.rooms.list import RoomList
|
|
56
58
|
from office365.planner.planner import Planner
|
|
57
59
|
from office365.reports.root import ReportRoot
|
|
58
|
-
from office365.runtime.auth.token_response import TokenResponse
|
|
59
60
|
from office365.runtime.client_runtime_context import ClientRuntimeContext
|
|
60
61
|
from office365.runtime.http.http_method import HttpMethod
|
|
61
62
|
from office365.runtime.http.request_options import RequestOptions
|
|
@@ -77,157 +78,73 @@ from office365.teams.viva.employee_experience import EmployeeExperience
|
|
|
77
78
|
class GraphClient(ClientRuntimeContext):
|
|
78
79
|
"""Graph Service client"""
|
|
79
80
|
|
|
80
|
-
def __init__(
|
|
81
|
-
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
token_callback=None,
|
|
84
|
+
tenant=None,
|
|
85
|
+
scopes=None,
|
|
86
|
+
token_cache=None,
|
|
87
|
+
environment=AzureEnvironment.Global,
|
|
88
|
+
):
|
|
89
|
+
# type: (Callable[[], dict], str, list[str], Any, str) -> None
|
|
90
|
+
"""
|
|
91
|
+
:param list[str] or None scopes: Scopes requested to access an API
|
|
92
|
+
:param Any token_cache: Default cache is in memory only,
|
|
93
|
+
Refer https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
|
|
94
|
+
"""
|
|
82
95
|
super(GraphClient, self).__init__()
|
|
83
96
|
self._pending_request = None
|
|
84
|
-
self.
|
|
97
|
+
self._token_callback = token_callback
|
|
98
|
+
self._tenant = tenant
|
|
99
|
+
self._token_cache = token_cache
|
|
100
|
+
self._environment = environment
|
|
101
|
+
self._scopes = scopes
|
|
85
102
|
|
|
86
|
-
|
|
87
|
-
def with_certificate(
|
|
88
|
-
tenant, client_id, thumbprint, private_key, scopes=None, token_cache=None
|
|
89
|
-
):
|
|
103
|
+
def with_certificate(self, client_id, thumbprint, private_key):
|
|
90
104
|
"""
|
|
91
105
|
Initializes the confidential client with client certificate
|
|
92
106
|
|
|
93
|
-
:param str tenant: Tenant name, for example: contoso.onmicrosoft.com
|
|
94
107
|
:param str client_id: The OAuth client id of the calling application.
|
|
95
108
|
:param str thumbprint: Thumbprint
|
|
96
109
|
:param str private_key: Private key
|
|
97
|
-
:param list[str] or None scopes: Scopes requested to access an API
|
|
98
|
-
:param Any token_cache: Default cache is in memory only,
|
|
99
|
-
Refer https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
|
|
100
110
|
"""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
authority_url = "https://login.microsoftonline.com/{0}".format(tenant)
|
|
104
|
-
import msal
|
|
105
|
-
|
|
106
|
-
app = msal.ConfidentialClientApplication(
|
|
107
|
-
client_id,
|
|
108
|
-
authority=authority_url,
|
|
109
|
-
client_credential={
|
|
110
|
-
"thumbprint": thumbprint,
|
|
111
|
-
"private_key": private_key,
|
|
112
|
-
},
|
|
113
|
-
token_cache=token_cache, # Default cache is in memory only.
|
|
114
|
-
# You can learn how to use SerializableTokenCache from
|
|
115
|
-
# https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
def _acquire_token():
|
|
119
|
-
return app.acquire_token_for_client(scopes=scopes)
|
|
120
|
-
|
|
121
|
-
return GraphClient(_acquire_token)
|
|
111
|
+
self.pending_request().with_certificate(client_id, thumbprint, private_key)
|
|
112
|
+
return self
|
|
122
113
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
tenant, client_id, client_secret, scopes=None, token_cache=None
|
|
126
|
-
):
|
|
127
|
-
# type: (str, str, str, List[str], Any) -> "GraphClient"
|
|
114
|
+
def with_client_secret(self, client_id, client_secret):
|
|
115
|
+
# type: (str, str) -> "GraphClient"
|
|
128
116
|
"""
|
|
129
117
|
Initializes the confidential client with client secret
|
|
130
118
|
|
|
131
|
-
:param str tenant: Tenant name, for example: contoso.onmicrosoft.com
|
|
132
119
|
:param str client_id: The OAuth client id of the calling application.
|
|
133
120
|
:param str client_secret: Client secret
|
|
134
|
-
:param list[str] or None scopes: Scopes requested to access an API
|
|
135
|
-
:param Any token_cache: Default cache is in memory only,
|
|
136
|
-
Refer https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
|
|
137
121
|
"""
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
authority_url = "https://login.microsoftonline.com/{0}".format(tenant)
|
|
141
|
-
import msal
|
|
142
|
-
|
|
143
|
-
app = msal.ConfidentialClientApplication(
|
|
144
|
-
client_id,
|
|
145
|
-
authority=authority_url,
|
|
146
|
-
client_credential=client_secret,
|
|
147
|
-
token_cache=token_cache,
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
def _acquire_token():
|
|
151
|
-
return app.acquire_token_for_client(scopes=scopes)
|
|
152
|
-
|
|
153
|
-
return GraphClient(_acquire_token)
|
|
122
|
+
self.pending_request().with_client_secret(client_id, client_secret)
|
|
123
|
+
return self
|
|
154
124
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
# type: (str, str, Optional[str], List[str]) -> "GraphClient"
|
|
125
|
+
def with_token_interactive(self, client_id, username=None):
|
|
126
|
+
# type: (str, Optional[str]) -> "GraphClient"
|
|
158
127
|
"""
|
|
159
128
|
Initializes the client via user credentials
|
|
160
129
|
Note: only works if your app is registered with redirect_uri as http://localhost
|
|
161
130
|
|
|
162
|
-
:param str tenant: Tenant name, for example: contoso.onmicrosoft.com
|
|
163
131
|
:param str client_id: The OAuth client id of the calling application.
|
|
164
132
|
:param str username: Typically a UPN in the form of an email address.
|
|
165
|
-
:param list[str] or None scopes: Scopes requested to access an API
|
|
166
133
|
"""
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
app = msal.PublicClientApplication(client_id, authority=authority_url)
|
|
173
|
-
|
|
174
|
-
def _acquire_token():
|
|
175
|
-
# The pattern to acquire a token looks like this.
|
|
176
|
-
result = None
|
|
177
|
-
|
|
178
|
-
# Firstly, check the cache to see if this end user has signed in before
|
|
179
|
-
accounts = app.get_accounts(username=username)
|
|
180
|
-
if accounts:
|
|
181
|
-
chosen = accounts[0] # Assuming the end user chose this one to proceed
|
|
182
|
-
# Now let's try to find a token in cache for this account
|
|
183
|
-
result = app.acquire_token_silent(scopes, account=chosen)
|
|
184
|
-
|
|
185
|
-
if not result:
|
|
186
|
-
result = app.acquire_token_interactive(
|
|
187
|
-
scopes,
|
|
188
|
-
login_hint=username,
|
|
189
|
-
)
|
|
190
|
-
return result
|
|
191
|
-
|
|
192
|
-
return GraphClient(_acquire_token)
|
|
193
|
-
|
|
194
|
-
@staticmethod
|
|
195
|
-
def with_username_and_password(tenant, client_id, username, password, scopes=None):
|
|
196
|
-
# type: (str, str, str, str, List[str]) -> "GraphClient"
|
|
134
|
+
self.pending_request().with_token_interactive(client_id, username)
|
|
135
|
+
return self
|
|
136
|
+
|
|
137
|
+
def with_username_and_password(self, client_id, username, password):
|
|
138
|
+
# type: (str, str, str) -> "GraphClient"
|
|
197
139
|
"""
|
|
198
140
|
Initializes the client via user credentials
|
|
199
141
|
|
|
200
|
-
:param str tenant: Tenant name, for example: contoso.onmicrosoft.com
|
|
201
142
|
:param str client_id: The OAuth client id of the calling application.
|
|
202
143
|
:param str username: Typically a UPN in the form of an email address.
|
|
203
144
|
:param str password: The password.
|
|
204
|
-
:param list[str] or None scopes: Scopes requested to access an API
|
|
205
145
|
"""
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
authority_url = "https://login.microsoftonline.com/{0}".format(tenant)
|
|
209
|
-
import msal
|
|
210
|
-
|
|
211
|
-
app = msal.PublicClientApplication(
|
|
212
|
-
authority=authority_url,
|
|
213
|
-
client_id=client_id,
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
def _acquire_token():
|
|
217
|
-
result = None
|
|
218
|
-
accounts = app.get_accounts(username=username)
|
|
219
|
-
if accounts:
|
|
220
|
-
result = app.acquire_token_silent(scopes, account=accounts[0])
|
|
221
|
-
|
|
222
|
-
if not result:
|
|
223
|
-
result = app.acquire_token_by_username_password(
|
|
224
|
-
username=username,
|
|
225
|
-
password=password,
|
|
226
|
-
scopes=scopes,
|
|
227
|
-
)
|
|
228
|
-
return result
|
|
229
|
-
|
|
230
|
-
return GraphClient(_acquire_token)
|
|
146
|
+
self.pending_request().with_username_and_password(client_id, username, password)
|
|
147
|
+
return self
|
|
231
148
|
|
|
232
149
|
def execute_batch(self, items_per_batch=20, success_callback=None):
|
|
233
150
|
"""Constructs and submit a batch request
|
|
@@ -238,7 +155,7 @@ class GraphClient(ClientRuntimeContext):
|
|
|
238
155
|
:param (List[ClientObject|ClientResult])-> None success_callback: A success callback
|
|
239
156
|
"""
|
|
240
157
|
batch_request = ODataV4BatchRequest(V4JsonFormat())
|
|
241
|
-
batch_request.beforeExecute += self.
|
|
158
|
+
batch_request.beforeExecute += self.pending_request().authenticate_request
|
|
242
159
|
while self.has_pending_request:
|
|
243
160
|
qry = self._get_next_query(items_per_batch)
|
|
244
161
|
batch_request.execute_query(qry)
|
|
@@ -249,8 +166,11 @@ class GraphClient(ClientRuntimeContext):
|
|
|
249
166
|
def pending_request(self):
|
|
250
167
|
# type: () -> GraphRequest
|
|
251
168
|
if self._pending_request is None:
|
|
252
|
-
self._pending_request = GraphRequest(
|
|
253
|
-
|
|
169
|
+
self._pending_request = GraphRequest(
|
|
170
|
+
tenant=self._tenant, environment=self._environment
|
|
171
|
+
)
|
|
172
|
+
if callable(self._token_callback):
|
|
173
|
+
self._pending_request.with_access_token(self._token_callback)
|
|
254
174
|
self._pending_request.beforeExecute += self._build_specific_query
|
|
255
175
|
return self._pending_request
|
|
256
176
|
|
|
@@ -266,13 +186,6 @@ class GraphClient(ClientRuntimeContext):
|
|
|
266
186
|
elif isinstance(self.current_query, DeleteEntityQuery):
|
|
267
187
|
request.method = HttpMethod.Delete
|
|
268
188
|
|
|
269
|
-
def _authenticate_request(self, request):
|
|
270
|
-
# type: (RequestOptions) -> None
|
|
271
|
-
"""Authenticate request."""
|
|
272
|
-
token_json = self._acquire_token_callback()
|
|
273
|
-
token = TokenResponse.from_json(token_json)
|
|
274
|
-
request.ensure_header("Authorization", "Bearer {0}".format(token.accessToken))
|
|
275
|
-
|
|
276
189
|
@property
|
|
277
190
|
def admin(self):
|
|
278
191
|
"""A container for administrator functionality for SharePoint and OneDrive."""
|
|
@@ -475,6 +388,13 @@ class GraphClient(ClientRuntimeContext):
|
|
|
475
388
|
"""
|
|
476
389
|
return InformationProtection(self, ResourcePath("informationProtection"))
|
|
477
390
|
|
|
391
|
+
@property
|
|
392
|
+
def storage(self):
|
|
393
|
+
"""
|
|
394
|
+
Facilitates the structures of fileStorageContainers.
|
|
395
|
+
"""
|
|
396
|
+
return Storage(self, ResourcePath("storage"))
|
|
397
|
+
|
|
478
398
|
@property
|
|
479
399
|
def subscriptions(self):
|
|
480
400
|
"""
|