Enhance logging: change log level to DEBUG and add detailed database connection logging in user and tenant modules
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+2
-2
@@ -81,12 +81,12 @@ from tenant import get_tenant_context
|
|||||||
|
|
||||||
|
|
||||||
app = Flask(__name__, static_folder='static') # Correctly set static folder
|
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):
|
if not os.path.exists(cfg.LOGS_FOLDER):
|
||||||
os.makedirs(cfg.LOGS_FOLDER, exist_ok=True)
|
os.makedirs(cfg.LOGS_FOLDER, exist_ok=True)
|
||||||
log_file_path = os.path.join(cfg.LOGS_FOLDER, 'application.log')
|
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 = 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'))
|
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(name)s %(message)s'))
|
||||||
app.logger.handlers = []
|
app.logger.handlers = []
|
||||||
app.logger.addHandler(file_handler)
|
app.logger.addHandler(file_handler)
|
||||||
|
|||||||
+74
-4
@@ -13,6 +13,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import settings as cfg
|
import settings as cfg
|
||||||
|
from settings import MongoClient
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -32,6 +33,21 @@ def _get_nested_value(source, path, default=None):
|
|||||||
return current
|
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):
|
def _parse_port_from_host(host):
|
||||||
"""Parse host header and return (hostname, port) when a numeric port is present."""
|
"""Parse host header and return (hostname, port) when a numeric port is present."""
|
||||||
if host.startswith('['):
|
if host.startswith('['):
|
||||||
@@ -84,6 +100,52 @@ def get_tenant_config(tenant_id=None):
|
|||||||
return TENANT_REGISTRY.get('default', {}) or {}
|
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):
|
def is_tenant_module_enabled(module_name, tenant_id=None, default=False):
|
||||||
"""Resolve whether a feature module is enabled for the current tenant."""
|
"""Resolve whether a feature module is enabled for the current tenant."""
|
||||||
config = get_tenant_config(tenant_id)
|
config = get_tenant_config(tenant_id)
|
||||||
@@ -170,11 +232,19 @@ class TenantContext:
|
|||||||
def _get_db_name(self, tenant_id):
|
def _get_db_name(self, tenant_id):
|
||||||
"""
|
"""
|
||||||
Get MongoDB database name for tenant.
|
Get MongoDB database name for tenant.
|
||||||
Format: inventar_<tenant_id>
|
Format: inventar_<tenant_id> unless tenant config overrides it.
|
||||||
"""
|
"""
|
||||||
# Sanitize tenant_id for MongoDB database name
|
explicit_db = None
|
||||||
sanitized = ''.join(c if c.isalnum() or c == '_' else '' for c in tenant_id.lower())
|
if isinstance(self.config, dict):
|
||||||
db_name = f"inventar_{sanitized}"
|
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
|
self.db_name = db_name
|
||||||
return db_name
|
return db_name
|
||||||
|
|
||||||
|
|||||||
+23
-12
@@ -21,7 +21,8 @@ import settings as cfg
|
|||||||
from settings import MongoClient
|
from settings import MongoClient
|
||||||
|
|
||||||
logger = logging.getLogger('app')
|
logger = logging.getLogger('app')
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.DEBUG)
|
||||||
|
logger.propagate = True
|
||||||
|
|
||||||
|
|
||||||
def normalize_student_card_id(card_id):
|
def normalize_student_card_id(card_id):
|
||||||
@@ -449,22 +450,32 @@ def check_nm_pwd(username, password):
|
|||||||
try:
|
try:
|
||||||
hashed_password = hashing(password)
|
hashed_password = hashing(password)
|
||||||
logger.info("check_nm_pwd password hash for username=%r: %s", username, hashed_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]
|
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']
|
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:
|
if user_record is None:
|
||||||
try:
|
logger.warning("No user document found in db=%r for username=%r", db_name, username)
|
||||||
available_dbs = client.list_database_names()
|
if db_name not in available_dbs:
|
||||||
logger.warning(
|
logger.warning("Tenant database %r is missing from available MongoDB databases", db_name)
|
||||||
"No user document in tenant database %r for username=%r. Available databases=%s",
|
if 'users' not in existing_collections:
|
||||||
db_name,
|
logger.warning("Tenant database %r has no users collection", db_name)
|
||||||
username,
|
|
||||||
available_dbs,
|
|
||||||
)
|
|
||||||
except Exception as exc:
|
|
||||||
logger.exception("Could not list databases during failed login check: %s", exc)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.info("Found user document for username=%r in db=%r: %s", username, db_name, user_record)
|
logger.info("Found user document for username=%r in db=%r: %s", username, db_name, user_record)
|
||||||
|
|||||||
Reference in New Issue
Block a user