Odstranil jsem hardcoded IP fallbacky z portálového Python kódu:

DEFAULT_APPFACTORY_HOST = "192.168.66.130" je pryč z config.py (line 10).
DEFAULT_GITEA_URL = "http://192.168.66.130:3000" je pryč z auth.py (line 24).
Doplněné chování:
APPFACTORY_HOST se odvozuje přes helper: env APPFACTORY_HOST, potom APPFACTORY_PORTAL_PUBLIC_URL, potom request host.
Gitea browser redirect používá jen explicitní veřejnou URL z GITEA_URL nebo GITEA_ROOT_URL.
Server-side Gitea token/userinfo requesty používají GITEA_URL, potom GITEA_ROOT_URL, jinak interní Docker URL http://appfactory-gitea:3000.
Gitea login tlačítko se zobrazí jen při kompletní konfiguraci: public URL, client id, client secret a redirect URI.
Přímý Gitea login bez kompletní konfigurace vrací čitelnou chybu.
This commit is contained in:
JiriUhlir
2026-06-08 11:38:57 +02:00
parent 9916e4d833
commit 7dffff17c7
3 changed files with 74 additions and 20 deletions
+42 -1
View File
@@ -8,7 +8,7 @@ APPFACTORY_ENV = "/opt/appfactory/config/appfactory.env"
DEFAULT_BACKUP_DIR = "/opt/appfactory/backups"
DEFAULT_GITEA_ORG = "appfactory"
DEFAULT_APPFACTORY_HOST = "192.168.66.130"
INTERNAL_GITEA_URL = "http://appfactory-gitea:3000"
PORTAL_PREFIX = "/portal"
@@ -58,6 +58,47 @@ def get_google_redirect_uri() -> str:
return ""
def get_gitea_public_url() -> str:
return (read_env_value("GITEA_URL", "") or read_env_value("GITEA_ROOT_URL", "")).rstrip("/")
def get_gitea_server_url() -> str:
return get_gitea_public_url() or INTERNAL_GITEA_URL
def get_gitea_redirect_uri() -> str:
redirect_uri = read_env_value("GITEA_OAUTH_REDIRECT_URI", "").strip()
if redirect_uri:
return redirect_uri
public_url = get_portal_public_url()
if public_url:
return f"{public_url}/auth/gitea/callback"
return ""
def is_gitea_oauth_button_enabled() -> bool:
return bool(
get_gitea_public_url()
and read_env_value("GITEA_OAUTH_CLIENT_ID", "")
and read_env_value("GITEA_OAUTH_CLIENT_SECRET", "")
and get_gitea_redirect_uri()
)
def get_appfactory_host(request_host: str = "") -> str:
configured_host = read_env_value("APPFACTORY_HOST", "").strip()
if configured_host:
return configured_host
public_url = get_portal_public_url()
if public_url:
return public_url.split("://", 1)[-1].split("/", 1)[0].split(":", 1)[0]
return (request_host or "").split(":", 1)[0]
def get_auth_domain_readiness() -> dict[str, bool]:
google_enabled = read_env_bool("GOOGLE_OAUTH_ENABLED")
google_client_id = read_env_value("GOOGLE_CLIENT_ID", "")
+7 -6
View File
@@ -7,11 +7,12 @@ from fastapi.responses import HTMLResponse, RedirectResponse
from ..auth import require_user
from ..config import (
DEFAULT_APPFACTORY_HOST,
DEFAULT_GITEA_ORG,
DELETE_APP_SCRIPT,
DEPLOY_SCRIPT,
GENERATE_COMPOSE_SCRIPT,
get_appfactory_host,
get_gitea_public_url,
read_env_value,
)
from ..db.apps import (
@@ -206,9 +207,9 @@ def apps_page(
offset = (page_number - 1) * DEFAULT_PAGE_SIZE
apps = apps[offset : offset + DEFAULT_PAGE_SIZE]
gitea_url = read_env_value("GITEA_URL", "")
gitea_url = get_gitea_public_url()
gitea_org = read_env_value("GITEA_ORG", DEFAULT_GITEA_ORG)
host = read_env_value("APPFACTORY_HOST", DEFAULT_APPFACTORY_HOST)
host = get_appfactory_host(request.url.hostname or "")
rows = ""
@@ -226,8 +227,8 @@ def apps_page(
memory_label = memory or "výchozí"
cpus_label = cpus or "výchozí"
http_clone = html.escape(f"git clone {gitea_url}/{gitea_org}/{app_id}.git")
ssh_clone = html.escape(f"git clone ssh://git@{host}:2222/{gitea_org}/{app_id}.git")
http_clone = html.escape(f"git clone {gitea_url}/{gitea_org}/{app_id}.git") if gitea_url else ""
ssh_clone = html.escape(f"git clone ssh://git@{host}:2222/{gitea_org}/{app_id}.git") if host else ""
rows += f"""
<tr class="service-row">
@@ -970,7 +971,7 @@ def create_app(
user=user,
)
gitea_url = read_env_value("GITEA_URL", "").rstrip("/")
gitea_url = get_gitea_public_url()
gitea_org = read_env_value("GITEA_ORG", DEFAULT_GITEA_ORG)
repository_url = f"{gitea_url}/{gitea_org}/{app_id}.git" if gitea_url else None
owner_value = clean_optional(owner) or user.get("display_name") or user.get("username") or None
+25 -13
View File
@@ -10,12 +10,19 @@ from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from app.auth import authenticate_user, current_user, find_or_create_oauth_user
from app.config import get_google_redirect_uri, is_google_oauth_button_enabled, read_env_value
from app.config import (
get_gitea_public_url,
get_gitea_redirect_uri,
get_gitea_server_url,
get_google_redirect_uri,
is_gitea_oauth_button_enabled,
is_google_oauth_button_enabled,
read_env_value,
)
from app.db.audit import log_audit_event
from app.templates.layout import page
router = APIRouter()
DEFAULT_GITEA_URL = "http://192.168.66.130:3000"
GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth"
GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token"
GOOGLE_USERINFO_URL = "https://openidconnect.googleapis.com/v1/userinfo"
@@ -54,12 +61,13 @@ def gitea_login(request: Request):
if current_user(request):
return RedirectResponse(url="/portal/operations", status_code=303)
gitea_url = read_env_value("GITEA_URL", DEFAULT_GITEA_URL).rstrip("/")
gitea_url = get_gitea_public_url()
client_id = read_env_value("GITEA_OAUTH_CLIENT_ID", "")
redirect_uri = read_env_value("GITEA_OAUTH_REDIRECT_URI", "")
if not client_id or not redirect_uri:
client_secret = read_env_value("GITEA_OAUTH_CLIENT_SECRET", "")
redirect_uri = get_gitea_redirect_uri()
if not gitea_url or not client_id or not client_secret or not redirect_uri:
_log_gitea_failure("missing_oauth_config")
return _render_login("Přihlášení přes Gitea není správně nastavené.")
return _render_login("Gitea login is not fully configured.")
state = secrets.token_urlsafe(32)
request.session["gitea_oauth_state"] = state
@@ -227,10 +235,10 @@ def logout(request: Request):
def _exchange_gitea_code(code: str) -> str:
gitea_url = read_env_value("GITEA_URL", DEFAULT_GITEA_URL).rstrip("/")
gitea_url = get_gitea_server_url()
client_id = read_env_value("GITEA_OAUTH_CLIENT_ID", "")
client_secret = read_env_value("GITEA_OAUTH_CLIENT_SECRET", "")
redirect_uri = read_env_value("GITEA_OAUTH_REDIRECT_URI", "")
redirect_uri = get_gitea_redirect_uri()
if not client_id or not client_secret or not redirect_uri:
raise RuntimeError("Missing Gitea OAuth configuration")
@@ -260,7 +268,7 @@ def _exchange_gitea_code(code: str) -> str:
def _fetch_gitea_user(access_token: str) -> dict:
gitea_url = read_env_value("GITEA_URL", DEFAULT_GITEA_URL).rstrip("/")
gitea_url = get_gitea_server_url()
request = UrlRequest(
f"{gitea_url}/api/v1/user",
headers={
@@ -350,6 +358,13 @@ def _render_login(error: str | None = None) -> str:
error_html = ""
if error:
error_html = f'<p class="alert alert-danger">{html.escape(error)}</p>'
gitea_login_html = ""
if is_gitea_oauth_button_enabled():
gitea_login_html = """
<p>
<a class="btn" href="/portal/auth/gitea/login">Sign in with Gitea</a>
</p>
"""
google_login_html = ""
if is_google_oauth_button_enabled():
google_login_html = """
@@ -365,10 +380,7 @@ def _render_login(error: str | None = None) -> str:
<h2>CSBot Services Portal</h2>
<p class="muted">Doporučené přihlášení je přes Gitea. Lokální účet slouží pouze jako nouzový administrátorský přístup.</p>
{error_html}
<p>
<a class="btn" href="/portal/auth/gitea/login">Přihlásit přes Gitea</a>
</p>
{gitea_login_html}
{google_login_html}