gateway/modules/methods/methodSharepoint.py
2025-06-10 18:19:33 +02:00

390 lines
No EOL
15 KiB
Python

from typing import Dict, Any, Optional
import logging
from datetime import datetime, UTC
from office365.runtime.auth.user_credential import UserCredential
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File
from office365.sharepoint.lists.list import List
from office365.sharepoint.lists.list_creation_information import ListCreationInformation
from modules.methods.methodBase import MethodBase, AuthSource, MethodResult
from modules.models.userConnection import UserConnection
logger = logging.getLogger(__name__)
class MethodSharepoint(MethodBase):
"""SharePoint method implementation for document operations"""
def __init__(self):
super().__init__()
self.name = "sharepoint"
self.description = "Handle SharePoint document operations like search, read, and write"
self.authSource = AuthSource.MICROSOFT
@property
def actions(self) -> Dict[str, Dict[str, Any]]:
"""Available actions and their parameters"""
return {
"search": {
"description": "Search SharePoint documents",
"retryMax": 3,
"timeout": 30,
"parameters": {
"query": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True},
"listName": {"type": "string", "required": False},
"maxResults": {"type": "number", "required": False}
}
},
"read": {
"description": "Read SharePoint document content",
"retryMax": 2,
"timeout": 30,
"parameters": {
"fileUrl": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True}
}
},
"write": {
"description": "Write content to SharePoint document",
"retryMax": 2,
"timeout": 30,
"parameters": {
"fileUrl": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True},
"content": {"type": "string", "required": True},
"contentType": {"type": "string", "required": False}
}
},
"readList": {
"description": "Read items from SharePoint list",
"retryMax": 2,
"timeout": 30,
"parameters": {
"siteUrl": {"type": "string", "required": True},
"listName": {"type": "string", "required": True},
"query": {"type": "string", "required": False},
"fields": {"type": "array", "required": False}
}
},
"writeList": {
"description": "Write items to SharePoint list",
"retryMax": 2,
"timeout": 30,
"parameters": {
"siteUrl": {"type": "string", "required": True},
"listName": {"type": "string", "required": True},
"items": {"type": "array", "required": True}
}
},
"createList": {
"description": "Create a new SharePoint list",
"retryMax": 2,
"timeout": 30,
"parameters": {
"siteUrl": {"type": "string", "required": True},
"listName": {"type": "string", "required": True},
"description": {"type": "string", "required": False},
"template": {"type": "string", "required": False},
"fields": {"type": "array", "required": False}
}
}
}
async def execute(self, action: str, parameters: Dict[str, Any], authData: Optional[Dict[str, Any]] = None) -> MethodResult:
"""Execute SharePoint method"""
try:
# Validate parameters
if not await self.validateParameters(action, parameters):
return self._createResult(
success=False,
data={"error": f"Invalid parameters for {action}"}
)
# Get UserConnection from auth_data
if not authData or "userConnection" not in authData:
return self._createResult(
success=False,
data={"error": "UserConnection required for SharePoint operations"}
)
userConnection: UserConnection = authData["userConnection"]
# Execute action
if action == "search":
return await self._search_documents(parameters, userConnection)
elif action == "read":
return await self._read_document(parameters, userConnection)
elif action == "write":
return await self._write_document(parameters, userConnection)
elif action == "readList":
return await self._readList(parameters, userConnection)
elif action == "writeList":
return await self._writeList(parameters, userConnection)
elif action == "createList":
return await self._createList(parameters, userConnection)
else:
return self._createResult(
success=False,
data={"error": f"Unknown action: {action}"}
)
except Exception as e:
logger.error(f"Error executing SharePoint {action}: {e}")
return self._createResult(
success=False,
data={"error": str(e)}
)
async def _search_documents(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Search SharePoint documents"""
try:
siteUrl = parameters["siteUrl"]
query = parameters["query"]
listName = parameters.get("listName")
maxResults = parameters.get("maxResults", 10)
# Create SharePoint context
ctx = ClientContext(siteUrl).with_credentials(
UserCredential(userConnection.authToken, userConnection.refreshToken)
)
# Search in specific list or entire site
if listName:
targetList = ctx.web.lists.get_by_title(listName)
items = targetList.items.filter(f"Title eq '{query}'").top(maxResults).get().execute_query()
results = [{
"title": item.properties["Title"],
"url": item.properties["FileRef"],
"modified": item.properties["Modified"],
"created": item.properties["Created"]
} for item in items]
else:
# Search entire site
search_results = ctx.search(query).execute_query()
results = [{
"title": result.properties["Title"],
"url": result.properties["Path"],
"modified": result.properties["LastModifiedTime"],
"created": result.properties["Created"]
} for result in search_results[:maxResults]]
return self._createResult(
success=True,
data={
"query": query,
"results": results
}
)
except Exception as e:
logger.error(f"Error searching SharePoint documents: {e}")
return self._createResult(
success=False,
data={"error": f"Search failed: {str(e)}"}
)
async def _read_document(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Read SharePoint document content"""
try:
siteUrl = parameters["siteUrl"]
fileUrl = parameters["fileUrl"]
# Create SharePoint context
ctx = ClientContext(siteUrl).with_credentials(
UserCredential(userConnection.authToken, userConnection.refreshToken)
)
# Get file
file = ctx.web.get_file_by_server_relative_url(fileUrl)
file_content = file.read().execute_query()
return self._createResult(
success=True,
data={
"url": fileUrl,
"content": file_content.content.decode('utf-8'),
"modified": file.properties["TimeLastModified"],
"size": file.properties["Length"]
}
)
except Exception as e:
logger.error(f"Error reading SharePoint document: {e}")
return self._createResult(
success=False,
data={"error": f"Read failed: {str(e)}"}
)
async def _write_document(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Write content to SharePoint document"""
try:
siteUrl = parameters["siteUrl"]
fileUrl = parameters["fileUrl"]
content = parameters["content"]
contentType = parameters.get("contentType", "text/plain")
# Create SharePoint context
ctx = ClientContext(siteUrl).with_credentials(
UserCredential(userConnection.authToken, userConnection.refreshToken)
)
# Get or create file
try:
file = ctx.web.get_file_by_server_relative_url(fileUrl)
except:
# Create new file
folderUrl = "/".join(fileUrl.split("/")[:-1])
fileName = fileUrl.split("/")[-1]
folder = ctx.web.get_folder_by_server_relative_url(folderUrl)
file = folder.upload_file(fileName, content.encode('utf-8')).execute_query()
# Update file content
file.write(content.encode('utf-8')).execute_query()
return self._createResult(
success=True,
data={
"url": fileUrl,
"modified": datetime.now(UTC).isoformat(),
"size": len(content.encode('utf-8'))
}
)
except Exception as e:
logger.error(f"Error writing SharePoint document: {e}")
return self._createResult(
success=False,
data={"error": f"Write failed: {str(e)}"}
)
async def _readList(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Read items from SharePoint list"""
try:
siteUrl = parameters["siteUrl"]
listName = parameters["listName"]
query = parameters.get("query")
fields = parameters.get("fields", ["*"])
# Create SharePoint account
account = Account(
credentials=(userConnection.authToken, userConnection.refreshToken),
protocol=MSGraphProtocol()
)
# Get site
site = account.get_site(siteUrl)
# Get list
list = site.get_list(listName)
# Get items
if query:
items = list.get_items(query=query, fields=fields)
else:
items = list.get_items(fields=fields)
return self._createResult(
success=True,
data={
"siteUrl": siteUrl,
"listName": listName,
"items": items
}
)
except Exception as e:
logger.error(f"Error reading SharePoint list: {e}")
return self._createResult(
success=False,
data={"error": f"Read failed: {str(e)}"}
)
async def _writeList(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Write items to SharePoint list"""
try:
siteUrl = parameters["siteUrl"]
listName = parameters["listName"]
items = parameters["items"]
# Create SharePoint account
account = Account(
credentials=(userConnection.authToken, userConnection.refreshToken),
protocol=MSGraphProtocol()
)
# Get site
site = account.get_site(siteUrl)
# Get list
list = site.get_list(listName)
# Add items
results = []
for item in items:
result = list.add_item(item)
results.append({
"id": result.id,
"status": "success"
})
return self._createResult(
success=True,
data={
"siteUrl": siteUrl,
"listName": listName,
"results": results
}
)
except Exception as e:
logger.error(f"Error writing to SharePoint list: {e}")
return self._createResult(
success=False,
data={"error": f"Write failed: {str(e)}"}
)
async def _createList(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Create a new SharePoint list"""
try:
siteUrl = parameters["siteUrl"]
listName = parameters["listName"]
description = parameters.get("description")
template = parameters.get("template", "generic")
fields = parameters.get("fields", [])
# Create SharePoint account
account = Account(
credentials=(userConnection.authToken, userConnection.refreshToken),
protocol=MSGraphProtocol()
)
# Get site
site = account.get_site(siteUrl)
# Create list
list = site.create_list(
name=listName,
description=description,
template=template
)
# Add fields
for field in fields:
list.add_field(
name=field["name"],
field_type=field["type"],
required=field.get("required", False),
description=field.get("description")
)
return self._createResult(
success=True,
data={
"siteUrl": siteUrl,
"listName": listName,
"id": list.id,
"webUrl": list.web_url
}
)
except Exception as e:
logger.error(f"Error creating SharePoint list: {e}")
return self._createResult(
success=False,
data={"error": f"Create failed: {str(e)}"}
)