From 83c6951f7daf87cee1c99a916e5aadd3e53b0689 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sun, 2 Nov 2025 01:01:17 +0100
Subject: [PATCH] integrated sharepoint search routes
---
app.py | 3 +
modules/routes/routeSharepoint.py | 146 ++++++++++++++++++
.../mainServiceSharepoint.py | 2 +-
3 files changed, 150 insertions(+), 1 deletion(-)
create mode 100644 modules/routes/routeSharepoint.py
diff --git a/app.py b/app.py
index d5254f9c..d4b469ff 100644
--- a/app.py
+++ b/app.py
@@ -421,3 +421,6 @@ app.include_router(voiceGoogleRouter)
from modules.routes.routeSecurityAdmin import router as adminSecurityRouter
app.include_router(adminSecurityRouter)
+from modules.routes.routeSharepoint import router as sharepointRouter
+app.include_router(sharepointRouter)
+
diff --git a/modules/routes/routeSharepoint.py b/modules/routes/routeSharepoint.py
new file mode 100644
index 00000000..c1ae48cd
--- /dev/null
+++ b/modules/routes/routeSharepoint.py
@@ -0,0 +1,146 @@
+"""
+SharePoint routes for folder browsing
+Provides endpoints for listing SharePoint sites and browsing folders
+"""
+
+import logging
+from typing import List, Dict, Any, Optional
+from fastapi import APIRouter, HTTPException, Depends, Path, Query, Request, status
+
+from modules.security.auth import limiter, getCurrentUser
+from modules.datamodels.datamodelUam import User, UserConnection
+from modules.interfaces.interfaceDbAppObjects import getInterface
+from modules.services import getInterface as getServices
+
+logger = logging.getLogger(__name__)
+
+router = APIRouter(
+ prefix="/api/sharepoint",
+ tags=["SharePoint"],
+ responses={
+ 404: {"description": "Not found"},
+ 400: {"description": "Bad request"},
+ 401: {"description": "Unauthorized"},
+ 500: {"description": "Internal server error"}
+ }
+)
+
+def _getUserConnection(interface, connectionId: str, userId: str) -> Optional[UserConnection]:
+ """Get a user connection by ID, ensuring it belongs to the user"""
+ try:
+ connections = interface.getUserConnections(userId)
+ for conn in connections:
+ if conn.id == connectionId:
+ return conn
+ return None
+ except Exception as e:
+ logger.error(f"Error getting user connection: {str(e)}")
+ return None
+
+@router.get("/{connectionId}/sites", response_model=List[Dict[str, Any]])
+@limiter.limit("30/minute")
+async def get_sharepoint_sites(
+ request: Request,
+ connectionId: str = Path(..., description="Microsoft connection ID"),
+ currentUser: User = Depends(getCurrentUser)
+) -> List[Dict[str, Any]]:
+ """Get all SharePoint sites accessible via a Microsoft connection"""
+ try:
+ interface = getInterface(currentUser)
+
+ # Get the connection and verify it belongs to the user
+ connection = _getUserConnection(interface, connectionId, currentUser.id)
+ if not connection:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=f"Connection {connectionId} not found or does not belong to user"
+ )
+
+ # Verify it's a Microsoft connection
+ authority = connection.authority.value if hasattr(connection.authority, 'value') else str(connection.authority)
+ if authority.lower() != 'msft':
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f"Connection {connectionId} is not a Microsoft connection"
+ )
+
+ # Initialize services
+ services = getServices(currentUser, None)
+
+ # Set access token on SharePoint service
+ if not services.sharepoint.setAccessTokenFromConnection(connection):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Failed to set SharePoint access token. Connection may be expired or invalid."
+ )
+
+ # Discover SharePoint sites
+ sites = await services.sharepoint.discoverSites()
+
+ return sites
+
+ except HTTPException:
+ raise
+ except Exception as e:
+ logger.error(f"Error getting SharePoint sites: {str(e)}")
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail=f"Error getting SharePoint sites: {str(e)}"
+ )
+
+@router.get("/{connectionId}/sites/{siteId}/folders", response_model=List[Dict[str, Any]])
+@limiter.limit("60/minute")
+async def list_sharepoint_folders(
+ request: Request,
+ connectionId: str = Path(..., description="Microsoft connection ID"),
+ siteId: str = Path(..., description="SharePoint site ID"),
+ path: Optional[str] = Query(None, description="Folder path (empty for root)"),
+ currentUser: User = Depends(getCurrentUser)
+) -> List[Dict[str, Any]]:
+ """List folder contents for a SharePoint site and folder path"""
+ try:
+ interface = getInterface(currentUser)
+
+ # Get the connection and verify it belongs to the user
+ connection = _getUserConnection(interface, connectionId, currentUser.id)
+ if not connection:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=f"Connection {connectionId} not found or does not belong to user"
+ )
+
+ # Verify it's a Microsoft connection
+ authority = connection.authority.value if hasattr(connection.authority, 'value') else str(connection.authority)
+ if authority.lower() != 'msft':
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f"Connection {connectionId} is not a Microsoft connection"
+ )
+
+ # Initialize services
+ services = getServices(currentUser, None)
+
+ # Set access token on SharePoint service
+ if not services.sharepoint.setAccessTokenFromConnection(connection):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Failed to set SharePoint access token. Connection may be expired or invalid."
+ )
+
+ # Normalize folder path (empty string for root)
+ folderPath = path or ''
+
+ # List folder contents
+ items = await services.sharepoint.listFolderContents(siteId, folderPath)
+
+ return items or []
+
+ except HTTPException:
+ raise
+ except Exception as e:
+ logger.error(f"Error listing SharePoint folders: {str(e)}")
+ raise HTTPException(
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+ detail=f"Error listing SharePoint folders: {str(e)}"
+ )
+
diff --git a/modules/services/serviceSharepoint/mainServiceSharepoint.py b/modules/services/serviceSharepoint/mainServiceSharepoint.py
index 481c6818..dcce9894 100644
--- a/modules/services/serviceSharepoint/mainServiceSharepoint.py
+++ b/modules/services/serviceSharepoint/mainServiceSharepoint.py
@@ -44,7 +44,7 @@ class SharepointService:
logger.error(f"No token found for connection {userConnection.id}")
return False
- self.access_token = token.tokenAccess
+ self.accessToken = token.tokenAccess
logger.info(f"Access token set for connection {userConnection.id}")
return True