From 20d2bf215fdea22246a5fa7085a3788ce85beccb Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Sat, 28 Mar 2026 18:28:35 +0100 Subject: [PATCH] fixes --- modules/auth/tokenManager.py | 2 +- .../features/automation2/mainAutomation2.py | 13 +++++++++++ modules/interfaces/interfaceDbApp.py | 13 ++++------- .../services/serviceChat/mainServiceChat.py | 3 ++- modules/shared/dbMultiTenantOptimizations.py | 22 +++++++++++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/modules/auth/tokenManager.py b/modules/auth/tokenManager.py index 5740a2ac..940de055 100644 --- a/modules/auth/tokenManager.py +++ b/modules/auth/tokenManager.py @@ -181,7 +181,7 @@ class TokenManager: # Only allow a new refresh if at least 10 minutes passed since the token was created/refreshed try: nowTs = getUtcTimestamp() - createdTs = parseTimestamp(oldToken.createdAt, default=0.0) + createdTs = parseTimestamp(oldToken.sysCreatedAt, default=0.0) secondsSinceLastRefresh = nowTs - createdTs if secondsSinceLastRefresh < 10 * 60: logger.info( diff --git a/modules/features/automation2/mainAutomation2.py b/modules/features/automation2/mainAutomation2.py index 9ec97eca..08038e68 100644 --- a/modules/features/automation2/mainAutomation2.py +++ b/modules/features/automation2/mainAutomation2.py @@ -77,6 +77,19 @@ TEMPLATE_ROLES = [ {"context": "DATA", "item": None, "view": True, "read": "m", "create": "m", "update": "m", "delete": "m"}, ] }, + { + "roleLabel": "automation2-admin", + "description": { + "en": "Automation2 Admin - Full UI and API for the instance; data remains user-scoped (MY)", + "de": "Automation2 Admin - Volle UI und API für die Instanz; Daten weiterhin benutzerspezifisch (MY)", + "fr": "Administrateur Automation2 - UI et API complets pour l'instance; donnees limitees a l'utilisateur (MY)", + }, + "accessRules": [ + {"context": "UI", "item": None, "view": True}, + {"context": "RESOURCE", "item": None, "view": True}, + {"context": "DATA", "item": None, "view": True, "read": "m", "create": "m", "update": "m", "delete": "m"}, + ], + }, ] diff --git a/modules/interfaces/interfaceDbApp.py b/modules/interfaces/interfaceDbApp.py index 2a6b0f78..ee1dc379 100644 --- a/modules/interfaces/interfaceDbApp.py +++ b/modules/interfaces/interfaceDbApp.py @@ -2858,8 +2858,8 @@ class AppObjects: # Ensure token has required fields if not token.id: token.id = str(uuid.uuid4()) - if not token.createdAt: - token.createdAt = getUtcTimestamp() + if not token.sysCreatedAt: + token.sysCreatedAt = getUtcTimestamp() # If replace_existing is True, delete old access tokens for this user and authority first if replace_existing: @@ -2892,12 +2892,7 @@ class AppObjects: ) # Continue with saving the new token even if deletion fails - # Convert to dict and ensure all fields are properly set token_dict = token.model_dump() - # Ensure userId is set to current user - # Convert to dict and ensure all fields are properly set - token_dict = token.model_dump() - # Ensure userId is set to current user token_dict["userId"] = self.currentUser.id # Save to database @@ -2936,8 +2931,8 @@ class AppObjects: # Ensure token has required fields if not token.id: token.id = str(uuid.uuid4()) - if not token.createdAt: - token.createdAt = getUtcTimestamp() + if not token.sysCreatedAt: + token.sysCreatedAt = getUtcTimestamp() # Convert to dict and ensure all fields are properly set token_dict = token.model_dump() diff --git a/modules/serviceCenter/services/serviceChat/mainServiceChat.py b/modules/serviceCenter/services/serviceChat/mainServiceChat.py index b05b0c64..40769fae 100644 --- a/modules/serviceCenter/services/serviceChat/mainServiceChat.py +++ b/modules/serviceCenter/services/serviceChat/mainServiceChat.py @@ -333,7 +333,8 @@ class ChatService: token_status = "expired" else: # Check if this token was recently refreshed (within last 5 minutes) - time_since_creation = current_time - token.createdAt if hasattr(token, 'createdAt') else 0 + createdTs = getattr(token, "sysCreatedAt", None) + time_since_creation = (current_time - createdTs) if createdTs else 0 if time_since_creation < 300: # 5 minutes token_status = "valid (refreshed)" else: diff --git a/modules/shared/dbMultiTenantOptimizations.py b/modules/shared/dbMultiTenantOptimizations.py index 95ad6cae..c178c376 100644 --- a/modules/shared/dbMultiTenantOptimizations.py +++ b/modules/shared/dbMultiTenantOptimizations.py @@ -21,6 +21,18 @@ from typing import Optional, List logger = logging.getLogger(__name__) +def _ensureUamTablesMatchModels(dbConnector) -> None: + """Run connector schema sync so sys* columns exist before we CREATE INDEX on them.""" + if not hasattr(dbConnector, "_ensureTableExists"): + return + try: + from modules.datamodels.datamodelInvitation import Invitation + + dbConnector._ensureTableExists(Invitation) + except Exception as e: + logger.debug(f"_ensureUamTablesMatchModels: {e}") + + def _getConnection(dbConnector): """Get a connection from the DatabaseConnector. @@ -176,6 +188,11 @@ def applyMultiTenantOptimizations(dbConnector, tables: Optional[List[str]] = Non except Exception as autoErr: logger.debug(f"Could not set autocommit: {autoErr}") + try: + _ensureUamTablesMatchModels(dbConnector) + except Exception as preIdxErr: + logger.debug(f"Pre-index table ensure: {preIdxErr}") + try: with conn.cursor() as cursor: # Apply indexes @@ -214,6 +231,11 @@ def applyIndexesOnly(dbConnector, tables: Optional[List[str]] = None) -> int: originalAutocommit = conn.autocommit conn.autocommit = True + try: + _ensureUamTablesMatchModels(dbConnector) + except Exception as preIdxErr: + logger.debug(f"Pre-index table ensure: {preIdxErr}") + try: with conn.cursor() as cursor: return _applyIndexes(cursor, tables)