From a0b9a6e4b58d62c24cdcce36a54863729c0dcef9 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sat, 24 Jan 2026 00:42:19 +0100
Subject: [PATCH] reference fixes
---
modules/aicore/aicorePluginPerplexity.py | 2 +-
modules/datamodels/datamodelChat.py | 36 +++++++++----------
modules/datamodels/datamodelFiles.py | 4 +--
modules/interfaces/interfaceDbManagement.py | 5 +--
modules/interfaces/interfaceRbac.py | 1 -
modules/routes/routeDataConnections.py | 1 +
modules/routes/routeDataFiles.py | 10 +++---
modules/routes/routeDataUsers.py | 2 +-
modules/routes/routeSecurityGoogle.py | 1 +
modules/routes/routeSecurityMsft.py | 1 +
.../serviceAi/subContentExtraction.py | 2 +-
.../methods/methodAi/actions/process.py | 2 +-
.../workflows/processing/core/taskPlanner.py | 2 +-
.../workflows/processing/modes/modeDynamic.py | 2 +-
.../workflows/processing/workflowProcessor.py | 2 +-
15 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/modules/aicore/aicorePluginPerplexity.py b/modules/aicore/aicorePluginPerplexity.py
index e751f1e9..e6d1ba10 100644
--- a/modules/aicore/aicorePluginPerplexity.py
+++ b/modules/aicore/aicorePluginPerplexity.py
@@ -6,7 +6,7 @@ from typing import List
from fastapi import HTTPException
from modules.shared.configuration import APP_CONFIG
from .aicoreBase import BaseConnectorAi
-from modules.datamodels.datamodelAi import AiModel, PriorityEnum, ProcessingModeEnum, OperationTypeEnum, AiModelCall, AiModelResponse, createOperationTypeRatings, AiCallPromptWebSearch, AiCallPromptWebCrawl
+from modules.datamodels.datamodelAi import AiModel, PriorityEnum, ProcessingModeEnum, OperationTypeEnum, AiModelCall, AiModelResponse, createOperationTypeRatings, AiCallPromptWebSearch, AiCallPromptWebCrawl, AiCallOptions
from modules.datamodels.datamodelTools import CountryCodes
# Configure logger
diff --git a/modules/datamodels/datamodelChat.py b/modules/datamodels/datamodelChat.py
index c2838ad3..328bee22 100644
--- a/modules/datamodels/datamodelChat.py
+++ b/modules/datamodels/datamodelChat.py
@@ -14,11 +14,11 @@ class ChatStat(BaseModel):
id: str = Field(
default_factory=lambda: str(uuid.uuid4()), description="Primary key"
)
- mandateId: str = Field(
- description="ID of the mandate this stat belongs to"
+ mandateId: Optional[str] = Field(
+ default="", description="ID of the mandate this stat belongs to"
)
- featureInstanceId: str = Field(
- description="ID of the feature instance this stat belongs to"
+ featureInstanceId: Optional[str] = Field(
+ default="", description="ID of the feature instance this stat belongs to"
)
workflowId: Optional[str] = Field(
None, description="Foreign key to workflow (for workflow stats)"
@@ -57,11 +57,11 @@ class ChatLog(BaseModel):
id: str = Field(
default_factory=lambda: str(uuid.uuid4()), description="Primary key"
)
- mandateId: str = Field(
- description="ID of the mandate this log belongs to"
+ mandateId: Optional[str] = Field(
+ default="", description="ID of the mandate this log belongs to"
)
- featureInstanceId: str = Field(
- description="ID of the feature instance this log belongs to"
+ featureInstanceId: Optional[str] = Field(
+ default="", description="ID of the feature instance this log belongs to"
)
workflowId: str = Field(description="Foreign key to workflow")
message: str = Field(description="Log message")
@@ -110,11 +110,11 @@ class ChatDocument(BaseModel):
id: str = Field(
default_factory=lambda: str(uuid.uuid4()), description="Primary key"
)
- mandateId: str = Field(
- description="ID of the mandate this document belongs to"
+ mandateId: Optional[str] = Field(
+ default="", description="ID of the mandate this document belongs to"
)
- featureInstanceId: str = Field(
- description="ID of the feature instance this document belongs to"
+ featureInstanceId: Optional[str] = Field(
+ default="", description="ID of the feature instance this document belongs to"
)
messageId: str = Field(description="Foreign key to message")
fileId: str = Field(description="Foreign key to file")
@@ -224,11 +224,11 @@ class ChatMessage(BaseModel):
id: str = Field(
default_factory=lambda: str(uuid.uuid4()), description="Primary key"
)
- mandateId: str = Field(
- description="ID of the mandate this message belongs to"
+ mandateId: Optional[str] = Field(
+ default="", description="ID of the mandate this message belongs to"
)
- featureInstanceId: str = Field(
- description="ID of the feature instance this message belongs to"
+ featureInstanceId: Optional[str] = Field(
+ default="", description="ID of the feature instance this message belongs to"
)
workflowId: str = Field(description="Foreign key to workflow")
parentMessageId: Optional[str] = Field(
@@ -327,8 +327,8 @@ registerModelLabels(
class ChatWorkflow(BaseModel):
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Primary key", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
- mandateId: str = Field(description="ID of the mandate this workflow belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
- featureInstanceId: str = Field(description="ID of the feature instance this workflow belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
+ mandateId: Optional[str] = Field(default="", description="ID of the mandate this workflow belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
+ featureInstanceId: Optional[str] = Field(default="", description="ID of the feature instance this workflow belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
status: str = Field(default="running", description="Current status of the workflow", json_schema_extra={"frontend_type": "select", "frontend_readonly": False, "frontend_required": False, "frontend_options": [
{"value": "running", "label": {"en": "Running", "fr": "En cours"}},
{"value": "completed", "label": {"en": "Completed", "fr": "Terminé"}},
diff --git a/modules/datamodels/datamodelFiles.py b/modules/datamodels/datamodelFiles.py
index 07880f3d..f1b07eb3 100644
--- a/modules/datamodels/datamodelFiles.py
+++ b/modules/datamodels/datamodelFiles.py
@@ -12,8 +12,8 @@ import base64
class FileItem(BaseModel):
id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Primary key", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
- mandateId: str = Field(description="ID of the mandate this file belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
- featureInstanceId: str = Field(description="ID of the feature instance this file belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
+ mandateId: Optional[str] = Field(default="", description="ID of the mandate this file belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
+ featureInstanceId: Optional[str] = Field(default="", description="ID of the feature instance this file belongs to", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
fileName: str = Field(description="Name of the file", json_schema_extra={"frontend_type": "text", "frontend_readonly": False, "frontend_required": True})
mimeType: str = Field(description="MIME type of the file", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
fileHash: str = Field(description="Hash of the file", json_schema_extra={"frontend_type": "text", "frontend_readonly": True, "frontend_required": False})
diff --git a/modules/interfaces/interfaceDbManagement.py b/modules/interfaces/interfaceDbManagement.py
index b514cbf3..a26e8c98 100644
--- a/modules/interfaces/interfaceDbManagement.py
+++ b/modules/interfaces/interfaceDbManagement.py
@@ -989,8 +989,9 @@ class ComponentObjects:
fileHash = hashlib.sha256(content).hexdigest()
# Use mandateId and featureInstanceId from context for proper data isolation
- mandateId = self.mandateId
- featureInstanceId = self.featureInstanceId
+ # Convert None to empty string to satisfy Pydantic validation
+ mandateId = self.mandateId or ""
+ featureInstanceId = self.featureInstanceId or ""
# Create FileItem instance
fileItem = FileItem(
diff --git a/modules/interfaces/interfaceRbac.py b/modules/interfaces/interfaceRbac.py
index 6b432a2b..a99bfd0b 100644
--- a/modules/interfaces/interfaceRbac.py
+++ b/modules/interfaces/interfaceRbac.py
@@ -62,7 +62,6 @@ def getRecordsetWithRBAC(
# SysAdmin bypass: SysAdmin users have full access to all tables
isSysAdmin = getattr(currentUser, 'isSysAdmin', False)
if isSysAdmin:
- logger.debug(f"SysAdmin user {currentUser.id} bypassing RBAC for table {table}")
# Direct access without RBAC filtering
# Note: getRecordset doesn't support orderBy/limit - these are only used in RBAC path
return connector.getRecordset(modelClass, recordFilter=recordFilter)
diff --git a/modules/routes/routeDataConnections.py b/modules/routes/routeDataConnections.py
index 210e0522..2dade569 100644
--- a/modules/routes/routeDataConnections.py
+++ b/modules/routes/routeDataConnections.py
@@ -20,6 +20,7 @@ import math
from modules.datamodels.datamodelUam import User, UserConnection, AuthAuthority, ConnectionStatus
from modules.datamodels.datamodelSecurity import Token
from modules.auth import getCurrentUser, limiter
+from modules.auth.tokenRefreshService import token_refresh_service
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResponse, PaginationMetadata, normalize_pagination_dict
from modules.interfaces.interfaceDbApp import getInterface
from modules.shared.timeUtils import getUtcTimestamp, parseTimestamp
diff --git a/modules/routes/routeDataFiles.py b/modules/routes/routeDataFiles.py
index 66345ce5..1a84b7e4 100644
--- a/modules/routes/routeDataFiles.py
+++ b/modules/routes/routeDataFiles.py
@@ -136,15 +136,13 @@ async def upload_file(
else: # new_file
message = "File uploaded successfully"
- # If workflowId is provided, update the file information
- if workflowId:
- updateData = {"workflowId": workflowId}
- managementInterface.updateFile(fileItem.id, updateData)
- fileItem.workflowId = workflowId
-
# Convert FileItem to dictionary for JSON response
fileMeta = fileItem.model_dump()
+ # If workflowId is provided, include it in the response (not stored in FileItem model)
+ if workflowId:
+ fileMeta["workflowId"] = workflowId
+
# Response with duplicate information
return JSONResponse({
"message": message,
diff --git a/modules/routes/routeDataUsers.py b/modules/routes/routeDataUsers.py
index ed55b11f..b3da0c2e 100644
--- a/modules/routes/routeDataUsers.py
+++ b/modules/routes/routeDataUsers.py
@@ -21,7 +21,7 @@ import modules.interfaces.interfaceDbApp as interfaceDbApp
from modules.auth import limiter, getRequestContext, RequestContext
# Import the attribute definition and helper functions
-from modules.datamodels.datamodelUam import User
+from modules.datamodels.datamodelUam import User, UserInDB
from modules.datamodels.datamodelPagination import PaginationParams, PaginatedResponse, PaginationMetadata, normalize_pagination_dict
# Configure logger
diff --git a/modules/routes/routeSecurityGoogle.py b/modules/routes/routeSecurityGoogle.py
index 39edcf8b..a4795243 100644
--- a/modules/routes/routeSecurityGoogle.py
+++ b/modules/routes/routeSecurityGoogle.py
@@ -17,6 +17,7 @@ from modules.interfaces.interfaceDbApp import getInterface, getRootInterface
from modules.datamodels.datamodelUam import AuthAuthority, User, ConnectionStatus, UserConnection
from modules.auth import getCurrentUser, limiter
from modules.auth import createAccessToken, setAccessTokenCookie, createRefreshToken, setRefreshTokenCookie
+from modules.auth.tokenManager import TokenManager
from modules.shared.timeUtils import createExpirationTimestamp, getUtcTimestamp, parseTimestamp
# Configure logger
diff --git a/modules/routes/routeSecurityMsft.py b/modules/routes/routeSecurityMsft.py
index bc637222..921ddafe 100644
--- a/modules/routes/routeSecurityMsft.py
+++ b/modules/routes/routeSecurityMsft.py
@@ -18,6 +18,7 @@ from modules.datamodels.datamodelUam import AuthAuthority, User, ConnectionStatu
from modules.datamodels.datamodelSecurity import Token
from modules.auth import getCurrentUser, limiter
from modules.auth import createAccessToken, setAccessTokenCookie, createRefreshToken, setRefreshTokenCookie
+from modules.auth.tokenManager import TokenManager
from modules.shared.timeUtils import createExpirationTimestamp, getUtcTimestamp, parseTimestamp
# Configure logger
diff --git a/modules/services/serviceAi/subContentExtraction.py b/modules/services/serviceAi/subContentExtraction.py
index 696ba377..a7250a3a 100644
--- a/modules/services/serviceAi/subContentExtraction.py
+++ b/modules/services/serviceAi/subContentExtraction.py
@@ -15,7 +15,7 @@ import base64
from typing import Dict, Any, List, Optional
from modules.datamodels.datamodelChat import ChatDocument
-from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent
+from modules.datamodels.datamodelExtraction import ContentPart, DocumentIntent, ExtractionOptions, MergeStrategy
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
logger = logging.getLogger(__name__)
diff --git a/modules/workflows/methods/methodAi/actions/process.py b/modules/workflows/methods/methodAi/actions/process.py
index cdaf55b6..1ab4a7ee 100644
--- a/modules/workflows/methods/methodAi/actions/process.py
+++ b/modules/workflows/methods/methodAi/actions/process.py
@@ -6,7 +6,7 @@ import time
import json
from typing import Dict, Any, List, Optional
from modules.datamodels.datamodelChat import ActionResult, ActionDocument
-from modules.datamodels.datamodelAi import AiCallOptions
+from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, ProcessingModeEnum
from modules.datamodels.datamodelExtraction import ContentPart
logger = logging.getLogger(__name__)
diff --git a/modules/workflows/processing/core/taskPlanner.py b/modules/workflows/processing/core/taskPlanner.py
index 94c695cb..b1e1def7 100644
--- a/modules/workflows/processing/core/taskPlanner.py
+++ b/modules/workflows/processing/core/taskPlanner.py
@@ -6,7 +6,7 @@
import json
import logging
from typing import Dict, Any
-from modules.datamodels.datamodelChat import TaskStep, TaskContext, TaskPlan
+from modules.datamodels.datamodelChat import TaskStep, TaskContext, TaskPlan, WorkflowModeEnum
from modules.datamodels.datamodelAi import AiCallOptions, OperationTypeEnum, ProcessingModeEnum, PriorityEnum
from modules.workflows.processing.shared.promptGenerationTaskplan import (
generateTaskPlanningPrompt
diff --git a/modules/workflows/processing/modes/modeDynamic.py b/modules/workflows/processing/modes/modeDynamic.py
index 45b92961..1510e512 100644
--- a/modules/workflows/processing/modes/modeDynamic.py
+++ b/modules/workflows/processing/modes/modeDynamic.py
@@ -11,7 +11,7 @@ from datetime import datetime, timezone
from typing import List, Dict, Any
from modules.datamodels.datamodelChat import (
TaskStep, TaskContext, TaskResult, ActionItem, TaskStatus,
- ActionResult, Observation, ObservationPreview, ReviewResult
+ ActionResult, Observation, ObservationPreview, ReviewResult, ReviewContext
)
from modules.datamodels.datamodelChat import ChatWorkflow
from modules.workflows.processing.modes.modeBase import BaseMode
diff --git a/modules/workflows/processing/workflowProcessor.py b/modules/workflows/processing/workflowProcessor.py
index c73d280b..11879e9d 100644
--- a/modules/workflows/processing/workflowProcessor.py
+++ b/modules/workflows/processing/workflowProcessor.py
@@ -13,7 +13,7 @@ from modules.workflows.processing.modes.modeBase import BaseMode
from modules.workflows.processing.modes.modeDynamic import DynamicMode
from modules.workflows.processing.modes.modeAutomation import AutomationMode
from modules.workflows.processing.shared.stateTools import checkWorkflowStopped
-from modules.datamodels.datamodelAi import OperationTypeEnum, PriorityEnum, ProcessingModeEnum
+from modules.datamodels.datamodelAi import OperationTypeEnum, PriorityEnum, ProcessingModeEnum, AiCallOptions
from modules.shared.jsonUtils import extractJsonString, repairBrokenJson
if TYPE_CHECKING: