gateway/modules/workflows/methods/methodSharepoint/methodSharepoint.py

402 lines
19 KiB
Python

# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
SharePoint operations method module.
Handles SharePoint document operations using the SharePoint service.
"""
import logging
from modules.workflows.methods.methodBase import MethodBase
from modules.datamodels.datamodelWorkflowActions import WorkflowActionDefinition, WorkflowActionParameter
from modules.shared.frontendTypes import FrontendType
# Import helpers
from .helpers.connection import ConnectionHelper
from .helpers.siteDiscovery import SiteDiscoveryHelper
from .helpers.documentParsing import DocumentParsingHelper
from .helpers.pathProcessing import PathProcessingHelper
from .helpers.apiClient import ApiClientHelper
# Import actions
from .actions.findDocumentPath import findDocumentPath
from .actions.readDocuments import readDocuments
from .actions.uploadDocument import uploadDocument
from .actions.listDocuments import listDocuments
from .actions.analyzeFolderUsage import analyzeFolderUsage
from .actions.findSiteByUrl import findSiteByUrl
from .actions.downloadFileByPath import downloadFileByPath
from .actions.copyFile import copyFile
from .actions.uploadFile import uploadFile
logger = logging.getLogger(__name__)
class MethodSharepoint(MethodBase):
"""SharePoint operations methods."""
def __init__(self, services):
super().__init__(services)
self.name = "sharepoint"
self.description = "SharePoint operations methods"
# Initialize helper modules
self.connection = ConnectionHelper(self)
self.siteDiscovery = SiteDiscoveryHelper(self)
self.documentParsing = DocumentParsingHelper(self)
self.pathProcessing = PathProcessingHelper(self)
self.apiClient = ApiClientHelper(self)
# RBAC-Integration: Action-Definitionen mit actionId
self._actions = {
"findDocumentPath": WorkflowActionDefinition(
actionId="sharepoint.findDocumentPath",
description="Find documents and folders by name/path across sites",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"site": WorkflowActionParameter(
name="site",
type="str",
frontendType=FrontendType.TEXT,
required=False,
description="Site hint"
),
"searchQuery": WorkflowActionParameter(
name="searchQuery",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Search terms or path"
),
"maxResults": WorkflowActionParameter(
name="maxResults",
type="int",
frontendType=FrontendType.NUMBER,
required=False,
default=1000,
description="Maximum items to return",
validation={"min": 1, "max": 10000}
)
},
execute=findDocumentPath.__get__(self, self.__class__)
),
"readDocuments": WorkflowActionDefinition(
actionId="sharepoint.readDocuments",
description="Read documents from SharePoint and extract content/metadata",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"documentList": WorkflowActionParameter(
name="documentList",
type="List[str]",
frontendType=FrontendType.DOCUMENT_REFERENCE,
required=False,
description="Document list reference(s) containing findDocumentPath result"
),
"pathQuery": WorkflowActionParameter(
name="pathQuery",
type="str",
frontendType=FrontendType.SHAREPOINT_FOLDER,
required=False,
description="Direct path query if no documentList (e.g., /sites/SiteName/FolderPath)"
),
"includeMetadata": WorkflowActionParameter(
name="includeMetadata",
type="bool",
frontendType=FrontendType.CHECKBOX,
required=False,
default=True,
description="Include metadata"
)
},
execute=readDocuments.__get__(self, self.__class__)
),
"uploadDocument": WorkflowActionDefinition(
actionId="sharepoint.uploadDocument",
description="Upload documents to SharePoint",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"documentList": WorkflowActionParameter(
name="documentList",
type="List[str]",
frontendType=FrontendType.DOCUMENT_REFERENCE,
required=True,
description="Document reference(s) to upload. File names are taken from the documents"
),
"pathQuery": WorkflowActionParameter(
name="pathQuery",
type="str",
frontendType=FrontendType.SHAREPOINT_FOLDER,
required=False,
description="Direct upload target path if documentList doesn't contain findDocumentPath result (e.g., /sites/SiteName/FolderPath)"
)
},
execute=uploadDocument.__get__(self, self.__class__)
),
"listDocuments": WorkflowActionDefinition(
actionId="sharepoint.listDocuments",
description="List documents and folders in SharePoint paths across sites",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"documentList": WorkflowActionParameter(
name="documentList",
type="List[str]",
frontendType=FrontendType.DOCUMENT_REFERENCE,
required=False,
description="Document list reference(s) containing findDocumentPath result"
),
"pathQuery": WorkflowActionParameter(
name="pathQuery",
type="str",
frontendType=FrontendType.SHAREPOINT_FOLDER,
required=False,
description="Direct path query if no documentList (e.g., /sites/SiteName/FolderPath)"
),
"includeSubfolders": WorkflowActionParameter(
name="includeSubfolders",
type="bool",
frontendType=FrontendType.CHECKBOX,
required=False,
default=False,
description="Include one level of subfolders"
)
},
execute=listDocuments.__get__(self, self.__class__)
),
"analyzeFolderUsage": WorkflowActionDefinition(
actionId="sharepoint.analyzeFolderUsage",
description="Analyze usage intensity of folders and files in SharePoint",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"documentList": WorkflowActionParameter(
name="documentList",
type="List[str]",
frontendType=FrontendType.DOCUMENT_REFERENCE,
required=True,
description="Document list reference(s) containing findDocumentPath result"
),
"startDateTime": WorkflowActionParameter(
name="startDateTime",
type="str",
frontendType=FrontendType.DATETIME,
required=False,
description="Start date/time in ISO format (e.g., 2025-11-01T00:00:00Z). Default: 30 days ago"
),
"endDateTime": WorkflowActionParameter(
name="endDateTime",
type="str",
frontendType=FrontendType.DATETIME,
required=False,
description="End date/time in ISO format (e.g., 2025-11-30T23:59:59Z). Default: current time"
),
"interval": WorkflowActionParameter(
name="interval",
type="str",
frontendType=FrontendType.SELECT,
frontendOptions=["day", "week", "month"],
required=False,
default="day",
description="Time interval for grouping activities"
)
},
execute=analyzeFolderUsage.__get__(self, self.__class__)
),
"findSiteByUrl": WorkflowActionDefinition(
actionId="sharepoint.findSiteByUrl",
description="Find SharePoint site by hostname and site path",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"hostname": WorkflowActionParameter(
name="hostname",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="SharePoint hostname (e.g., example.sharepoint.com)"
),
"sitePath": WorkflowActionParameter(
name="sitePath",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Site path (e.g., SteeringBPM or /sites/SteeringBPM)"
)
},
execute=findSiteByUrl.__get__(self, self.__class__)
),
"downloadFileByPath": WorkflowActionDefinition(
actionId="sharepoint.downloadFileByPath",
description="Download file from SharePoint by exact file path",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"siteId": WorkflowActionParameter(
name="siteId",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
),
"filePath": WorkflowActionParameter(
name="filePath",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Full file path relative to site root (e.g., /General/50 Docs hosted by SELISE/file.xlsx)"
)
},
execute=downloadFileByPath.__get__(self, self.__class__)
),
"copyFile": WorkflowActionDefinition(
actionId="sharepoint.copyFile",
description="Copy file within SharePoint",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"siteId": WorkflowActionParameter(
name="siteId",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
),
"sourceFolder": WorkflowActionParameter(
name="sourceFolder",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Source folder path relative to site root"
),
"sourceFile": WorkflowActionParameter(
name="sourceFile",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Source file name"
),
"destFolder": WorkflowActionParameter(
name="destFolder",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Destination folder path relative to site root"
),
"destFile": WorkflowActionParameter(
name="destFile",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Destination file name"
)
},
execute=copyFile.__get__(self, self.__class__)
),
"uploadFile": WorkflowActionDefinition(
actionId="sharepoint.uploadFile",
description="Upload raw file content (bytes) to SharePoint",
dynamicMode=True,
parameters={
"connectionReference": WorkflowActionParameter(
name="connectionReference",
type="str",
frontendType=FrontendType.USER_CONNECTION,
required=True,
description="Microsoft connection label"
),
"siteId": WorkflowActionParameter(
name="siteId",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="SharePoint site ID (from findSiteByUrl result) or document reference containing site info"
),
"folderPath": WorkflowActionParameter(
name="folderPath",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="Folder path relative to site root"
),
"fileName": WorkflowActionParameter(
name="fileName",
type="str",
frontendType=FrontendType.TEXT,
required=True,
description="File name"
),
"content": WorkflowActionParameter(
name="content",
type="str",
frontendType=FrontendType.DOCUMENT_REFERENCE,
required=True,
description="Document reference containing file content as base64-encoded bytes"
)
},
execute=uploadFile.__get__(self, self.__class__)
)
}
# Validate actions after definition
self._validateActions()
# Register actions as methods (optional, für direkten Zugriff)
self.findDocumentPath = findDocumentPath.__get__(self, self.__class__)
self.readDocuments = readDocuments.__get__(self, self.__class__)
self.uploadDocument = uploadDocument.__get__(self, self.__class__)
self.listDocuments = listDocuments.__get__(self, self.__class__)
self.analyzeFolderUsage = analyzeFolderUsage.__get__(self, self.__class__)
self.findSiteByUrl = findSiteByUrl.__get__(self, self.__class__)
self.downloadFileByPath = downloadFileByPath.__get__(self, self.__class__)
self.copyFile = copyFile.__get__(self, self.__class__)
self.uploadFile = uploadFile.__get__(self, self.__class__)