Skip to content

Commit 98d7a5d

Browse files
committed
new types & methods for Teams API
1 parent 1a2e6d6 commit 98d7a5d

File tree

23 files changed

+359
-12
lines changed

23 files changed

+359
-12
lines changed

examples/reports/get_user_mfa_status.py

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""
2+
Get a list of the authentication methods registered for a user as defined in the userRegistrationDetails object.
3+
This method doesn't work for disabled users.
4+
5+
"""
16
from office365.graph_client import GraphClient
27
from tests import test_client_id, test_client_secret, test_tenant
38

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from office365.runtime.client_value import ClientValue
2+
3+
4+
class BroadcastMeetingSettings(ClientValue):
5+
"""Represents settings related to a live event in Microsoft Teams."""

office365/communications/onlinemeetings/online_meeting.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def video_teleconference_id(self):
124124
@property
125125
def recordings(self):
126126
# type: () -> EntityCollection[CallRecording]
127-
"""he recordings of an online meeting"""
127+
"""The recordings of an online meeting"""
128128
return self.properties.get(
129129
"recordings",
130130
EntityCollection(

office365/directory/audit/directory.py

+31
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
from typing import Optional
33

44
from office365.directory.audit.activity_initiator import AuditActivityInitiator
5+
from office365.directory.audit.target_resource import TargetResource
56
from office365.entity import Entity
7+
from office365.runtime.client_value_collection import ClientValueCollection
68

79

810
class DirectoryAudit(Entity):
@@ -25,6 +27,14 @@ def activity_display_name(self):
2527
"""
2628
return self.properties.get("activityDisplayName", None)
2729

30+
@property
31+
def additional_details(self):
32+
# type: () -> Optional[dict]
33+
"""
34+
Indicates additional details on the activity.
35+
"""
36+
return self.properties.get("additionalDetails", None)
37+
2838
@property
2939
def category(self):
3040
# type: () -> Optional[str]
@@ -69,6 +79,14 @@ def logged_by_service(self):
6979
"""
7080
return self.properties.get("loggedByService", None)
7181

82+
@property
83+
def result(self):
84+
# type: () -> Optional[str]
85+
"""
86+
Indicates the result of the activity. Possible values are: success, failure, timeout, unknownFutureValue.
87+
"""
88+
return self.properties.get("result", None)
89+
7290
@property
7391
def result_reason(self):
7492
# type: () -> Optional[str]
@@ -77,11 +95,24 @@ def result_reason(self):
7795
"""
7896
return self.properties.get("resultReason", None)
7997

98+
@property
99+
def target_resources(self):
100+
# type: () -> Optional[str]
101+
"""
102+
Indicates information on which resource was changed due to the activity. Target Resource Type can be User,
103+
Device, Directory, App, Role, Group, Policy or Other. Supports $filter (eq) for id and displayName;
104+
and $filter (startswith) for displayName.
105+
"""
106+
return self.properties.get(
107+
"targetResources", ClientValueCollection(TargetResource)
108+
)
109+
80110
def get_property(self, name, default_value=None):
81111
if default_value is None:
82112
property_mapping = {
83113
"activityDateTime": self.activity_datetime,
84114
"initiatedBy": self.initiated_by,
115+
"targetResources": self.target_resources,
85116
}
86117
default_value = property_mapping.get(name, None)
87118
return super(DirectoryAudit, self).get_property(name, default_value)

office365/directory/audit/signins/signin.py

+14
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@
33

44
from office365.directory.audit.signins.location import SignInLocation
55
from office365.directory.audit.signins.status import SignInStatus
6+
from office365.directory.policies.applied_conditional_access import (
7+
AppliedConditionalAccessPolicy,
8+
)
69
from office365.entity import Entity
710
from office365.intune.devices.detail import DeviceDetail
11+
from office365.runtime.client_value_collection import ClientValueCollection
812

913

1014
class SignIn(Entity):
@@ -24,6 +28,15 @@ def app_id(self):
2428
"""Unique GUID representing the app ID in the Azure Active Directory."""
2529
return self.properties.get("appId", None)
2630

31+
@property
32+
def applied_conditional_access_policies(self):
33+
# type: () -> Optional[str]
34+
"""Provides a list of conditional access policies that the corresponding sign-in activity triggers."""
35+
return self.properties.get(
36+
"appliedConditionalAccessPolicies",
37+
ClientValueCollection(AppliedConditionalAccessPolicy),
38+
)
39+
2740
@property
2841
def client_app_used(self):
2942
# type: () -> Optional[str]
@@ -122,6 +135,7 @@ def status(self):
122135
def get_property(self, name, default_value=None):
123136
if default_value is None:
124137
property_mapping = {
138+
"appliedConditionalAccessPolicies": self.applied_conditional_access_policies,
125139
"createdDateTime": self.created_datetime,
126140
"deviceDetail": self.device_detail,
127141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from office365.runtime.client_value import ClientValue
2+
3+
4+
class TargetResource(ClientValue):
5+
"""Represents target resource types associated with audit activity."""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from office365.directory.identitygovernance.accessreview.stages import AccessReviewStageCollection
2+
from office365.entity import Entity
3+
from office365.runtime.paths.resource_path import ResourcePath
4+
5+
6+
class AccessReviewInstance(Entity):
7+
"""
8+
Represents a Microsoft Entra access review recurrence. If the parent accessReviewScheduleDefinition is a
9+
recurring access review, instances represent each recurrence. A review that does not recur will have exactly
10+
one instance. Instances also represent each unique group being reviewed in the schedule definition.
11+
If a schedule definition reviews multiple groups, each group will have a unique instance for each recurrence.
12+
13+
Every accessReviewInstance contains a list of decisions that reviewers can take action on.
14+
There is one decision per identity being reviewed.
15+
"""
16+
17+
@property
18+
def stages(self):
19+
# type: () -> AccessReviewStageCollection
20+
"""If the instance has multiple stages, this returns the collection of stages.
21+
A new stage will only be created when the previous stage ends"""
22+
return self.properties.get(
23+
"stages",
24+
AccessReviewStageCollection(
25+
self.context, ResourcePath("stages", self.resource_path)
26+
),
27+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from office365.entity import Entity
2+
3+
4+
class AccessReviewStage(Entity):
5+
"""
6+
Represents a stage of a Microsoft Entra access review. If the parent accessReviewScheduleDefinition has defined
7+
the stageSettings property, the accessReviewInstance is comprised of up to three subsequent stages.
8+
Each stage may have a different set of reviewers who can act on the stage decisions, and settings determining
9+
which decisions pass from stage to stage.
10+
11+
Every accessReviewStage contains a list of decision items for reviewers.
12+
There's only one decision per identity being reviewed.
13+
"""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from office365.directory.identitygovernance.accessreview.stage import AccessReviewStage
2+
from office365.entity_collection import EntityCollection
3+
4+
5+
class AccessReviewStageCollection(EntityCollection[AccessReviewStage]):
6+
"""AccessReviewStage collection"""
7+
8+
def __init__(self, context, resource_path=None):
9+
super(AccessReviewStageCollection, self).__init__(context, AccessReviewStage, resource_path)

office365/directory/insights/trending.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from datetime import datetime
2+
from typing import Optional
3+
4+
from office365.directory.insights.resource_reference import ResourceReference
15
from office365.entity import Entity
26
from office365.runtime.paths.resource_path import ResourcePath
37

@@ -8,10 +12,31 @@ class Trending(Entity):
812
OneDrive files, and files stored on SharePoint team sites can trend around the user.
913
"""
1014

15+
@property
16+
def last_modified_datetime(self):
17+
# type: () -> Optional[datetime]
18+
"""Gets date and time the item was last modified."""
19+
return self.properties.get("lastModifiedDateTime", datetime.min)
20+
21+
@property
22+
def resource_reference(self):
23+
# type: () -> ResourceReference
24+
"""Reference properties of the trending document, such as the url and type of the document."""
25+
return self.properties.get("resourceReference", ResourceReference())
26+
1127
@property
1228
def resource(self):
1329
"""Used for navigating to the trending document."""
1430
return self.properties.get(
1531
"resource",
1632
Entity(self.context, ResourcePath("resource", self.resource_path)),
1733
)
34+
35+
def get_property(self, name, default_value=None):
36+
if default_value is None:
37+
property_mapping = {
38+
"lastModifiedDateTime": self.last_modified_datetime,
39+
"resourceReference": self.resource_reference,
40+
}
41+
default_value = property_mapping.get(name, None)
42+
return super(Trending, self).get_property(name, default_value)

office365/directory/licenses/assignment_state.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ def __init__(
1818
assigned_by_group=None,
1919
disabled_plans=None,
2020
error=None,
21-
lastUpdatedDateTime=None,
22-
skuId=None,
21+
last_updated_datetime=None,
22+
sku_id=None,
2323
state=None,
2424
):
2525
"""
@@ -31,13 +31,13 @@ def __init__(
3131
The possible values are CountViolation, MutuallyExclusiveViolation, DependencyViolation,
3232
ProhibitedInUsageLocationViolation, UniquenessViolation, and Other.
3333
For more information on how to identify and resolve license assignment errors, see here.
34-
:param str skuId: The unique identifier for the SKU. Read-Only.
34+
:param str sku_id: The unique identifier for the SKU. Read-Only.
3535
:param str state: Indicate the current state of this assignment. Read-Only.
3636
The possible values are Active, ActiveWithError, Disabled, and Error.
3737
"""
3838
self.assignedByGroup = assigned_by_group
3939
self.disabledPlans = StringCollection(disabled_plans)
4040
self.error = error
41-
self.lastUpdatedDateTime = lastUpdatedDateTime
42-
self.skuId = skuId
41+
self.lastUpdatedDateTime = last_updated_datetime
42+
self.skuId = sku_id
4343
self.state = state
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from office365.entity import Entity
2+
3+
4+
class ScopedRoleMembership(Entity):
5+
"""A scoped-role membership describes a user's membership of a directory role that is further
6+
scoped to an Administrative Unit. Scoped-role membership provides a mechanism to allow a tenant-wide company
7+
administrator to delegate administrative privileges to a user, to manage users and groups in a subset
8+
of the organization."""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from office365.runtime.client_value import ClientValue
2+
from office365.runtime.types.collections import StringCollection
3+
4+
5+
class AppliedConditionalAccessPolicy(ClientValue):
6+
"""Indicates the attributes related to applied conditional access policy or policies that are triggered
7+
by a sign-in activity.
8+
9+
The data in this object is returned only for callers with privileges to read conditional access data.
10+
For more information, see Permissions for viewing applied conditional access (CA) policies in sign-ins.
11+
"""
12+
13+
def __init__(
14+
self,
15+
display_name=None,
16+
enforced_grant_controls=None,
17+
enforced_session_controls=None,
18+
id_=None,
19+
result=None,
20+
):
21+
"""
22+
:param str display_name: Refers to the name of the conditional access policy
23+
:param list[str] enforced_grant_controls: Refers to the grant controls enforced by the conditional access policy
24+
:param list[str] enforced_session_controls: Refers to the session controls enforced by the conditional
25+
access policy
26+
"""
27+
self.displayName = display_name
28+
self.enforcedGrantControls = StringCollection(enforced_grant_controls)
29+
self.enforcedSessionControls = StringCollection(enforced_session_controls)
30+
self.id = id_
31+
self.result = result

office365/directory/rolemanagement/role.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from typing import Optional
22

33
from office365.directory.object import DirectoryObject
4+
from office365.directory.permissions.scoped_role_membership import ScopedRoleMembership
5+
from office365.entity_collection import EntityCollection
46
from office365.runtime.paths.resource_path import ResourcePath
57

68

@@ -36,3 +38,16 @@ def members(self):
3638
self.context, ResourcePath("members", self.resource_path)
3739
),
3840
)
41+
42+
@property
43+
def scoped_members(self):
44+
"""Members of this directory role that are scoped to administrative units. """
45+
46+
return self.properties.get(
47+
"scopedMembers",
48+
EntityCollection(
49+
self.context,
50+
ScopedRoleMembership,
51+
ResourcePath("scopedMembers", self.resource_path),
52+
),
53+
)
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1+
from typing import TYPE_CHECKING
2+
13
from office365.reports.report import Report
24
from office365.runtime.client_result import ClientResult
35
from office365.runtime.queries.function import FunctionQuery
46

7+
if TYPE_CHECKING:
8+
from office365.reports.root import ReportRoot
9+
510

6-
def create_report_query(report_root, report_name, period=None):
11+
def create_report_query(report_root, report_name, period=None, return_stream=False):
12+
# type: (ReportRoot, str, str, bool) -> FunctionQuery
713
"""
814
Construct Report query
915
10-
:param office365.reports.root.ReportRoot report_root: Report container
16+
:param ReportRoot report_root: Report container
1117
:param str report_name: Report name
1218
:param str period: Specifies the length of time over which the report is aggregated.
1319
The supported values for {period_value} are: D7, D30, D90, and D180. These values follow the format
1420
Dn where n represents the number of days over which the report is aggregated. Required.
21+
:param bool return_stream: If true, return a stream of report data.
1522
"""
1623
params = {
1724
"period": period,
1825
}
19-
return_type = ClientResult(report_root.context, Report())
26+
if return_stream:
27+
return_type = ClientResult(report_root.context, bytes())
28+
else:
29+
return_type = ClientResult(report_root.context, Report())
2030
return FunctionQuery(report_root, report_name, params, return_type)

office365/reports/root.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def get_email_activity_user_detail(self, period):
8989
The supported values for {period_value} are: D7, D30, D90, and D180. These values follow the format
9090
Dn where n represents the number of days over which the report is aggregated. Required.
9191
"""
92-
qry = create_report_query(self, "getEmailActivityUserDetail", period)
92+
qry = create_report_query(self, "getEmailActivityUserDetail", period, return_stream=True)
9393
self.context.add_query(qry)
9494
return qry.return_type
9595

0 commit comments

Comments
 (0)