# 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" ), "pathQuery": WorkflowActionParameter( name="pathQuery", type="str", frontendType=FrontendType.TEXT, required=False, description="Full SharePoint path (e.g. /sites/SiteName/Shared Documents/file.pdf). When provided, siteId and filePath are derived automatically." ), "siteId": WorkflowActionParameter( name="siteId", type="str", frontendType=FrontendType.TEXT, required=False, description="SharePoint site ID (optional when pathQuery is provided)" ), "filePath": WorkflowActionParameter( name="filePath", type="str", frontendType=FrontendType.TEXT, required=False, description="File path relative to site root (optional when pathQuery is provided)" ) }, 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" ), "sourcePath": WorkflowActionParameter( name="sourcePath", type="str", frontendType=FrontendType.TEXT, required=True, description="Full path to source file (e.g. /sites/.../folder/file.pdf)" ), "destPath": WorkflowActionParameter( name="destPath", type="str", frontendType=FrontendType.TEXT, required=True, description="Full path to destination folder (e.g. /sites/.../folder)" ) }, 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" ), "pathQuery": WorkflowActionParameter( name="pathQuery", type="str", frontendType=FrontendType.TEXT, required=False, description="Target folder path (e.g. /sites/.../Folder). When provided, siteId and folderPath are derived. Alternative to explicit siteId+folderPath." ), "siteId": WorkflowActionParameter( name="siteId", type="str", frontendType=FrontendType.TEXT, required=False, description="SharePoint site ID (when not using pathQuery)" ), "folderPath": WorkflowActionParameter( name="folderPath", type="str", frontendType=FrontendType.TEXT, required=False, description="Folder path relative to site root (when not using pathQuery)" ), "fileName": WorkflowActionParameter( name="fileName", type="str", frontendType=FrontendType.TEXT, required=False, description="File name (defaults to document name when content from context)" ), "content": WorkflowActionParameter( name="content", type="Any", frontendType=FrontendType.DOCUMENT_REFERENCE, required=True, description="File content from context (upstream document) or document reference" ) }, 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__)