From 2a02bb1c014dc7acab8d51053b72bf9f1f0d63fc Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sat, 23 Aug 2025 14:40:36 +0200
Subject: [PATCH] running MVP2
---
modules/chat/handling/handlingTasks.py | 13 +-
modules/chat/methodBase.py | 12 +-
modules/chat/serviceCenter.py | 3 +-
modules/interfaces/interfaceAppObjects.py | 144 ++++++++++++++++------
modules/interfaces/interfaceChatModel.py | 29 +++--
modules/methods/methodOutlook.py | 43 +++----
modules/methods/methodSharepoint.py | 14 +--
modules/methods/methodWeb.py | 9 +-
modules/routes/routeSecurityGoogle.py | 14 +--
modules/routes/routeSecurityLocal.py | 4 +-
modules/routes/routeSecurityMsft.py | 18 +--
notes/changelog.txt | 6 +
12 files changed, 199 insertions(+), 110 deletions(-)
diff --git a/modules/chat/handling/handlingTasks.py b/modules/chat/handling/handlingTasks.py
index 662990fd..8d783264 100644
--- a/modules/chat/handling/handlingTasks.py
+++ b/modules/chat/handling/handlingTasks.py
@@ -642,8 +642,13 @@ class HandlingTasks:
action.result = first_doc.documentData.get("result", "")
elif hasattr(first_doc, 'documentData') and isinstance(first_doc.documentData, str):
action.result = first_doc.documentData
- action.execResultLabel = result.resultLabel or result_label
- await self.createActionMessage(action, result, workflow, result.resultLabel or result_label, created_documents, task_step, task_index)
+ # Preserve the action's execResultLabel for document routing
+ # Action methods should NOT return resultLabel - this is managed by the action handler
+ if not action.execResultLabel:
+ logger.warning(f"Action {action.execMethod}.{action.execAction} has no execResultLabel set")
+ # Always use the action's execResultLabel for message creation to ensure proper document routing
+ message_result_label = action.execResultLabel
+ await self.createActionMessage(action, result, workflow, message_result_label, created_documents, task_step, task_index)
# Log action results
logger.info(f"✓ Action completed successfully")
@@ -719,7 +724,7 @@ class HandlingTasks:
return ActionResult(
success=result.success,
documents=original_documents, # Preserve original documents field from method result
- resultLabel=result.resultLabel or result_label,
+ resultLabel=action.execResultLabel, # Always use action's execResultLabel
error=result.error or ""
)
except Exception as e:
@@ -728,7 +733,7 @@ class HandlingTasks:
return ActionResult(
success=False,
documents=[], # Empty documents for error case
- resultLabel=result_label,
+ resultLabel=action.execResultLabel,
error=str(e)
)
diff --git a/modules/chat/methodBase.py b/modules/chat/methodBase.py
index 99c602d1..010a7994 100644
--- a/modules/chat/methodBase.py
+++ b/modules/chat/methodBase.py
@@ -10,7 +10,17 @@ import inspect
logger = logging.getLogger(__name__)
def action(func):
- """Decorator to mark a method as an available action"""
+ """Decorator to mark a method as an available action
+
+ IMPORTANT: Action methods should NOT return resultLabel in their ActionResult.
+ The resultLabel is managed by the action handler using the action's execResultLabel
+ from the action plan. This ensures consistent document routing throughout the workflow.
+
+ Action methods should only return:
+ - success: bool
+ - documents: List[ActionDocument]
+ - error: str (if success=False)
+ """
@wraps(func)
async def wrapper(self, parameters: Dict[str, Any], *args, **kwargs):
return await func(self, parameters, *args, **kwargs)
diff --git a/modules/chat/serviceCenter.py b/modules/chat/serviceCenter.py
index 8ea6d000..63b94f62 100644
--- a/modules/chat/serviceCenter.py
+++ b/modules/chat/serviceCenter.py
@@ -468,7 +468,8 @@ class ServiceCenter:
token = None
token_status = "unknown"
try:
- token = self.interfaceApp.getToken(connection.authority.value)
+ # Use getConnectionToken to find token for this specific connection
+ token = self.interfaceApp.getConnectionToken(connection.id)
if token:
if hasattr(token, 'expiresAt') and token.expiresAt:
current_time = get_utc_timestamp()
diff --git a/modules/interfaces/interfaceAppObjects.py b/modules/interfaces/interfaceAppObjects.py
index 587d5b6b..c88638fd 100644
--- a/modules/interfaces/interfaceAppObjects.py
+++ b/modules/interfaces/interfaceAppObjects.py
@@ -740,9 +740,13 @@ class AppObjects:
"message": f"Error checking username availability: {str(e)}"
}
- def saveToken(self, token: Token) -> None:
- """Save a token for the current user"""
+ def saveAccessToken(self, token: Token) -> None:
+ """Save an access token for the current user (must NOT have connectionId)"""
try:
+ # Validate that this is NOT a connection token
+ if token.connectionId:
+ raise ValueError("Access tokens cannot have connectionId - use saveConnectionToken instead")
+
# Validate user context
if not self.currentUser or not self.currentUser.id:
raise ValueError("No valid user context available for token storage")
@@ -758,7 +762,7 @@ class AppObjects:
# Convert to dict and ensure all fields are properly set
token_dict = token.dict()
- # Ensure userId is set to current user (this might override the token's userId)
+ # Ensure userId is set to current user
token_dict["userId"] = self.currentUser.id
# Save to database
@@ -767,19 +771,57 @@ class AppObjects:
# Clear cache to ensure fresh data
self._clearTableCache("tokens")
-
-
except Exception as e:
- logger.error(f"Error saving token: {str(e)}")
+ logger.error(f"Error saving access token: {str(e)}")
raise
- def getToken(self, authority: str, auto_refresh: bool = True) -> Optional[Token]:
- """Get the latest valid token for the current user and authority, optionally auto-refresh if expired"""
+ def saveConnectionToken(self, token: Token) -> None:
+ """Save a connection token (must have connectionId)"""
try:
- # Get tokens for this user and authority
+ # Validate that this IS a connection token
+ if not token.connectionId:
+ raise ValueError("Connection tokens must have connectionId - use saveAccessToken instead")
+
+ # Validate user context
+ if not self.currentUser or not self.currentUser.id:
+ raise ValueError("No valid user context available for token storage")
+
+ # Set the user ID for the connection token
+ token.userId = self.currentUser.id
+
+ # Ensure token has required fields
+ if not token.id:
+ token.id = str(uuid.uuid4())
+ if not token.createdAt:
+ token.createdAt = get_utc_timestamp()
+
+ # Convert to dict and ensure all fields are properly set
+ token_dict = token.dict()
+ # Ensure userId is set to current user
+ token_dict["userId"] = self.currentUser.id
+
+ # Save to database
+ self.db.recordCreate("tokens", token_dict)
+
+ # Clear cache to ensure fresh data
+ self._clearTableCache("tokens")
+
+ except Exception as e:
+ logger.error(f"Error saving connection token: {str(e)}")
+ raise
+
+ def getAccessToken(self, authority: str, auto_refresh: bool = True) -> Optional[Token]:
+ """Get the latest valid access token for the current user and authority, optionally auto-refresh if expired"""
+ try:
+ # Validate that we're not looking for connection tokens
+ if not self.currentUser or not self.currentUser.id:
+ raise ValueError("No valid user context available for token retrieval")
+
+ # Get access tokens for this user and authority (must NOT have connectionId)
tokens = self.db.getRecordset("tokens", recordFilter={
"userId": self.currentUser.id,
- "authority": authority
+ "authority": authority,
+ "connectionId": None # Ensure we only get access tokens
})
if not tokens:
@@ -792,8 +834,6 @@ class AppObjects:
# Check if token is expired
if latest_token.expiresAt and latest_token.expiresAt < get_utc_timestamp():
if auto_refresh:
-
-
# Import TokenManager here to avoid circular imports
from modules.security.tokenManager import TokenManager
token_manager = TokenManager()
@@ -802,45 +842,58 @@ class AppObjects:
refreshed_token = token_manager.refresh_token(latest_token)
if refreshed_token:
# Save the new token and delete the old one
- self.saveToken(refreshed_token)
- self.deleteToken(authority)
+ self.saveAccessToken(refreshed_token)
+ self.deleteAccessToken(authority)
-
return refreshed_token
else:
- logger.warning(f"Failed to refresh expired token for {authority}")
+ logger.warning(f"Failed to refresh expired access token for {authority}")
return None
else:
- logger.warning(f"Token for {authority} is expired (expiresAt: {latest_token.expiresAt})")
+ logger.warning(f"Access token for {authority} is expired (expiresAt: {latest_token.expiresAt})")
return None
return latest_token
except Exception as e:
- logger.error(f"Error getting token: {str(e)}")
+ logger.error(f"Error getting access token: {str(e)}")
return None
- def getTokenForConnection(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
- """Get the token for a specific connection, optionally auto-refresh if expired"""
+ def getConnectionToken(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
+ """Get the connection token for a specific connectionId, optionally auto-refresh if expired"""
try:
+ logger.debug(f"Getting connection token for connectionId: {connectionId}")
+
+ # Validate connectionId
+ if not connectionId:
+ raise ValueError("connectionId is required for getConnectionToken")
+
# Get token for this specific connection
+ logger.debug(f"Querying tokens table with connectionId: {connectionId}")
+
+ # Query for specific connection
tokens = self.db.getRecordset("tokens", recordFilter={
"connectionId": connectionId
})
+ logger.debug(f"Raw tokens from database for connectionId {connectionId}: {tokens}")
+ logger.debug(f"Tokens count: {len(tokens) if tokens else 0}")
+
if not tokens:
- logger.warning(f"No token found for connection: {connectionId}")
+ logger.warning(f"No connection token found for connectionId: {connectionId}")
return None
# Sort by expiration date and get the latest (most recent expiration)
+ logger.debug(f"Sorting tokens by expiresAt, current tokens: {tokens}")
tokens.sort(key=lambda x: x.get("expiresAt", 0), reverse=True)
latest_token = Token(**tokens[0])
+ logger.debug(f"Latest connection token: {latest_token}")
+ logger.debug(f"Token expiresAt: {latest_token.expiresAt}, type: {type(latest_token.expiresAt)}")
+ logger.debug(f"Current UTC timestamp: {get_utc_timestamp()}, type: {type(get_utc_timestamp())}")
# Check if token is expired
if latest_token.expiresAt and latest_token.expiresAt < get_utc_timestamp():
if auto_refresh:
-
-
# Import TokenManager here to avoid circular imports
from modules.security.tokenManager import TokenManager
token_manager = TokenManager()
@@ -849,31 +902,36 @@ class AppObjects:
refreshed_token = token_manager.refresh_token(latest_token)
if refreshed_token:
# Save the new token and delete the old one
- self.saveToken(refreshed_token)
- self.deleteTokenByConnectionId(connectionId)
+ self.saveConnectionToken(refreshed_token)
+ self.deleteConnectionTokenByConnectionId(connectionId)
-
return refreshed_token
else:
- logger.warning(f"Failed to refresh expired token for connection {connectionId}")
+ logger.warning(f"Failed to refresh expired connection token for connectionId {connectionId}")
return None
else:
- logger.warning(f"Token for connection {connectionId} is expired (expiresAt: {latest_token.expiresAt})")
+ logger.warning(f"Connection token for connectionId {connectionId} is expired (expiresAt: {latest_token.expiresAt})")
return None
+ logger.debug(f"Returning valid connection token: {latest_token}")
return latest_token
except Exception as e:
- logger.error(f"Error getting token for connection {connectionId}: {str(e)}")
+ logger.error(f"Error getting connection token for connectionId {connectionId}: {str(e)}")
return None
- def deleteToken(self, authority: str) -> None:
- """Delete all tokens for the current user and authority"""
+ def deleteAccessToken(self, authority: str) -> None:
+ """Delete all access tokens for the current user and authority"""
try:
- # Get tokens to delete
+ # Validate user context
+ if not self.currentUser or not self.currentUser.id:
+ raise ValueError("No valid user context available for token deletion")
+
+ # Get access tokens to delete (must NOT have connectionId)
tokens = self.db.getRecordset("tokens", recordFilter={
"userId": self.currentUser.id,
- "authority": authority
+ "authority": authority,
+ "connectionId": None # Ensure we only delete access tokens
})
# Delete each token
@@ -884,13 +942,17 @@ class AppObjects:
self._clearTableCache("tokens")
except Exception as e:
- logger.error(f"Error deleting token: {str(e)}")
+ logger.error(f"Error deleting access token: {str(e)}")
raise
- def deleteTokenByConnectionId(self, connectionId: str) -> None:
- """Delete all tokens for a specific connection"""
+ def deleteConnectionTokenByConnectionId(self, connectionId: str) -> None:
+ """Delete all connection tokens for a specific connectionId"""
try:
- # Get tokens to delete
+ # Validate connectionId
+ if not connectionId:
+ raise ValueError("connectionId is required for deleteConnectionTokenByConnectionId")
+
+ # Get connection tokens to delete
tokens = self.db.getRecordset("tokens", recordFilter={
"connectionId": connectionId
})
@@ -903,9 +965,15 @@ class AppObjects:
self._clearTableCache("tokens")
except Exception as e:
- logger.error(f"Error deleting token for connection {connectionId}: {str(e)}")
+ logger.error(f"Error deleting connection token for connectionId {connectionId}: {str(e)}")
raise
+ # Backward compatibility method
+ def getTokenForConnection(self, connectionId: str, auto_refresh: bool = True) -> Optional[Token]:
+ """Backward compatibility method - use getConnectionToken instead"""
+ logger.warning("getTokenForConnection is deprecated, use getConnectionToken instead")
+ return self.getConnectionToken(connectionId, auto_refresh)
+
def cleanupExpiredTokens(self) -> int:
"""Clean up expired tokens for all connections, returns count of cleaned tokens"""
try:
diff --git a/modules/interfaces/interfaceChatModel.py b/modules/interfaces/interfaceChatModel.py
index 1e2363a5..f698d66b 100644
--- a/modules/interfaces/interfaceChatModel.py
+++ b/modules/interfaces/interfaceChatModel.py
@@ -31,32 +31,41 @@ register_model_labels(
)
class ActionResult(BaseModel, ModelMixin):
- """Clean action result with documents as primary output"""
+ """Clean action result with documents as primary output
+
+ IMPORTANT: Action methods should NOT set resultLabel in their return value.
+ The resultLabel is managed by the action handler using the action's execResultLabel
+ from the action plan. This ensures consistent document routing throughout the workflow.
+ """
# Core result
success: bool = Field(description="Whether execution succeeded")
error: Optional[str] = Field(None, description="Error message if failed")
# Primary output - documents
documents: List[ActionDocument] = Field(default_factory=list, description="Document outputs")
- resultLabel: Optional[str] = Field(None, description="Label for document routing")
+ resultLabel: Optional[str] = Field(None, description="Label for document routing (set by action handler, not by action methods)")
@classmethod
- def success(cls, documents: List[ActionDocument] = None, resultLabel: str = None) -> 'ActionResult':
- """Create a successful action result"""
+ def success(cls, documents: List[ActionDocument] = None) -> 'ActionResult':
+ """Create a successful action result
+
+ Note: Do not set resultLabel - this is managed by the action handler
+ """
return cls(
success=True,
- documents=documents or [],
- resultLabel=resultLabel
+ documents=documents or []
)
@classmethod
- def failure(cls, error: str, documents: List[ActionDocument] = None, resultLabel: str = None) -> 'ActionResult':
- """Create a failed action result"""
+ def failure(cls, error: str, documents: List[ActionDocument] = None) -> 'ActionResult':
+ """Create a failed action result
+
+ Note: Do not set resultLabel - this is managed by the action handler
+ """
return cls(
success=False,
documents=documents or [],
- error=error,
- resultLabel=resultLabel
+ error=error
)
# Register labels for ActionResult
diff --git a/modules/methods/methodOutlook.py b/modules/methods/methodOutlook.py
index 15d5bae8..65a6c3f2 100644
--- a/modules/methods/methodOutlook.py
+++ b/modules/methods/methodOutlook.py
@@ -102,18 +102,25 @@ class MethodOutlook(MethodBase):
Helper function to get Microsoft connection details.
"""
try:
+ logger.debug(f"Getting Microsoft connection for reference: {connectionReference}")
+
# Get the connection from the service
userConnection = self.service.getUserConnectionFromConnectionReference(connectionReference)
if not userConnection:
logger.error(f"Connection not found: {connectionReference}")
return None
+ logger.debug(f"Found connection: {userConnection.id}, status: {userConnection.status.value}, authority: {userConnection.authority.value}")
+
# Get the token for this specific connection
- token = self.service.interfaceApp.getTokenForConnection(userConnection.id)
+ token = self.service.interfaceApp.getConnectionToken(userConnection.id)
if not token:
logger.error(f"Token not found for connection: {userConnection.id}")
+ logger.debug(f"Connection details: {userConnection}")
return None
+ logger.debug(f"Token retrieved for connection {userConnection.id}")
+
# Check if token is expired
if hasattr(token, 'expiresAt') and token.expiresAt:
current_time = get_utc_timestamp()
@@ -126,8 +133,6 @@ class MethodOutlook(MethodBase):
logger.error(f"Connection is not active: {userConnection.id}, status: {userConnection.status.value}")
return None
-
-
return {
"id": userConnection.id,
"accessToken": token.tokenAccess,
@@ -482,8 +487,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_emails"
+ }]
)
except Exception as e:
@@ -529,8 +533,10 @@ class MethodOutlook(MethodBase):
)
# Get Microsoft connection
+ logger.debug(f"Getting Microsoft connection for sendEmail action")
connection = self._getMicrosoftConnection(connectionReference)
if not connection:
+ logger.error(f"Failed to get Microsoft connection for reference: {connectionReference}")
return ActionResult.failure(error="Failed to get Microsoft connection")
# Get the composed email document
@@ -777,8 +783,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="email_draft_created"
+ }]
)
else:
logger.error(f"Failed to create draft. Status: {response.status_code}, Response: {response.text}")
@@ -815,8 +820,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_email_draft"
+ }]
)
except Exception as e:
@@ -998,8 +1002,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_email_search"
+ }]
)
except Exception as e:
@@ -1122,8 +1125,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_drafts_list"
+ }]
)
except Exception as e:
@@ -1233,8 +1235,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_drafts_found"
+ }]
)
except Exception as e:
@@ -1377,8 +1378,7 @@ class MethodOutlook(MethodBase):
"timestamp": get_utc_timestamp()
},
"mimeType": "application/json"
- }],
- resultLabel="outlook_drafts_folder_check"
+ }]
)
except Exception as e:
@@ -1618,8 +1618,7 @@ class MethodOutlook(MethodBase):
"documentName": f"composed_email_{int(get_utc_timestamp())}.json",
"documentData": result_data,
"mimeType": "application/json"
- }],
- resultLabel="composed_email"
+ }]
)
except Exception as e:
@@ -1662,8 +1661,7 @@ class MethodOutlook(MethodBase):
"status": "ready"
},
"mimeType": "application/json"
- }],
- resultLabel="permissions_ready"
+ }]
)
else:
return ActionResult(
@@ -1680,8 +1678,7 @@ class MethodOutlook(MethodBase):
},
"mimeType": "application/json"
}],
- error="Connection lacks necessary permissions for Outlook operations",
- resultLabel="permissions_missing"
+ error="Connection lacks necessary permissions for Outlook operations"
)
except Exception as e:
diff --git a/modules/methods/methodSharepoint.py b/modules/methods/methodSharepoint.py
index bd2047fe..361c804b 100644
--- a/modules/methods/methodSharepoint.py
+++ b/modules/methods/methodSharepoint.py
@@ -44,7 +44,7 @@ class MethodSharepoint(MethodBase):
return None
# Get the token for this specific connection
- token = self.service.interfaceApp.getTokenForConnection(userConnection.id)
+ token = self.service.interfaceApp.getConnectionToken(userConnection.id)
if not token:
logger.warning(f"No token found for connection {userConnection.id}")
return None
@@ -283,8 +283,7 @@ class MethodSharepoint(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="sharepoint_find_path"
+ ]
)
except Exception as e:
@@ -474,8 +473,7 @@ class MethodSharepoint(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="sharepoint_documents"
+ ]
)
except Exception as e:
logger.error(f"Error reading SharePoint documents: {str(e)}")
@@ -652,8 +650,7 @@ class MethodSharepoint(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="sharepoint_upload"
+ ]
)
except Exception as e:
@@ -861,8 +858,7 @@ class MethodSharepoint(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="sharepoint_document_list"
+ ]
)
except Exception as e:
diff --git a/modules/methods/methodWeb.py b/modules/methods/methodWeb.py
index 36f20143..47945cf4 100644
--- a/modules/methods/methodWeb.py
+++ b/modules/methods/methodWeb.py
@@ -562,8 +562,7 @@ class MethodWeb(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="web_search_results"
+ ]
)
except Exception as e:
@@ -698,8 +697,7 @@ class MethodWeb(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="web_crawl_results"
+ ]
)
except Exception as e:
@@ -803,8 +801,7 @@ class MethodWeb(MethodBase):
"documentData": result_data,
"mimeType": output_mime_type
}
- ],
- resultLabel="web_scrape_results"
+ ]
)
except Exception as e:
diff --git a/modules/routes/routeSecurityGoogle.py b/modules/routes/routeSecurityGoogle.py
index bfa80f4e..b297680d 100644
--- a/modules/routes/routeSecurityGoogle.py
+++ b/modules/routes/routeSecurityGoogle.py
@@ -223,9 +223,9 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
createdAt=get_utc_timestamp()
)
- # Save token
+ # Save access token (no connectionId)
appInterface = getInterface(user)
- appInterface.saveToken(token)
+ appInterface.saveAccessToken(token)
# Return success page with token data
return HTMLResponse(
@@ -347,7 +347,7 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
expiresAt=create_expiration_timestamp(token_response.get("expires_in", 0)),
createdAt=get_utc_timestamp()
)
- interface.saveToken(token)
+ interface.saveConnectionToken(token)
# Return success page with connection data
return HTMLResponse(
@@ -491,7 +491,7 @@ async def refresh_token(
logger.debug(f"Found Google connection: {google_connection.id}, status={google_connection.status}")
# Get the token for this specific connection using the new method
- current_token = appInterface.getTokenForConnection(google_connection.id, auto_refresh=False)
+ current_token = appInterface.getConnectionToken(google_connection.id, auto_refresh=False)
if not current_token:
raise HTTPException(
@@ -507,9 +507,9 @@ async def refresh_token(
refreshed_token = token_manager.refresh_token(current_token)
if refreshed_token:
- # Save the new token and delete the old one
- appInterface.saveToken(refreshed_token)
- appInterface.deleteTokenByConnectionId(google_connection.id)
+ # Save the new connection token and delete the old one
+ appInterface.saveConnectionToken(refreshed_token)
+ appInterface.deleteConnectionTokenByConnectionId(google_connection.id)
# Update the connection's expiration time
google_connection.expiresAt = float(refreshed_token.expiresAt)
diff --git a/modules/routes/routeSecurityLocal.py b/modules/routes/routeSecurityLocal.py
index 4d53d216..76b3bb1a 100644
--- a/modules/routes/routeSecurityLocal.py
+++ b/modules/routes/routeSecurityLocal.py
@@ -103,8 +103,8 @@ async def login(
expiresAt=expires_at.timestamp()
)
- # Save token
- userInterface.saveToken(token)
+ # Save access token
+ userInterface.saveAccessToken(token)
# Create response data
response_data = {
diff --git a/modules/routes/routeSecurityMsft.py b/modules/routes/routeSecurityMsft.py
index 90a957c9..d46e4897 100644
--- a/modules/routes/routeSecurityMsft.py
+++ b/modules/routes/routeSecurityMsft.py
@@ -173,9 +173,9 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
createdAt=get_utc_timestamp()
)
- # Save token
+ # Save access token (no connectionId)
appInterface = getInterface(user)
- appInterface.saveToken(token)
+ appInterface.saveAccessToken(token)
# Create JWT token data
jwt_token_data = {
@@ -198,8 +198,8 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
createdAt=get_utc_timestamp()
)
- # Save JWT token
- appInterface.saveToken(jwt_token_obj)
+ # Save JWT access token
+ appInterface.saveAccessToken(jwt_token_obj)
# Convert token to dict and ensure proper timestamp handling
token_dict = jwt_token_obj.to_dict()
@@ -328,7 +328,7 @@ async def auth_callback(code: str, state: str, request: Request) -> HTMLResponse
)
- interface.saveToken(token)
+ interface.saveConnectionToken(token)
# Return success page with connection data
@@ -499,7 +499,7 @@ async def refresh_token(
# Get the token for this specific connection using the new method
# Enable auto-refresh to handle expired tokens gracefully
- current_token = appInterface.getTokenForConnection(msft_connection.id, auto_refresh=True)
+ current_token = appInterface.getConnectionToken(msft_connection.id, auto_refresh=True)
if not current_token:
raise HTTPException(
@@ -515,9 +515,9 @@ async def refresh_token(
refreshed_token = token_manager.refresh_token(current_token)
if refreshed_token:
- # Save the new token and delete the old one
- appInterface.saveToken(refreshed_token)
- appInterface.deleteTokenByConnectionId(msft_connection.id)
+ # Save the new connection token and delete the old one
+ appInterface.saveConnectionToken(refreshed_token)
+ appInterface.deleteConnectionTokenByConnectionId(msft_connection.id)
# Update the connection's expiration time
msft_connection.expiresAt = float(refreshed_token.expiresAt)
diff --git a/notes/changelog.txt b/notes/changelog.txt
index b4c71704..b7b189c1 100644
--- a/notes/changelog.txt
+++ b/notes/changelog.txt
@@ -1,6 +1,12 @@
TODO
+- ui: Besseres Rendering der Tasks, Actions, Files (hierarchisch eingerückt) und der Log Entries ohne Rahmen
+- ui: Beim Laden des Workflows die Logs und Messages synchron laden chronologisch
+- documents: Sprechende Filenamen für user, ein Label für die interne Nutzung
+- Chat: Pro Action und Task eine Message an den User in der UserLanguage
+
+
- check history --> tasks?
- model reference diagram for all models. who uses who? --> to see the basic building blocks