mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-28 21:17:36 +00:00
Merge pull request #903 from CyberMind-FR/fix/nextcloud-connection-urls
Some checks are pending
License Headers / check (push) Waiting to run
Some checks are pending
License Headers / check (push) Waiting to run
fix(nextcloud): connection URLs use real public domain not localhost:8080
This commit is contained in:
commit
aacbb39fb8
|
|
@ -16,6 +16,24 @@ from secubox_core.config import get_config
|
|||
app = FastAPI(title="SecuBox Nextcloud")
|
||||
config = get_config("nextcloud")
|
||||
|
||||
|
||||
def _public_base_url(ssl_domain: str, domain: str, http_port: int) -> str:
|
||||
"""Return the URL a client/device uses to reach Nextcloud.
|
||||
|
||||
HAProxy terminates TLS 1.3 in front of every SecuBox vhost, so a real
|
||||
public domain is always reachable over https. Precedence: an explicit
|
||||
ssl_domain wins; otherwise the configured public ``domain`` (skipping the
|
||||
``cloud.local`` placeholder); only a bare host with no real domain falls
|
||||
back to the container port. Never emit ``localhost`` when a domain exists —
|
||||
that is unreachable from a phone/desktop client (the bug this fixes).
|
||||
"""
|
||||
if ssl_domain:
|
||||
return f"https://{ssl_domain}"
|
||||
if "." in domain and domain != "cloud.local":
|
||||
return f"https://{domain}"
|
||||
return f"http://localhost:{http_port}"
|
||||
|
||||
|
||||
LXC_NAME = config.get("container_name", "nextcloud")
|
||||
LXC_PATH = Path(config.get("lxc_path", "/data/lxc"))
|
||||
DATA_PATH = Path(config.get("data_path", "/data/volumes/nextcloud"))
|
||||
|
|
@ -158,8 +176,7 @@ async def status():
|
|||
"disk_used": disk_used,
|
||||
# Public URL from the real domain (not localhost) so the dashboard links
|
||||
# somewhere reachable; falls back to the container port for a bare host.
|
||||
"web_url": f"https://{domain}" if "." in domain and domain != "cloud.local"
|
||||
else f"http://localhost:{http_port}",
|
||||
"web_url": _public_base_url(config.get("ssl_domain", ""), domain, http_port),
|
||||
"ssl_enabled": config.get("ssl_enabled", False),
|
||||
"container_name": LXC_NAME,
|
||||
}
|
||||
|
|
@ -443,12 +460,10 @@ def restore_backup(name: str):
|
|||
async def get_connections():
|
||||
"""Get connection URLs (CalDAV, CardDAV, WebDAV)"""
|
||||
http_port = config.get("http_port", 8080)
|
||||
ssl_enabled = config.get("ssl_enabled", False)
|
||||
domain = config.get("domain", "cloud.local")
|
||||
ssl_domain = config.get("ssl_domain", "")
|
||||
|
||||
base_url = f"http://localhost:{http_port}"
|
||||
if ssl_enabled and ssl_domain:
|
||||
base_url = f"https://{ssl_domain}"
|
||||
base_url = _public_base_url(ssl_domain, domain, http_port)
|
||||
|
||||
return {
|
||||
"base_url": base_url,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
secubox-nextcloud (1.5.1-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* Fix connection URLs showing http://localhost:8080 instead of the real
|
||||
public domain. /connections only checked ssl_domain (unset in
|
||||
secubox.conf [nextcloud], which carries `domain`) and fell back to
|
||||
localhost; the panel also hardcoded localhost, ignoring status.web_url.
|
||||
New pure _public_base_url() helper (ssl_domain > domain > localhost),
|
||||
used by both /connections and /status; panel now renders status.web_url.
|
||||
Regression tests added (tests/test_public_base_url.py).
|
||||
|
||||
-- Gerald KERMA <devel@cybermind.fr> Fri, 25 Jul 2026 12:00:00 +0200
|
||||
|
||||
secubox-nextcloud (1.5.0-1~bookworm2) bookworm; urgency=medium
|
||||
|
||||
* Phase 2: Requires=secubox-core.service -> Wants= on this module's unit
|
||||
|
|
|
|||
52
packages/secubox-nextcloud/tests/test_public_base_url.py
Normal file
52
packages/secubox-nextcloud/tests/test_public_base_url.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
||||
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
|
||||
# Source-Disclosed License — All rights reserved except as expressly granted.
|
||||
# See LICENCE-CMSD-1.0.md for terms.
|
||||
|
||||
"""
|
||||
SecuBox-Deb :: Nextcloud — _public_base_url unit tests
|
||||
|
||||
Regression guard: /connections must never hand a client localhost when a
|
||||
real public domain is configured (clients reach Nextcloud through HAProxy
|
||||
TLS 1.3). The helper is pure so it is tested without importing the FastAPI
|
||||
app (which starts a cache thread + LXC probes at import time).
|
||||
"""
|
||||
|
||||
import ast
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
MAIN = Path(__file__).resolve().parent.parent / "api" / "main.py"
|
||||
|
||||
|
||||
def _load_helper():
|
||||
"""Extract and exec only the _public_base_url function from api/main.py."""
|
||||
tree = ast.parse(MAIN.read_text())
|
||||
for node in tree.body:
|
||||
if isinstance(node, ast.FunctionDef) and node.name == "_public_base_url":
|
||||
src = textwrap.dedent(ast.get_source_segment(MAIN.read_text(), node))
|
||||
ns: dict = {}
|
||||
exec(src, ns)
|
||||
return ns["_public_base_url"]
|
||||
raise AssertionError("_public_base_url not found in api/main.py")
|
||||
|
||||
|
||||
_public_base_url = _load_helper()
|
||||
|
||||
|
||||
def test_configured_domain_yields_https_not_localhost():
|
||||
# The bug: secubox.conf [nextcloud] has domain but no ssl_domain.
|
||||
assert _public_base_url("", "nc.gk2.secubox.in", 8080) == "https://nc.gk2.secubox.in"
|
||||
|
||||
|
||||
def test_ssl_domain_takes_precedence():
|
||||
assert _public_base_url("secure.example.com", "nc.gk2.secubox.in", 8080) == \
|
||||
"https://secure.example.com"
|
||||
|
||||
|
||||
def test_placeholder_domain_falls_back_to_localhost():
|
||||
assert _public_base_url("", "cloud.local", 8080) == "http://localhost:8080"
|
||||
|
||||
|
||||
def test_bare_host_without_dot_falls_back_to_localhost():
|
||||
assert _public_base_url("", "nextcloud", 9000) == "http://localhost:9000"
|
||||
|
|
@ -237,9 +237,11 @@
|
|||
document.getElementById('data-size').textContent = status.disk_used || '-';
|
||||
document.getElementById('version').textContent = status.version || '-';
|
||||
|
||||
const port = status.http_port || 8080;
|
||||
document.getElementById('web-url').textContent = `http://localhost:${port}`;
|
||||
document.getElementById('web-url').href = `http://localhost:${port}`;
|
||||
// Use the public URL the API resolves (real domain behind HAProxy
|
||||
// TLS), not a hardcoded localhost the client can't reach.
|
||||
const webUrl = status.web_url || `http://localhost:${status.http_port || 8080}`;
|
||||
document.getElementById('web-url').textContent = webUrl;
|
||||
document.getElementById('web-url').href = webUrl;
|
||||
}
|
||||
|
||||
async function loadStorage() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user