Update app.py

This commit is contained in:
2026-05-05 20:47:44 +02:00
parent dbe4b21889
commit 2d538d6542
+34 -28
View File
@@ -5,6 +5,7 @@ import logging
import threading
from collections import defaultdict
from datetime import datetime, timezone
from threading import Lock
import requests
from flask import Flask, request, Response
@@ -65,11 +66,8 @@ logging.basicConfig(
format="%(message)s"
)
# 🔇 HTTP Noise entfernen
logging.getLogger("werkzeug").setLevel(logging.ERROR)
logging.getLogger("urllib3").setLevel(logging.WARNING)
# 🔇 Gunicorn Access Logs entfernen
logging.getLogger("gunicorn.access").setLevel(logging.WARNING)
logger = logging.getLogger("matrix-interceptor")
@@ -83,7 +81,7 @@ def log_event(event: str, **kwargs):
logger.info(f"{base} {details}")
def debug_log(title, data):
if os.getenv("DEBUG", "false").lower() == "true":
if config.debug:
logger.debug(f"{title}: {json.dumps(data, default=str)}")
# ============================================================
@@ -104,9 +102,10 @@ if missing:
KNOWN_EXTERNAL_USERS = {}
RATE_LIMIT = defaultdict(list)
METRICS = defaultdict(int)
METRICS_LOCK = Lock()
CACHE_FILE = "/app/cache/known_users.json"
CACHE_DIRTY = True
CACHE_DIRTY = False
# ============================================================
# CACHE HANDLING
@@ -114,19 +113,20 @@ CACHE_DIRTY = True
def load_cache():
global KNOWN_EXTERNAL_USERS
if os.path.exists(CACHE_FILE):
try:
with open(CACHE_FILE, "r") as f:
KNOWN_EXTERNAL_USERS = json.load(f)
logger.info(f"Loaded cache with {len(KNOWN_EXTERNAL_USERS)} users")
except:
except Exception as e:
logger.error(f"Cache load failed: {e}")
KNOWN_EXTERNAL_USERS = {}
else:
# 🔥 neu: Datei initial anlegen
os.makedirs(os.path.dirname(CACHE_FILE), exist_ok=True)
with open(CACHE_FILE, "w") as f:
json.dump({}, f)
logger.info("Initialized empty cache file")
logger.info("Initialized empty cache")
def save_cache():
global CACHE_DIRTY
@@ -154,7 +154,7 @@ def periodic_cache_save():
def extract_domain(user_id):
try:
return user_id.split(":")[1].lower().rstrip(".")
except:
except Exception:
return "unknown"
def is_external(user_id):
@@ -175,30 +175,32 @@ def remember_user(user_id):
global CACHE_DIRTY
KNOWN_EXTERNAL_USERS[user_id] = time.time()
CACHE_DIRTY = True
save_cache() # 🔥 critical safety write
def is_local_room(room_id):
try:
return room_id.split(":")[1] == config.local_domain
except:
except Exception:
return False
def get_role(user_id):
return "admin" if user_id in config.admin_users else "user"
# ============================================================
# RATE LIMIT (IMPROVED)
# RATE LIMIT
# ============================================================
def is_rate_limited(domain, sender):
key = f"{domain}:{sender}"
def is_rate_limited(domain):
now = time.time()
RATE_LIMIT[key] = [t for t in RATE_LIMIT[key] if now - t < 60]
RATE_LIMIT[domain] = [
t for t in RATE_LIMIT[domain] if now - t < 60
]
if len(RATE_LIMIT[key]) >= config.rate_limit_per_minute:
if len(RATE_LIMIT[domain]) >= config.rate_limit_per_minute:
return True
RATE_LIMIT[key].append(now)
RATE_LIMIT[domain].append(now)
return False
# ============================================================
@@ -280,8 +282,8 @@ def is_user_in_local_rooms(user_id):
if user_id in members_res.json().get("joined", {}):
return True
except:
return False
except Exception as e:
logger.error(f"Fallback check failed: {e}")
return False
@@ -348,7 +350,9 @@ def create_room():
)
if not allowed:
METRICS["create_room_blocked"] += 1
with METRICS_LOCK:
METRICS["create_room_blocked"] += 1
log_event(
"create_room_blocked",
actor=user_id,
@@ -359,7 +363,9 @@ def create_room():
return Response(json.dumps({"errcode": "M_FORBIDDEN"}), status=403)
if is_dm:
METRICS["create_room_allowed"] += 1
with METRICS_LOCK:
METRICS["create_room_allowed"] += 1
log_event(
"create_room_allowed",
actor=user_id,
@@ -387,13 +393,12 @@ def invite(room_id, event_id):
domain = extract_domain(sender)
if is_rate_limited(domain, sender):
if is_rate_limited(domain):
return Response(status=429)
if domain in config.domain_whitelist:
remember_user(sender)
METRICS["invite_allowed"] += 1
return forward_request(...)
return forward_request(
"PUT",
f"{config.tuwunel_url}/_matrix/federation/v2/invite/{room_id}/{event_id}",
request.headers,
@@ -406,11 +411,8 @@ def invite(room_id, event_id):
if not is_known_user(sender):
# 🔥 fallback fix
if is_user_in_local_rooms(sender):
remember_user(sender)
METRICS["invite_allowed"] += 1
return forward_request(
"PUT",
f"{config.tuwunel_url}/_matrix/federation/v2/invite/{room_id}/{event_id}",
@@ -419,7 +421,9 @@ def invite(room_id, event_id):
)
else:
METRICS["invite_blocked"] += 1
with METRICS_LOCK:
METRICS["invite_blocked"] += 1
log_event(
"invite_blocked",
actor=sender,
@@ -429,7 +433,9 @@ def invite(room_id, event_id):
return Response(status=403)
remember_user(sender)
METRICS["invite_allowed"] += 1
with METRICS_LOCK:
METRICS["invite_allowed"] += 1
return forward_request(
"PUT",