aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkj_sh6042026-04-03 17:34:35 -0400
committerkj_sh6042026-04-03 17:34:35 -0400
commite6ff2b91aebcf2e69a988dc04627cd987c2a0f47 (patch)
tree8e59a1632e60856f4f9c42cb60be04da181c76e3
parent9f0a5a6fce2621e320fdeb751243b4878f920401 (diff)
refactor: some productionization changes
-rw-r--r--README4
-rw-r--r--requirements.txt1
-rw-r--r--shim_app.py17
3 files changed, 21 insertions, 1 deletions
diff --git a/README b/README
index 1494a32..b0e2a55 100644
--- a/README
+++ b/README
@@ -14,12 +14,16 @@ quick start (assumes POSIX)
- python3 server.py
- open http://127.0.0.1:8585/app
+production configuration (gunicorn)
+ - gunicorn server:app --bind 0.0.0.0:8585 --workers 2 --threads 4 --timeout 60 --graceful-timeout 30 --keep-alive 5 --access-logfile - --error-logfile -
+
config
- SHIM_APP_NAME: ui/app name (default: shim)
- SHIM_BIND: bind address (default: 0.0.0.0)
- SHIM_PORT: port (default: 8585)
- SHIM_MOJICRYPT_BIN: mojicrypt path (default: ./vendor/mojicrypt)
- SHIM_COOKIE_SECURE: auto|true|false (default: auto)
+ - SHIM_ENFORCE_APP_REQUEST_GUARDS: false by default (set true only when proxy/host headers are correct)
- SHIM_SQLITE_TIMEOUT_SECONDS (default: 30.0)
- SHIM_SQLITE_BUSY_TIMEOUT_MS (default: 30000)
- SHIM_SQLITE_CACHE_SIZE_KIB (default: 32768)
diff --git a/requirements.txt b/requirements.txt
index 6a98c4f..833a7b6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,6 +3,7 @@ click==8.3.1
dnspython==2.8.0
email_validator==2.2.0
Flask==3.1.3
+gunicorn==22.0.0
idna==3.11
itsdangerous==2.2.0
Jinja2==3.1.6
diff --git a/shim_app.py b/shim_app.py
index 2e9bcdd..b84128c 100644
--- a/shim_app.py
+++ b/shim_app.py
@@ -693,6 +693,15 @@ def env_float(name: str, default: float, minimum: float) -> float:
return max(value, minimum)
+def env_bool(name: str, default: bool) -> bool:
+ raw = os.getenv(name, "true" if default else "false").strip().lower()
+ if raw in {"1", "true", "yes", "on"}:
+ return True
+ if raw in {"0", "false", "no", "off"}:
+ return False
+ return default
+
+
def create_app(base_dir: Optional[Path] = None) -> Flask:
project_dir = Path(base_dir or Path(__file__).parent).resolve()
app_name = os.getenv("SHIM_APP_NAME", "shim").strip() or "shim"
@@ -737,6 +746,7 @@ def create_app(base_dir: Optional[Path] = None) -> Flask:
sqlite_wal_autocheckpoint_pages = env_int(
"SHIM_SQLITE_WAL_AUTOCHECKPOINT_PAGES", 1000, 100
)
+ enforce_app_request_guards = env_bool("SHIM_ENFORCE_APP_REQUEST_GUARDS", False)
cookie_secure_mode = os.getenv("SHIM_COOKIE_SECURE", "auto").strip().lower()
if cookie_secure_mode not in {"auto", "true", "false"}:
@@ -1031,7 +1041,12 @@ def create_app(base_dir: Optional[Path] = None) -> Flask:
if user is not None:
g.current_user = user
- if request.method in MUTATING_METHODS and request.path.startswith("/app/"):
+ if (
+ enforce_app_request_guards
+ and g.current_user is not None
+ and request.method in MUTATING_METHODS
+ and request.path.startswith("/app/")
+ ):
if not is_same_origin_request():
abort(403)
if not is_valid_csrf_for_request():