Skip to content

Commit

Permalink
SharePoint API new types and model updates
Browse files Browse the repository at this point in the history
  • Loading branch information
vgrem committed Sep 8, 2024
1 parent 39c31d4 commit 4ec81b6
Show file tree
Hide file tree
Showing 19 changed files with 256 additions and 30 deletions.
3 changes: 0 additions & 3 deletions examples/directory/applications/has_delegated_perms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
from tests import (
test_admin_principal_name,
test_client_id,
test_password,
test_tenant,
test_user_principal_name,
test_username,
)

# client = GraphClient.with_username_and_password(
Expand Down
2 changes: 1 addition & 1 deletion examples/sharepoint/lists/read_properties.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Retrieve default properties of a List
Retrieve default properties of a SharePoint List
"""

from office365.sharepoint.client_context import ClientContext
Expand Down
12 changes: 12 additions & 0 deletions examples/sharepoint/lists/read_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""
Exports a SharePoint List schema
"""

from office365.sharepoint.client_context import ClientContext
from tests import test_client_credentials, test_team_site_url

ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
target_list = (
ctx.web.lists.get_by_title("Site Pages").select(["SchemaXml"]).get().execute_query()
)
print(target_list.schema_xml)
84 changes: 73 additions & 11 deletions generator/metadata/SharePoint.xml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions office365/backuprestore/root.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from office365.backuprestore.service_status import ServiceStatus
from office365.directory.protection.policy.one_drive_for_business import (
OneDriveForBusinessProtectionPolicy,
)
Expand All @@ -9,6 +10,11 @@
class BackupRestoreRoot(Entity):
"""Represents the Microsoft 365 Backup Storage service in a tenant."""

@property
def service_status(self):
"""Represents the tenant-level status of the Backup Storage service."""
return self.properties.get("serviceStatus", ServiceStatus())

@property
def one_drive_for_business_protection_policies(self):
"""The list of OneDrive for Business restore sessions available in the tenant."""
Expand All @@ -26,6 +32,7 @@ def one_drive_for_business_protection_policies(self):
def get_property(self, name, default_value=None):
if default_value is None:
property_mapping = {
"serviceStatus": self.service_status,
"oneDriveForBusinessProtectionPolicies": self.one_drive_for_business_protection_policies,
}
default_value = property_mapping.get(name, None)
Expand Down
5 changes: 5 additions & 0 deletions office365/backuprestore/service_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from office365.runtime.client_value import ClientValue


class ServiceStatus(ClientValue):
"""Represents the tenant-level service status of the backup service."""
6 changes: 5 additions & 1 deletion office365/directory/serviceprincipals/service_principal.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,11 @@ def _get_delegated(col):
if scope is None:
[return_type.add_child(g) for g in col if g.resource_id == self.id]
else:
[return_type.add_child(g) for g in col if g.scope == scope and g.resource_id == self.id]
[
return_type.add_child(g)
for g in col
if g.scope == scope and g.resource_id == self.id
]

def _principal_resolved(principal_id):
# type: (str) -> None
Expand Down
26 changes: 26 additions & 0 deletions office365/intune/devices/management/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
)
from office365.intune.devices.managed import ManagedDevice
from office365.intune.devices.management.reports.reports import DeviceManagementReports
from office365.intune.devices.management.terms_and_conditions import TermsAndConditions
from office365.intune.devices.management.virtual_endpoint import VirtualEndpoint
from office365.runtime.client_result import ClientResult
from office365.runtime.client_value_collection import ClientValueCollection
from office365.runtime.paths.resource_path import ResourcePath
Expand Down Expand Up @@ -40,6 +42,28 @@ def audit_events(self):
),
)

@property
def virtual_endpoint(self):
""""""
return self.properties.get(
"virtualEndpoint",
VirtualEndpoint(
self.context, ResourcePath("virtualEndpoint", self.resource_path)
),
)

@property
def terms_and_conditions(self):
""""""
return self.properties.get(
"termsAndConditions",
EntityCollection(
self.context,
TermsAndConditions,
ResourcePath("termsAndConditions", self.resource_path),
),
)

@property
def device_categories(self):
""""""
Expand Down Expand Up @@ -98,6 +122,8 @@ def get_property(self, name, default_value=None):
"deviceEnrollmentConfigurations": self.device_enrollment_configurations,
"intuneBrand": self.intune_brand,
"managedDevices": self.managed_devices,
"termsAndConditions": self.terms_and_conditions,
"virtualEndpoint": self.virtual_endpoint,
}
default_value = property_mapping.get(name, None)
return super(DeviceManagement, self).get_property(name, default_value)
10 changes: 10 additions & 0 deletions office365/intune/devices/management/terms_and_conditions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from office365.entity import Entity


class TermsAndConditions(Entity):
"""
A termsAndConditions entity represents the metadata and contents of a given Terms and Conditions (T&C) policy.
T&C policies’ contents are presented to users upon their first attempt to enroll into Intune and subsequently
upon edits where an administrator has required re-acceptance. They enable administrators to communicate
the provisions to which a user must agree in order to have devices enrolled into Intune.
"""
8 changes: 8 additions & 0 deletions office365/intune/devices/management/virtual_endpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from office365.entity import Entity


class VirtualEndpoint(Entity):
"""
Use the Cloud PC API to provision and manage virtual desktops for employees in an organization,
or along with the Intune API to manage physical and virtual endpoints.
"""
Empty file.
9 changes: 9 additions & 0 deletions office365/sharepoint/brandcenter/brand_center.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from office365.sharepoint.entity import Entity


class BrandCenter(Entity):
"""
The SharePoint brand center API offers a centralized branding management application
that empowers your brand managers or designated brand owners to help your organization to customize
the look and feel of their experiences.
"""
5 changes: 5 additions & 0 deletions office365/sharepoint/brandcenter/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from office365.runtime.client_value import ClientValue


class BrandCenterConfiguration(ClientValue):
""" """
8 changes: 8 additions & 0 deletions office365/sharepoint/client_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,14 @@ def announcements(self):

return AnnouncementsController(self, ResourcePath("Announcements"))

@property
def brand_center(self):
"""Alias to BrandCenter"""

from office365.sharepoint.brandcenter.brand_center import BrandCenter

return BrandCenter(self, ResourcePath("BrandCenter"))

@property
def client_people_picker(self):
"""Query principals service alias"""
Expand Down
3 changes: 3 additions & 0 deletions office365/sharepoint/contenttypes/fieldlinks/collection.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing_extensions import Self

from office365.runtime.paths.service_operation import ServiceOperationPath
from office365.runtime.queries.create_entity import CreateEntityQuery
from office365.runtime.queries.service_operation import ServiceOperationQuery
Expand Down Expand Up @@ -52,6 +54,7 @@ def get_by_id(self, _id):
)

def reorder(self, internal_names):
# type: (list[str]) -> Self
"""
Rearranges the collection of field links in the order in which field internal names are specified.
Expand Down
44 changes: 43 additions & 1 deletion office365/sharepoint/navigation/menu_node.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,57 @@
from office365.runtime.client_value import ClientValue
from office365.runtime.client_value_collection import ClientValueCollection
from office365.sharepoint.translation.resource_entry import SPResourceEntry


class MenuNode(ClientValue):
"""Represents a navigation node in the navigation hierarchy. A navigation hierarchy is a tree structure of
navigation nodes."""

def __init__(self, current_lcid=None, title=None):
def __init__(
self,
audience_ids=None,
current_lcid=None,
title=None,
is_deleted=None,
is_hidden=None,
key=None,
nodes=None,
node_type=None,
open_in_new_window=None,
simple_url=None,
translations=None,
):
"""
:param list[str] audience_ids:
:param int current_lcid:
:param str title: Specifies the title of the navigation node. The value is in the preferred language of the
user, if available, or is in the default language of the site (2) as a fallback.
:param int node_type: Specifies the type of the navigation node.
:param bool is_deleted: A client MUST use this property set to TRUE to indicate that this node MUST be
deleted by the server. When set to TRUE the server MUST delete the node including all the child nodes
when present. When set to FALSE the server SHOULD NOT delete this node.
:param bool is_hidden: Specifies whether the node will be hidden in the navigation menu. During editing,
all nodes temporarily become visible so that they can be edited.
:param str key: Specifies the identifier for the navigation node in the menu tree. If the navigation node does
not exist on the protocol server, this value MUST be an empty string.
:param list[MenuNode] nodes:
:param bool open_in_new_window:
:param str simple_url: If the NodeType (section 3.2.5.244.1.1.7) property is set to "SimpleLink",
this property represents the URL of the navigation node. The URL can be relative or absolute.
If the value is a relative URL, it can begin with URL tokens "~site" and "~sitecollection".
These tokens indicate that the URL is either relative to the site (2) or to the site collection
respectively. If the NodeType (section 3.2.5.244.1.1.7) property is not set to "SimpleLink",
the value MUST be an empty string.
:param list[SPResourceEntry] translations:
"""
self.AudienceIds = audience_ids
self.CurrentLCID = current_lcid
self.IsDeleted = is_deleted
self.IsHidden = is_hidden
self.Key = key
self.Nodes = ClientValueCollection(MenuNode, nodes)
self.NodeType = node_type
self.OpenInNewWindow = open_in_new_window
self.SimpleUrl = simple_url
self.Title = title
self.Translations = ClientValueCollection(SPResourceEntry, translations)
40 changes: 40 additions & 0 deletions office365/sharepoint/webs/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -2311,9 +2311,49 @@ def recycle_bin(self):

@property
def recycle_bin_enabled(self):
# type: () -> Optional[bool]
"""Specifies whether the Recycle Bin is enabled."""
return self.properties.get("RecycleBinEnabled", None)

@property
def related_hub_site_ids(self):
# type: () -> Optional[str]
""" """
return self.properties.get("RelatedHubSiteIds", None)

@property
def request_access_email(self):
# type: () -> Optional[str]
"""Gets the e-mail address to which requests for access are sent."""
return self.properties.get("RequestAccessEmail", None)

@property
def save_site_as_template_enabled(self):
# type: () -> Optional[bool]
"""Specifies if the site (2) can be saved as a site template.
A feature that creates content which is not compatible for a site template can set this value to false to
stop users of this site (2) from generating an invalid site template.
A feature ought to never set this value to true when it is deactivated or at any other time since another
feature might have created content that is not compatible in a site template.
Setting this value to false, if it was true, will result in a site template that is not supported.
"""
return self.properties.get("SaveSiteAsTemplateEnabled", None)

@property
def search_box_in_navbar(self):
# type: () -> Optional[int]
"""Gets the e-mail address to which requests for access are sent."""
return self.properties.get("SearchBoxInNavBar", None)

@property
def search_box_placeholder_text(self):
# type: () -> Optional[str]
"""Gets the placeholder text in SharePoint online search box for a given (sub) site."""
return self.properties.get("SearchBoxPlaceholderText", None)

@property
def navigation(self):
"""Specifies the navigation structure on the site (2), including the Quick Launch area and the link bar."""
Expand Down
12 changes: 0 additions & 12 deletions tests/sharepoint/sharepoint_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,3 @@ def ensure_list(web, list_properties):
if len(lists) == 1
else web.lists.add(list_properties).execute_query()
)

@staticmethod
def read_file_as_text(path):
with open(path, "r") as content_file:
file_content = content_file.read()
return file_content

@staticmethod
def read_file_as_binary(path):
with open(path, "rb") as content_file:
file_content = content_file.read()
return file_content
2 changes: 1 addition & 1 deletion tests/sharepoint/test_navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def setUpClass(cls):
# cls.assertTrue(result.value)

# def test1_get_global_nav(self):
# result = admin_client.navigation_service.global_nav().execute_query()
# result = self.client.navigation_service.global_nav().execute_query()
# self.assertIsNotNone(result.value)

def test_2_is_global_nav_enabled(self):
Expand Down

0 comments on commit 4ec81b6

Please sign in to comment.