INSTALL.md dækker hele vejen fra en frisk server til en kørende løsning: forudsætninger, database, .env, migrations, admin-UI-build, en systemd-unit til backend'en, domæne-/reverse proxy-krav (holdt værktøjs-uafhængigt, med en kort CloudPanel-note), DNS, Postal-webhook, rute-opsætning, verifikation og fremtidige opdateringer. scripts/create_admin_user.py lukker en reel mangel: der findes ingen selvbetjenings-registrering, så uden en bruger i databasen kan ingen logge ind på en frisk installation. Scriptet opretter (eller genbruger) en organisation + rute, samt en ny superadmin-bruger med korrekt hashet adgangskode — samme mønster som det eksisterende scripts/import_participants.py. Verificeret i en isoleret test (oprettet bruger kunne logge ind via POST /auth/login), testdata ryddet op igen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
83 lines
3.3 KiB
Python
83 lines
3.3 KiB
Python
"""One-off bootstrap: opretter den første organisation + rute + superadmin-bruger.
|
|
|
|
Der findes ingen selvbetjenings-registrering i systemet — uden en
|
|
bruger i databasen kan ingen logge ind overhovedet. Dette script
|
|
dækker det på en frisk installation.
|
|
|
|
Genbruger en organisation/rute med samme navn, hvis de allerede
|
|
findes (sikkert at køre flere gange, fx for at oprette endnu en
|
|
admin-bruger på en eksisterende organisation). Fejler tydeligt hvis
|
|
en bruger med samme email allerede findes, i stedet for at duplikere.
|
|
|
|
Brug:
|
|
uv run python scripts/create_admin_user.py \
|
|
--org "Fælles Vinindkøb" --route "Fælles Vinindkøb" \
|
|
--email admin@example.com --name "Dit Navn" --password "..."
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from sqlmodel import Session, select
|
|
|
|
from app.core.security import hash_password
|
|
from app.db import engine
|
|
from app.models.organization import Organization
|
|
from app.models.route import Route
|
|
from app.models.user import User
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument("--org", required=True, help="Organisationens navn (genbruges hvis den allerede findes)")
|
|
parser.add_argument("--route", required=True, help="Rutens navn (genbruges hvis den allerede findes)")
|
|
parser.add_argument("--email", required=True, help="Email til den nye admin-bruger")
|
|
parser.add_argument("--name", required=True, help="Navn på den nye admin-bruger")
|
|
parser.add_argument("--password", required=True, help="Adgangskode til den nye admin-bruger")
|
|
args = parser.parse_args()
|
|
|
|
with Session(engine) as session:
|
|
existing_user = session.exec(select(User).where(User.email == args.email)).first()
|
|
if existing_user is not None:
|
|
print(f"Fejl: en bruger med email {args.email!r} findes allerede (id={existing_user.id}).")
|
|
sys.exit(1)
|
|
|
|
organization = session.exec(select(Organization).where(Organization.name == args.org)).first()
|
|
if organization is None:
|
|
organization = Organization(name=args.org)
|
|
session.add(organization)
|
|
session.flush()
|
|
print(f"Oprettede organisation {args.org!r} (id={organization.id}).")
|
|
else:
|
|
print(f"Genbruger eksisterende organisation {args.org!r} (id={organization.id}).")
|
|
|
|
route = session.exec(
|
|
select(Route).where(Route.name == args.route, Route.organization_id == organization.id)
|
|
).first()
|
|
if route is None:
|
|
route = Route(name=args.route, organization_id=organization.id)
|
|
session.add(route)
|
|
session.flush()
|
|
print(f"Oprettede rute {args.route!r} (id={route.id}).")
|
|
else:
|
|
print(f"Genbruger eksisterende rute {args.route!r} (id={route.id}).")
|
|
|
|
user = User(
|
|
email=args.email,
|
|
name=args.name,
|
|
hashed_password=hash_password(args.password),
|
|
is_active=True,
|
|
is_superadmin=True,
|
|
organization_id=organization.id,
|
|
)
|
|
session.add(user)
|
|
session.commit()
|
|
session.refresh(user)
|
|
print(f"Oprettede superadmin-bruger {args.email!r} (id={user.id}).")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|