Update app.py

This commit is contained in:
dev 2026-11-02 04:46:50 +00:00
parent 48a035401a
commit 7b39b8957d

20
app.py
View File

@ -1,4 +1,3 @@
# app.py
import base64 import base64
import hashlib import hashlib
import html import html
@ -37,7 +36,9 @@ CLIENT_HASH_KEY_PATH = os.environ.get(
str(Path(DB_PATH).resolve().parent / "client_hash.key"), str(Path(DB_PATH).resolve().parent / "client_hash.key"),
) )
MAX_REQUEST_BYTES = 6 * 1024 * 1024 MAX_ATTACHMENT_BYTES = 100 * 1024 * 1024
MAX_REQUEST_BYTES = max(110 * 1024 * 1024, MAX_ATTACHMENT_BYTES + 10 * 1024 * 1024)
MAX_MESSAGE_LENGTH = 1000 MAX_MESSAGE_LENGTH = 1000
MAX_USERNAME_LENGTH = 30 MAX_USERNAME_LENGTH = 30
MIN_USERNAME_LENGTH = 3 MIN_USERNAME_LENGTH = 3
@ -47,7 +48,6 @@ MAX_HISTORY_MESSAGES = 100
MAX_INCREMENTAL_MESSAGES = 100 MAX_INCREMENTAL_MESSAGES = 100
MAX_FEED_MESSAGES = 50 MAX_FEED_MESSAGES = 50
MAX_THREAD_REPLIES = 100 MAX_THREAD_REPLIES = 100
MAX_ATTACHMENT_BYTES = 100 * 1024 * 1024
MAX_ATTACHMENT_NAME_LENGTH = 150 MAX_ATTACHMENT_NAME_LENGTH = 150
ATTACHMENT_ORPHAN_TTL_HOURS = 24 ATTACHMENT_ORPHAN_TTL_HOURS = 24
ATTACHMENT_CLEANUP_INTERVAL_SECONDS = 60 * 60 ATTACHMENT_CLEANUP_INTERVAL_SECONDS = 60 * 60
@ -993,7 +993,7 @@ def require_writable_user():
def require_moderator(): def require_moderator():
user, error = require_writable_user() user, error = require_writable_user()
if error: if error:
return error[0] if isinstance(error, tuple) and len(error) == 2 else error return None, error
if user["role"] not in {"moderator", "admin"}: if user["role"] not in {"moderator", "admin"}:
return None, (jsonify({"error": "Moderator access required.", "code": "forbidden"}), 403) return None, (jsonify({"error": "Moderator access required.", "code": "forbidden"}), 403)
return user, None return user, None
@ -1021,7 +1021,14 @@ def setup_request_security():
if request_blacklisted(): if request_blacklisted():
if request.path.startswith("/api/"): if request.path.startswith("/api/"):
return jsonify({"error": "Access to this service has been blocked.", "code": "blacklisted"}), 403 return jsonify({"error": "Access to this service has been blocked.", "code": "blacklisted"}), 403
return render_template("blocked.html", asset_version=get_asset_version()), 403 try:
return render_template("blocked.html", asset_version=get_asset_version()), 403
except Exception:
return (
"<!doctype html><html><head><meta charset='utf-8'><title>access blocked</title></head>"
"<body><h1>access blocked</h1><p>access is unavailable.</p></body></html>",
403,
)
@app.context_processor @app.context_processor
@ -1037,6 +1044,7 @@ def add_security_headers(response):
response.headers["Permissions-Policy"] = "camera=(self), microphone=(self), geolocation=()" response.headers["Permissions-Policy"] = "camera=(self), microphone=(self), geolocation=()"
response.headers["Cross-Origin-Opener-Policy"] = "same-origin" response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
response.headers["Cross-Origin-Resource-Policy"] = "same-origin" response.headers["Cross-Origin-Resource-Policy"] = "same-origin"
calls_connect_origin = CALLS_BASE calls_connect_origin = CALLS_BASE
calls_ws_origin = CALLS_BASE.replace("https://", "wss://").replace("http://", "ws://") calls_ws_origin = CALLS_BASE.replace("https://", "wss://").replace("http://", "ws://")
@ -1052,10 +1060,12 @@ def add_security_headers(response):
"script-src 'self'; " "script-src 'self'; "
f"connect-src 'self' {calls_connect_origin} {calls_ws_origin};" f"connect-src 'self' {calls_connect_origin} {calls_ws_origin};"
) )
if request.path.startswith("/static/"): if request.path.startswith("/static/"):
response.headers["Cache-Control"] = "public, max-age=31536000, immutable" response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
else: else:
response.headers["Cache-Control"] = "no-store" response.headers["Cache-Control"] = "no-store"
return response return response