feat: Grafana-Links aus FB_GRAFANA_PUBLIC_URL (Sub-Pfad-tauglich)
This commit is contained in:
@@ -7,6 +7,7 @@ from sqlalchemy import func, select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.auth import COOKIE, session_valid
|
from app.auth import COOKIE, session_valid
|
||||||
|
from app.config import get_settings
|
||||||
from app.db import get_session
|
from app.db import get_session
|
||||||
from app.engine.loans import add_months
|
from app.engine.loans import add_months
|
||||||
from app.engine.recurrence import occurrences
|
from app.engine.recurrence import occurrences
|
||||||
@@ -30,6 +31,22 @@ PAGE_SIZE = 50
|
|||||||
|
|
||||||
templates = Jinja2Templates(directory="app/templates")
|
templates = Jinja2Templates(directory="app/templates")
|
||||||
templates.env.globals["app_version"] = get_version()
|
templates.env.globals["app_version"] = get_version()
|
||||||
|
|
||||||
|
|
||||||
|
def grafana_public_base(request: Request) -> str:
|
||||||
|
"""Öffentliche Grafana-Basis-URL für Browser-Links/iframes. Ist
|
||||||
|
FB_GRAFANA_PUBLIC_URL gesetzt (Reverse-Proxy-Betrieb, z.B.
|
||||||
|
'https://fb.example.de/grafana/'), wird sie ohne abschließenden
|
||||||
|
Slash zurückgegeben; sonst der lokale Fallback http://<host>:8097
|
||||||
|
(Direktbetrieb ohne Proxy). Templates hängen bei Bedarf '/d/...' an."""
|
||||||
|
public = get_settings().grafana_public_url
|
||||||
|
if public:
|
||||||
|
return public.rstrip("/")
|
||||||
|
host = request.url.hostname or "127.0.0.1"
|
||||||
|
return f"http://{host}:8097"
|
||||||
|
|
||||||
|
|
||||||
|
templates.env.globals["grafana_public_base"] = grafana_public_base
|
||||||
templates.env.filters["eur"] = eur
|
templates.env.filters["eur"] = eur
|
||||||
templates.env.filters["de_label"] = de_label
|
templates.env.filters["de_label"] = de_label
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<a href="/szenarien">Szenarien</a>
|
<a href="/szenarien">Szenarien</a>
|
||||||
<a href="/admin">Admin</a>
|
<a href="/admin">Admin</a>
|
||||||
<a href="/hilfe">Hilfe</a>
|
<a href="/hilfe">Hilfe</a>
|
||||||
<a href="http://{{ request.url.hostname or '127.0.0.1' }}:8097" target="_blank" rel="noopener">Grafana</a>
|
<a href="{{ grafana_public_base(request) }}" target="_blank" rel="noopener">Grafana</a>
|
||||||
<form method="post" action="/logout">
|
<form method="post" action="/logout">
|
||||||
<button type="submit">Logout</button>
|
<button type="submit">Logout</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -77,8 +77,8 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>Grafana-Dashboard</h2>
|
<h2>Grafana-Dashboard</h2>
|
||||||
<iframe class="grafana" src="http://{{ request.url.hostname or '127.0.0.1' }}:8097/d/finanzen/finanzen?orgId=1&kiosk"></iframe>
|
<iframe class="grafana" src="{{ grafana_public_base(request) }}/d/finanzen/finanzen?orgId=1&kiosk"></iframe>
|
||||||
<p class="hint">Kein Diagramm sichtbar? Einmal in
|
<p class="hint">Kein Diagramm sichtbar? Einmal in
|
||||||
<a href="http://{{ request.url.hostname or '127.0.0.1' }}:8097" target="_blank">Grafana anmelden</a>
|
<a href="{{ grafana_public_base(request) }}" target="_blank">Grafana anmelden</a>
|
||||||
(gleiches Passwort wie hier).</p>
|
(gleiches Passwort wie hier).</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@
|
|||||||
Tiefpunkt: {{ row.result.low_point_balance|eur }} € am {{ row.result.low_point_date.strftime('%d.%m.%Y') }}<br>
|
Tiefpunkt: {{ row.result.low_point_balance|eur }} € am {{ row.result.low_point_date.strftime('%d.%m.%Y') }}<br>
|
||||||
{% if row.result.below_zero_date %}Unterschreitet 0 € ab {{ row.result.below_zero_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
{% if row.result.below_zero_date %}Unterschreitet 0 € ab {{ row.result.below_zero_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
||||||
{% if row.result.below_threshold_date %}Unterschreitet Warnschwelle ab {{ row.result.below_threshold_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
{% if row.result.below_threshold_date %}Unterschreitet Warnschwelle ab {{ row.result.below_threshold_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
||||||
Kurven in <a href="http://{{ request.url.hostname or '127.0.0.1' }}:8097" target="_blank" rel="noopener">Grafana</a> ansehen.
|
Kurven in <a href="{{ grafana_public_base(request) }}" target="_blank" rel="noopener">Grafana</a> ansehen.
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Noch nicht durchgerechnet.</p>
|
<p>Noch nicht durchgerechnet.</p>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from datetime import date, timedelta
|
from datetime import date, timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from app.config import get_settings
|
||||||
from app.formats import eur
|
from app.formats import eur
|
||||||
from app.models.tables import (Account, Loan, PlannedItem, RecurringItem,
|
from app.models.tables import (Account, Loan, PlannedItem, RecurringItem,
|
||||||
Scenario, ScenarioModifier, ScenarioPlannedItem)
|
Scenario, ScenarioModifier, ScenarioPlannedItem)
|
||||||
@@ -453,3 +454,32 @@ def test_neuer_eintrag_formular_struktur(client, db):
|
|||||||
assert 'class="value-label"' in r # dynamisches Wert-Label
|
assert 'class="value-label"' in r # dynamisches Wert-Label
|
||||||
assert 'Für diese Eintragsart nicht relevant' in r # Tooltip an Umschaltfeldern
|
assert 'Für diese Eintragsart nicht relevant' in r # Tooltip an Umschaltfeldern
|
||||||
assert '<hr' in r # Durchrechnen abgesetzt
|
assert '<hr' in r # Durchrechnen abgesetzt
|
||||||
|
|
||||||
|
|
||||||
|
def test_grafana_links_use_public_url_when_set(client, monkeypatch):
|
||||||
|
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||||
|
monkeypatch.setenv("FB_GRAFANA_PUBLIC_URL", "https://fb.example.de/grafana/")
|
||||||
|
get_settings.cache_clear()
|
||||||
|
try:
|
||||||
|
r = client.get("/")
|
||||||
|
assert r.status_code == 200
|
||||||
|
# iframe + Anmelde-Link nutzen die öffentliche URL, kein :8097 mehr.
|
||||||
|
assert "https://fb.example.de/grafana/d/finanzen/finanzen" in r.text
|
||||||
|
assert ":8097" not in r.text
|
||||||
|
# Nav-Link im base-Template ebenfalls.
|
||||||
|
assert 'href="https://fb.example.de/grafana"' in r.text
|
||||||
|
finally:
|
||||||
|
get_settings.cache_clear()
|
||||||
|
|
||||||
|
|
||||||
|
def test_grafana_links_fallback_to_host_port_when_unset(client, monkeypatch):
|
||||||
|
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||||
|
monkeypatch.delenv("FB_GRAFANA_PUBLIC_URL", raising=False)
|
||||||
|
get_settings.cache_clear()
|
||||||
|
try:
|
||||||
|
r = client.get("/")
|
||||||
|
assert r.status_code == 200
|
||||||
|
assert ":8097/d/finanzen/finanzen" in r.text
|
||||||
|
assert "fb.example.de" not in r.text
|
||||||
|
finally:
|
||||||
|
get_settings.cache_clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user