bypass profile select
This commit is contained in:
@@ -68,3 +68,4 @@ PYTORRENT_SESSION_COOKIE_SECURE=false
|
|||||||
|
|
||||||
# bypass auth on specific hosts (ex. local ip)
|
# bypass auth on specific hosts (ex. local ip)
|
||||||
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
||||||
|
PYTORRENT_AUTH_BYPASS_USER=admin
|
||||||
11
auth.md
11
auth.md
@@ -35,6 +35,9 @@ PYTORRENT_AUTH_PROXY_AUTO_CREATE_PERMISSION=rw
|
|||||||
# Optional: trusted direct-IP/local hosts that should skip pyTorrent auth.
|
# Optional: trusted direct-IP/local hosts that should skip pyTorrent auth.
|
||||||
# Use this only on private networks, never on public proxy hostnames.
|
# Use this only on private networks, never on public proxy hostnames.
|
||||||
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
||||||
|
|
||||||
|
# Existing active user used by bypassed requests. Defaults to admin.
|
||||||
|
PYTORRENT_AUTH_BYPASS_USER=admin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -137,15 +140,19 @@ Example:
|
|||||||
PYTORRENT_AUTH_ENABLE=true
|
PYTORRENT_AUTH_ENABLE=true
|
||||||
PYTORRENT_AUTH_PROVIDER=tinyauth
|
PYTORRENT_AUTH_PROVIDER=tinyauth
|
||||||
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
PYTORRENT_AUTH_BYPASS_HOSTS=10.11.1.11:8090,10.11.1.11
|
||||||
|
|
||||||
|
# Existing active user used by bypassed requests. Defaults to admin.
|
||||||
|
PYTORRENT_AUTH_BYPASS_USER=admin
|
||||||
```
|
```
|
||||||
|
|
||||||
Behavior:
|
Behavior:
|
||||||
|
|
||||||
- requests with `Host: 10.11.1.11:8090` or `Host: 10.11.1.11` use the built-in default admin user;
|
- requests with `Host: 10.11.1.11:8090` or `Host: 10.11.1.11` use the built-in default admin user;
|
||||||
- requests through the reverse proxy still require the configured auth provider;
|
- requests through the reverse proxy still require the configured auth provider;
|
||||||
- profile permissions are ignored for bypassed direct-IP requests because they run as the default admin user;
|
- `PYTORRENT_AUTH_BYPASS_USER` must point to an existing active user; when unset, pyTorrent uses `admin`;
|
||||||
|
- if the bypass user is `admin`, profile permissions are ignored because admins can access all profiles;
|
||||||
- when no active profile is saved for the bypass user, pyTorrent opens the profile picker instead of silently selecting the first profile;
|
- when no active profile is saved for the bypass user, pyTorrent opens the profile picker instead of silently selecting the first profile;
|
||||||
- after selecting a profile, the choice is saved in the default user's preferences and reused on the next direct-IP visit.
|
- after selecting a profile, the choice is saved in the bypass user's preferences and reused on the next direct-IP visit.
|
||||||
|
|
||||||
Do not add public domains to this list.
|
Do not add public domains to this list.
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ _API_ALLOWED_ORIGINS = _env_csv("PYTORRENT_API_ALLOWED_ORIGINS")
|
|||||||
API_ALLOWED_ORIGINS = _API_ALLOWED_ORIGINS or _env_csv("PYTORRENT_SOCKETIO_CORS_ALLOWED_ORIGINS")
|
API_ALLOWED_ORIGINS = _API_ALLOWED_ORIGINS or _env_csv("PYTORRENT_SOCKETIO_CORS_ALLOWED_ORIGINS")
|
||||||
# Note: Optional auth bypass for trusted direct-IP/local access. Values can be hosts or host:port pairs.
|
# Note: Optional auth bypass for trusted direct-IP/local access. Values can be hosts or host:port pairs.
|
||||||
AUTH_BYPASS_HOSTS = {item.lower() for item in _env_csv("PYTORRENT_AUTH_BYPASS_HOSTS")}
|
AUTH_BYPASS_HOSTS = {item.lower() for item in _env_csv("PYTORRENT_AUTH_BYPASS_HOSTS")}
|
||||||
|
# Note: Trusted auth-bypass requests act as this existing active user.
|
||||||
|
AUTH_BYPASS_USER = os.getenv("PYTORRENT_AUTH_BYPASS_USER", "admin").strip() or "admin"
|
||||||
|
|
||||||
TRAFFIC_HISTORY_RETENTION_DAYS = _env_int("PYTORRENT_TRAFFIC_HISTORY_RETENTION_DAYS", 90, 1)
|
TRAFFIC_HISTORY_RETENTION_DAYS = _env_int("PYTORRENT_TRAFFIC_HISTORY_RETENTION_DAYS", 90, 1)
|
||||||
JOBS_RETENTION_DAYS = _env_int("PYTORRENT_JOBS_RETENTION_DAYS", 30, 1)
|
JOBS_RETENTION_DAYS = _env_int("PYTORRENT_JOBS_RETENTION_DAYS", 30, 1)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ from ..config import (
|
|||||||
AUTH_PROXY_USER_HEADER,
|
AUTH_PROXY_USER_HEADER,
|
||||||
API_ALLOWED_ORIGINS,
|
API_ALLOWED_ORIGINS,
|
||||||
AUTH_BYPASS_HOSTS,
|
AUTH_BYPASS_HOSTS,
|
||||||
|
AUTH_BYPASS_USER,
|
||||||
)
|
)
|
||||||
from ..db import connect, default_user_id, utcnow
|
from ..db import connect, default_user_id, utcnow
|
||||||
|
|
||||||
@@ -82,9 +83,26 @@ def auth_bypassed_request() -> bool:
|
|||||||
return _host_matches_bypass(request.host)
|
return _host_matches_bypass(request.host)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def bypass_user_id() -> int:
|
||||||
|
"""Return the configured active user id used for trusted auth-bypass requests."""
|
||||||
|
username = str(AUTH_BYPASS_USER or "admin").strip() or "admin"
|
||||||
|
with connect() as conn:
|
||||||
|
row = conn.execute("SELECT id FROM users WHERE username=? AND is_active=1", (username,)).fetchone()
|
||||||
|
if row:
|
||||||
|
return int(row["id"])
|
||||||
|
# Note: Keep direct-IP access usable after old installs, but never choose an inactive fallback.
|
||||||
|
row = conn.execute("SELECT id FROM users WHERE username='admin' AND is_active=1").fetchone()
|
||||||
|
if row:
|
||||||
|
return int(row["id"])
|
||||||
|
row = conn.execute("SELECT id FROM users WHERE id=? AND is_active=1", (default_user_id(),)).fetchone()
|
||||||
|
return int(row["id"]) if row else 0
|
||||||
|
|
||||||
def current_user_id() -> int:
|
def current_user_id() -> int:
|
||||||
if not enabled() or auth_bypassed_request():
|
if not enabled():
|
||||||
return default_user_id()
|
return default_user_id()
|
||||||
|
if auth_bypassed_request():
|
||||||
|
return bypass_user_id()
|
||||||
api_user_id = getattr(g, "api_user_id", None)
|
api_user_id = getattr(g, "api_user_id", None)
|
||||||
if api_user_id:
|
if api_user_id:
|
||||||
return int(api_user_id)
|
return int(api_user_id)
|
||||||
@@ -385,8 +403,10 @@ def authenticate_external_user() -> dict[str, Any] | None:
|
|||||||
def ensure_request_user() -> int:
|
def ensure_request_user() -> int:
|
||||||
# Note: Socket.IO events do not go through Flask before_request like normal REST calls,
|
# Note: Socket.IO events do not go through Flask before_request like normal REST calls,
|
||||||
# so external proxy auth must be resolved explicitly during the Socket.IO handshake/events.
|
# so external proxy auth must be resolved explicitly during the Socket.IO handshake/events.
|
||||||
if not enabled() or auth_bypassed_request():
|
if not enabled():
|
||||||
return default_user_id()
|
return default_user_id()
|
||||||
|
if auth_bypassed_request():
|
||||||
|
return bypass_user_id()
|
||||||
uid = current_user_id()
|
uid = current_user_id()
|
||||||
if uid:
|
if uid:
|
||||||
return uid
|
return uid
|
||||||
|
|||||||
Reference in New Issue
Block a user