feat: update application version to 0.8.20 and enhance superadmin role management
Some checks failed
Deploy Development / deploy (push) Successful in 37s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 6s
Test Suite / playwright-tests (push) Failing after 39s

- Bumped application version to 0.8.20 in both backend and frontend files.
- Introduced migration 041 to promote the oldest admin user to superadmin if no superadmin exists.
- Updated registration logic to assign the superadmin role to the first user and those in ADMIN_BOOTSTRAP_EMAILS.
- Enhanced changelog to document the new version and changes made in this release.
This commit is contained in:
Lars 2026-05-05 21:10:19 +02:00
parent 9afcd762d0
commit b661d0edb2
4 changed files with 37 additions and 8 deletions

View File

@ -0,0 +1,20 @@
-- Migration 041: Super-Admin für bestehende Installationen
-- Bisheriger Bootstrap (registration_role) setzte nur 'admin'. Viele Endpunkte
-- (z. B. Verein löschen, Super-Rolle vergeben) verlangen 'superadmin'.
-- Wenn noch kein Super-Admin existiert: den ältesten Nutzer mit role = admin hochstufen.
UPDATE profiles p
SET role = 'superadmin', updated_at = NOW()
FROM (
SELECT id
FROM profiles
WHERE lower(trim(COALESCE(role, ''))) = 'admin'
ORDER BY id ASC
LIMIT 1
) sub
WHERE p.id = sub.id
AND NOT EXISTS (
SELECT 1
FROM profiles
WHERE lower(trim(COALESCE(role, ''))) = 'superadmin'
);

View File

@ -187,9 +187,10 @@ def verification_link(token: str) -> str:
def registration_role(cur, email_lower: str) -> str:
"""
bootstrap: erste Registrierung in leerer DB admin,
bootstrap: erste Registrierung in leerer DB superadmin,
oder E-Mail ADMIN_BOOTSTRAP_EMAILS (kommasepariert, Groß/Klein egal).
superadmin deckt alle Portal-Rechte ab (inkl. löschen / andere Super-Admins).
Um alle Self-Regs als Trainer zu haben: AUTO_ADMIN_FIRST_USER=false und keine ADMIN_BOOTSTRAP_EMAILS.
"""
bootstrap = {
@ -198,7 +199,7 @@ def registration_role(cur, email_lower: str) -> str:
if x.strip()
}
if email_lower in bootstrap:
return "admin"
return "superadmin"
if os.getenv("AUTO_ADMIN_FIRST_USER", "true").strip().lower() not in ("1", "true", "yes"):
return "trainer"
cur.execute("SELECT COUNT(*) AS n FROM profiles")
@ -207,7 +208,7 @@ def registration_role(cur, email_lower: str) -> str:
n = int(row["n"]) if row is not None else 0
except (KeyError, TypeError, ValueError):
n = 0
return "admin" if n == 0 else "trainer"
return "superadmin" if n == 0 else "trainer"
# ── Helper: Send Email ────────────────────────────────────────────────────────
@ -289,7 +290,7 @@ async def register(req: RegisterRequest, request: Request):
verification_token = secrets.token_urlsafe(32)
verification_expires = datetime.now(timezone.utc) + timedelta(hours=24)
# Rolle: erster Nutzer oder ADMIN_BOOTSTRAP_EMAILS → admin
# Rolle: erster Nutzer oder ADMIN_BOOTSTRAP_EMAILS → superadmin
role = registration_role(cur, email)
# Create profile (inactive until verified) — profiles.id ist SERIAL (INT), keine String-IDs einfügen.

View File

@ -1,11 +1,11 @@
# Shinkan Jinkendo Version Information
APP_VERSION = "0.8.19"
APP_VERSION = "0.8.20"
BUILD_DATE = "2026-05-05"
DB_SCHEMA_VERSION = "20260505040"
DB_SCHEMA_VERSION = "20260505041"
MODULE_VERSIONS = {
"auth": "1.1.0", # Registrierung: optional requested_club_id → Beitrittsantrag
"auth": "1.2.0", # Erster/bootstrap Nutzer und ADMIN_BOOTSTRAP_EMAILS → superadmin (nicht mehr admin)
"profiles": "1.3.0", # PUT role/tier (Portal-Admin); GET /profiles; pin_hash aus Liste entfernt
"clubs": "0.4.0", # public-directory, members/directory; Vereins-GUI verwendet Endpoints
"club_memberships": "1.0.0",
@ -26,6 +26,14 @@ MODULE_VERSIONS = {
}
CHANGELOG = [
{
"version": "0.8.20",
"date": "2026-05-05",
"changes": [
"Migration 041: wenn noch kein superadmin existiert, werden ältestes Profil mit role admin zu superadmin hochgestuft",
"Registrierung: erster Nutzer und ADMIN_BOOTSTRAP_EMAILS erhalten superadmin (vorher admin)",
],
},
{
"version": "0.8.19",
"date": "2026-05-05",

View File

@ -1,6 +1,6 @@
// Shinkan Jinkendo Frontend Version
export const APP_VERSION = "0.8.19"
export const APP_VERSION = "0.8.20"
export const BUILD_DATE = "2026-05-05"
export const PAGE_VERSIONS = {