feat(podcast): også gruppen Gramps må lytte
CD / deploy (push) Successful in 16s
CI / check (push) Successful in 22s

Slægten uden for den nære familie inviteres i gruppen Gramps, der kun giver
Gramps, podcasten og portalen. PODCAST_GROUP er nu kommasepareret
(standard "Familie,Gramps"). Podcast-kortet på forsiden vises også, selvom
brugeren ingen andre apps har.

Invitationssiden forklarer de kendte grupper med en linje, så det er tydeligt
hvad Familie, Gramps og Crawlkit-team giver.

Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
This commit is contained in:
agw
2026-10-04 22:29:19 +02:00
parent 94e5a0ca01
commit 70bc700a11
4 changed files with 25 additions and 19 deletions
+3 -2
View File
@@ -13,8 +13,9 @@ API_TOKEN = os.environ["AUTHENTIK_API_TOKEN"]
SECRET_KEY = os.environ["SESSION_SECRET"]
REDIRECT_URI = os.environ.get("OIDC_REDIRECT_URI", "https://weircon.dk/auth/callback")
ADMIN_GROUP = os.environ.get("ADMIN_GROUP", "authentik Admins")
# Hvem der må høre familiens podcasts (/podcast); admins kan altid.
PODCAST_GROUP = os.environ.get("PODCAST_GROUP", "Familie")
# Hvem der må høre familiens podcasts (/podcast); admins kan altid. Kommasepareret:
# Familie er den nære familie, Gramps er slægten der kun har Gramps + podcast + portal.
PODCAST_GROUPS = {g.strip() for g in os.environ.get("PODCAST_GROUP", "Familie,Gramps").split(",") if g.strip()}
MATOMO_BASE = os.environ.get("MATOMO_BASE", "https://matomo.weircon.dk").rstrip("/")
MATOMO_TOKEN = os.environ.get("MATOMO_TOKEN", "")
+3 -3
View File
@@ -71,14 +71,14 @@ def require_admin(request: Request):
def require_familie(request: Request):
"""Logget ind og i PODCAST_GROUP (eller admin). Uden login: login og tilbage hertil."""
"""Logget ind og i en af PODCAST_GROUPS (eller admin). Uden login: login og tilbage hertil."""
user = current_user(request)
if not user and request.method == "GET":
nxt = request.url.path + (f"?{request.url.query}" if request.url.query else "")
raise HTTPException(303, headers={"Location": "/auth/login?next=" + urllib.parse.quote(nxt, safe="")})
if not user:
raise HTTPException(401, "Log ind først")
if not (is_admin(user) or config.PODCAST_GROUP in (user.get("groups") or [])):
if not (is_admin(user) or config.PODCAST_GROUPS & set(user.get("groups") or [])):
raise HTTPException(403, "Kun for familien")
return user
@@ -153,7 +153,7 @@ async def dashboard_content(request: Request):
def _podcast_kort(user) -> list[dict]:
"""Kort til forsiden: én pr. podcast med udgivne episoder (admins ser også kladder)."""
if not (is_admin(user) or config.PODCAST_GROUP in (user.get("groups") or [])):
if not (is_admin(user) or config.PODCAST_GROUPS & set(user.get("groups") or [])):
return []
ud = []
for name in podcast.shows():
+6 -1
View File
@@ -24,13 +24,18 @@
<p style="margin:.9rem 0 .4rem"><strong>Grupper de skal med i</strong></p>
<div class="wt-grid wt-grid--tight">
{% set gruppe_hjaelp = {
"Familie": "den nære familie: Sønderlund, Mealie, Emby, Gramps (redigér), podcast m.m.",
"Gramps": "kun Gramps (læse), familiens podcast og portalen",
"Crawlkit-team": "kun crawlkit",
} %}
{% for g in grupper %}
<label class="wt-select-card">
<input type="checkbox" name="grupper" value="{{ g.pk }}" {% if g.name == "Familie" %}checked{% endif %}>
<span class="wt-select-card-ini">{{ g.name[0]|upper }}</span>
<span class="wt-select-card-body">
<span class="wt-select-card-name">{{ g.name }}</span>
<span class="wt-select-card-sub">{{ g.members }} medlemmer{% if g.name == "authentik Admins" %} · ⚠️ fuld admin-adgang{% endif %}</span>
<span class="wt-select-card-sub">{{ g.members }} medlemmer{% if g.name == "authentik Admins" %} · ⚠️ fuld admin-adgang{% elif g.name in gruppe_hjaelp %} · {{ gruppe_hjaelp[g.name] }}{% endif %}</span>
</span>
<span class="wt-select-card-chk">✓</span>
</label>
+13 -13
View File
@@ -12,19 +12,6 @@
</div>
{% endmacro %}
{% if error %}<div class="err">{{ error }}</div>{% endif %}
{% if groups %}
<div class="toolbar">
<div class="filter"><span class="mag">⌕</span>
<input id="appfilter" type="search" placeholder="Filtrér…" autocomplete="off" aria-label="Filtrér tjenester"></div>
<div class="viewtoggle" role="group" aria-label="Visning">
<button type="button" data-view="grouped" class="{{ 'on' if view != 'alpha' }}">Grupperet</button>
<button type="button" data-view="alpha" class="{{ 'on' if view == 'alpha' }}">Alfabetisk</button>
</div>
</div>
<section id="favsec" class="appgroup"{% if not fav_apps %} style="display:none"{% endif %}>
<h2>★ Favoritter</h2>
<div class="grid" id="favgrid">{% for a in fav_apps %}{{ card(a) }}{% endfor %}</div>
</section>
{% if podcasts %}
<section class="appgroup" id="podsec">
<h2>🎙️ Familiens podcast</h2>
@@ -40,6 +27,19 @@
</div>
</section>
{% endif %}
{% if groups %}
<div class="toolbar">
<div class="filter"><span class="mag">⌕</span>
<input id="appfilter" type="search" placeholder="Filtrér…" autocomplete="off" aria-label="Filtrér tjenester"></div>
<div class="viewtoggle" role="group" aria-label="Visning">
<button type="button" data-view="grouped" class="{{ 'on' if view != 'alpha' }}">Grupperet</button>
<button type="button" data-view="alpha" class="{{ 'on' if view == 'alpha' }}">Alfabetisk</button>
</div>
</div>
<section id="favsec" class="appgroup"{% if not fav_apps %} style="display:none"{% endif %}>
<h2>★ Favoritter</h2>
<div class="grid" id="favgrid">{% for a in fav_apps %}{{ card(a) }}{% endfor %}</div>
</section>
{% if mc_servers %}
<section class="appgroup" id="mcsec">
<h2>⛏️ Minecraft-servere</h2>