From b06828cc7ea435e90bd3814f0fae47cd0d84d7be Mon Sep 17 00:00:00 2001 From: AIIrondev Date: Wed, 29 Apr 2026 13:44:22 +0200 Subject: [PATCH] Enhance logging: change log level to DEBUG and add detailed database connection logging in user and tenant modules Co-authored-by: Copilot --- Web/app.py | 4 +-- Web/tenant.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++--- Web/user.py | 35 +++++++++++++++-------- 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/Web/app.py b/Web/app.py index 29d6f5a..5d7f00d 100755 --- a/Web/app.py +++ b/Web/app.py @@ -81,12 +81,12 @@ from tenant import get_tenant_context app = Flask(__name__, static_folder='static') # Correctly set static folder -app.logger.setLevel(logging.INFO) +app.logger.setLevel(logging.DEBUG) if not os.path.exists(cfg.LOGS_FOLDER): os.makedirs(cfg.LOGS_FOLDER, exist_ok=True) log_file_path = os.path.join(cfg.LOGS_FOLDER, 'application.log') file_handler = RotatingFileHandler(log_file_path, maxBytes=10 * 1024 * 1024, backupCount=5, encoding='utf-8') -file_handler.setLevel(logging.INFO) +file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(name)s %(message)s')) app.logger.handlers = [] app.logger.addHandler(file_handler) diff --git a/Web/tenant.py b/Web/tenant.py index 2f49d44..cbe4eff 100644 --- a/Web/tenant.py +++ b/Web/tenant.py @@ -13,6 +13,7 @@ import logging import os import re import settings as cfg +from settings import MongoClient logger = logging.getLogger(__name__) @@ -32,6 +33,21 @@ def _get_nested_value(source, path, default=None): return current +def _parse_tenant_db_map(): + mapping = {} + raw_map = os.getenv('INVENTAR_TENANT_DB_MAP', '').strip() + if not raw_map: + return mapping + + for mapping_pair in re.split(r'[;,\s]+', raw_map): + if '=' not in mapping_pair: + continue + key, value = mapping_pair.split('=', 1) + mapping[key.strip()] = value.strip() + + return mapping + + def _parse_port_from_host(host): """Parse host header and return (hostname, port) when a numeric port is present.""" if host.startswith('['): @@ -84,6 +100,52 @@ def get_tenant_config(tenant_id=None): return TENANT_REGISTRY.get('default', {}) or {} +def _normalize_db_name(db_name): + if not db_name: + return None + db_name = str(db_name).strip() + if db_name and not db_name.startswith('inventar_'): + db_name = f'inventar_{db_name}' + return db_name + + +def _tenant_db_aliases(tenant_id): + aliases = [] + env_map = _parse_tenant_db_map() + if tenant_id in env_map: + aliases.append(env_map[tenant_id]) + + if tenant_id.lower().startswith('schule'): + aliases.append(tenant_id.lower().replace('schule', 'school', 1)) + elif tenant_id.lower().startswith('school'): + aliases.append(tenant_id.lower().replace('school', 'schule', 1)) + + return [alias for alias in aliases if alias] + + +def _resolve_db_alias(tenant_id, db_name): + try: + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) + available_databases = client.list_database_names() + if db_name in available_databases: + return db_name + + for alias in _tenant_db_aliases(tenant_id): + candidate = _normalize_db_name(alias) + if candidate in available_databases: + logger.warning( + "Tenant DB fallback applied for tenant %r: %r -> %r", + tenant_id, + db_name, + candidate, + ) + return candidate + except Exception as exc: + logger.exception("Tenant DB alias resolution failed for %r: %s", tenant_id, exc) + + return db_name + + def is_tenant_module_enabled(module_name, tenant_id=None, default=False): """Resolve whether a feature module is enabled for the current tenant.""" config = get_tenant_config(tenant_id) @@ -170,11 +232,19 @@ class TenantContext: def _get_db_name(self, tenant_id): """ Get MongoDB database name for tenant. - Format: inventar_ + Format: inventar_ unless tenant config overrides it. """ - # Sanitize tenant_id for MongoDB database name - sanitized = ''.join(c if c.isalnum() or c == '_' else '' for c in tenant_id.lower()) - db_name = f"inventar_{sanitized}" + explicit_db = None + if isinstance(self.config, dict): + explicit_db = self.config.get('db') or self.config.get('db_name') + + if explicit_db: + db_name = _normalize_db_name(explicit_db) + else: + sanitized = ''.join(c if c.isalnum() or c == '_' else '' for c in tenant_id.lower()) + db_name = f"inventar_{sanitized}" + + db_name = _resolve_db_alias(tenant_id, db_name) self.db_name = db_name return db_name diff --git a/Web/user.py b/Web/user.py index 9c20182..e6fe86b 100755 --- a/Web/user.py +++ b/Web/user.py @@ -21,7 +21,8 @@ import settings as cfg from settings import MongoClient logger = logging.getLogger('app') -logger.setLevel(logging.INFO) +logger.setLevel(logging.DEBUG) +logger.propagate = True def normalize_student_card_id(card_id): @@ -449,22 +450,32 @@ def check_nm_pwd(username, password): try: hashed_password = hashing(password) logger.info("check_nm_pwd password hash for username=%r: %s", username, hashed_password) + available_dbs = [] + try: + available_dbs = client.list_database_names() + logger.debug("MongoDB connected. Available databases=%s", available_dbs) + except Exception as exc: + logger.exception("Unable to list MongoDB databases: %s", exc) db = client[db_name] + try: + existing_collections = db.list_collection_names() + except Exception as exc: + logger.exception("Unable to list collections for db=%r: %s", db_name, exc) + existing_collections = [] + logger.debug("Tenant db=%r collections=%s", db_name, existing_collections) + users = db['users'] - user_record = users.find_one({'$or': [{'Username': username}, {'username': username}]}) + query = {'$or': [{'Username': username}, {'username': username}]} + logger.debug("Running user lookup on %r: %s", db_name, query) + user_record = users.find_one(query) if user_record is None: - try: - available_dbs = client.list_database_names() - logger.warning( - "No user document in tenant database %r for username=%r. Available databases=%s", - db_name, - username, - available_dbs, - ) - except Exception as exc: - logger.exception("Could not list databases during failed login check: %s", exc) + logger.warning("No user document found in db=%r for username=%r", db_name, username) + if db_name not in available_dbs: + logger.warning("Tenant database %r is missing from available MongoDB databases", db_name) + if 'users' not in existing_collections: + logger.warning("Tenant database %r has no users collection", db_name) return None logger.info("Found user document for username=%r in db=%r: %s", username, db_name, user_record)