#!/usr/bin/env python3 """fg_setup.py — on 9202 (controller 0.287.0, drill catalog): two family members through the dashboard's Család card (POST /family/members/add — the card's own call), then MeTube and Grimmory installed through the product, and Grimmory's first admin made by the household through the SETUP gate (it is setup-gated AND family-gated). Secrets → 0600 scratch.""" import json, os, re, subprocess, sys, time from fg import * SC = w.SC log = open(f"{w.EV}/setup.txt", "a", buffering=1) def say(*a): w.say(*a); log.write(" ".join(map(str, a)) + "\n") w.login() say(f"##### family gate live setup on 9202 — controller {w.guest('docker inspect felhom-controller --format {{.Config.Image}}').strip()} | {time.strftime('%FT%TZ', time.gmtime())}") sess = dash_session(); csrf = open(f"{SC}/csrf{os.getpid()}.txt").read().strip() fam = {} for name in ("anna", "bela"): r = subprocess.run(["curl", "-sk", "-H", f"Host: {CTL}", "-H", f"Cookie: {sess}", "-H", f"X-CSRF-Token: {csrf}", "-X", "POST", "--data", f"name={name}", f"{w.BASE}/family/members/add"], capture_output=True, text=True) d = json.loads(r.stdout) fam[name] = d["data"]["password"] say(f"Család card: add {name} -> ok={d['ok']} members={d['data']['members']} password returned ONCE (len {len(fam[name])}, not printed)") r = subprocess.run(["curl", "-sk", "-H", f"Host: {CTL}", "-H", f"Cookie: {sess}", f"{w.BASE}/settings/security"], capture_output=True, text=True) say("the security page carries the card:", 'id="family-card"' in r.stdout, "| and no member password:", not any(p in r.stdout for p in fam.values())) json.dump(fam, open(f"{SC}/fam.json", "w")); os.chmod(f"{SC}/fam.json", 0o600) for app, sub in (("metube", "video"), ("grimmory", "library")): say(f"deploy {app} ->", w.deploy(app, sub)) say(f" {app} family-gate file:", w.guest(f"ls /opt/docker/stacks/traefik/dynamic/ | grep -E 'family-gate-{app}|setup-gate-{app}' | tr '\\n' ' '")) w.wait_app("library", "/api/v1/healthcheck", want=("200",), tries=90) pw = "Gm-" + __import__("secrets").token_hex(10) c, h, b = lan(f"library.{DOM}", "/api/v1/setup", method="POST", cookie=w.gate_cookie("library"), hdrs=("Content-Type: application/json",), data=json.dumps({"username": "admin", "password": pw, "email": "admin@felhom.invalid", "name": "Felhom"})) say("grimmory: the household makes the first admin THROUGH THE SETUP GATE ->", c) json.dump({"admin_pw": pw}, open(f"{SC}/gm.json", "w")); os.chmod(f"{SC}/gm.json", 0o600) for i in range(40): files = w.guest("ls /opt/docker/stacks/traefik/dynamic/ | grep -E 'grimmory' | tr '\\n' ' '") if "setup-gate-grimmory" not in files: break time.sleep(5) say(f"grimmory: setup gate opened by its probe after ~{5*i} s; files now: {files}")