diff --git a/services/communication/guest-helper.yaml b/services/communication/guest-helper.yaml deleted file mode 100644 index a390b75..0000000 --- a/services/communication/guest-helper.yaml +++ /dev/null @@ -1,239 +0,0 @@ -# services/communication/guest-helper.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: guest-helper -data: - app.py: | - import os, uuid, string, random - import requests - from fastapi import FastAPI, HTTPException, Header - from pydantic import BaseModel - import uvicorn - - BASE = os.environ.get("SYNAPSE_BASE", "http://othrys-synapse-matrix-synapse:8008") - SEED_USER = os.environ["SEEDER_USER"] - SEED_PASS = os.environ["SEEDER_PASS"] - SERVER_NAME = os.environ.get("SERVER_NAME", "live.bstein.dev") - ELEMENT_URL = os.environ.get("ELEMENT_URL", "https://live.bstein.dev") - ADMIN_TOKEN = os.environ.get("ADMIN_TOKEN") - - app = FastAPI(title="Guest Helper", version="0.1.0") - - - class InviteRequest(BaseModel): - room: str # room_id or alias - display_name: str | None = None - - - def login(user, password): - res = requests.post( - f"{BASE}/_matrix/client/v3/login", - json={ - "type": "m.login.password", - "identifier": {"type": "m.id.user", "user": user}, - "password": password, - }, - timeout=10, - ) - if res.status_code != 200: - raise HTTPException(status_code=500, detail="seeder login failed") - return res.json()["access_token"] - - - def resolve_room(token, room): - headers = {"Authorization": f"Bearer {token}"} - if room.startswith("!"): - return room - if room.startswith("#"): - alias_enc = requests.utils.requote_uri(room) - r = requests.get(f"{BASE}/_matrix/client/v3/directory/room/{alias_enc}", headers=headers, timeout=10) - if r.status_code != 200: - raise HTTPException(status_code=400, detail="room alias not found") - return r.json()["room_id"] - raise HTTPException(status_code=400, detail="room must be room_id or alias") - - - def random_pwd(): - alphabet = string.ascii_letters + string.digits - return "".join(random.choice(alphabet) for _ in range(20)) - - - def create_guest(token, display): - uid = f"@guest-{uuid.uuid4().hex[:8]}:{SERVER_NAME}" - pwd = random_pwd() - headers = {"Authorization": f"Bearer {token}"} - body = { - "password": pwd, - "displayname": display or "Guest", - "admin": False, - "deactivated": False, - } - r = requests.put( - f"{BASE}/_synapse/admin/v2/users/{requests.utils.requote_uri(uid)}", - headers=headers, - json=body, - timeout=10, - ) - if r.status_code not in (200, 201): - raise HTTPException(status_code=500, detail=f"user create failed: {r.text}") - return uid, pwd - - - def join_room_as(token, room_id, user_id): - headers = {"Authorization": f"Bearer {token}"} - r = requests.post( - f"{BASE}/_synapse/admin/v1/join/{requests.utils.requote_uri(room_id)}", - headers=headers, - json={"user_id": user_id}, - timeout=10, - ) - if r.status_code not in (200, 202): - raise HTTPException(status_code=500, detail=f"join failed: {r.text}") - - - def login_token(user, password): - r = requests.post( - f"{BASE}/_matrix/client/v3/login", - json={ - "type": "m.login.password", - "identifier": {"type": "m.id.user", "user": user}, - "password": password, - }, - timeout=10, - ) - if r.status_code != 200: - raise HTTPException(status_code=500, detail="guest login failed") - data = r.json() - return data["access_token"] - - - @app.post("/invite") - def invite(req: InviteRequest, x_admin_token: str | None = Header(default=None)): - if ADMIN_TOKEN and x_admin_token != ADMIN_TOKEN: - raise HTTPException(status_code=401, detail="unauthorized") - admin_token = login(SEED_USER, SEED_PASS) - room_id = resolve_room(admin_token, req.room) - guest_id, pwd = create_guest(admin_token, req.display_name) - join_room_as(admin_token, room_id, guest_id) - guest_token = login_token(guest_id, pwd) - join_url = f"{ELEMENT_URL}/#/room/{room_id}?access_token={guest_token}&user_id={guest_id}" - return { - "user_id": guest_id, - "password": pwd, - "room_id": room_id, - "access_token": guest_token, - "join_url": join_url, - } - - - def main(): - uvicorn.run(app, host="0.0.0.0", port=8081) - - - if __name__ == "__main__": - main() ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: guest-helper - labels: - app: guest-helper -spec: - replicas: 1 - selector: - matchLabels: - app: guest-helper - template: - metadata: - labels: - app: guest-helper - spec: - nodeSelector: - hardware: rpi5 - containers: - - name: api - image: python:3.11-slim - command: - - /bin/sh - - -c - - | - pip install --no-cache-dir fastapi uvicorn requests && \ - python /app/app.py - env: - - name: SYNAPSE_BASE - value: http://othrys-synapse-matrix-synapse:8008 - - name: SEEDER_USER - value: othrys-seeder - - name: SEEDER_PASS - valueFrom: - secretKeyRef: - name: atlasbot-credentials - key: seeder-password - - name: SERVER_NAME - value: live.bstein.dev - - name: ELEMENT_URL - value: https://live.bstein.dev - - name: ADMIN_TOKEN - valueFrom: - secretKeyRef: - name: guest-helper-admin - key: ADMIN_TOKEN - optional: true - ports: - - name: http - containerPort: 8081 - resources: - requests: - cpu: 50m - memory: 128Mi - limits: - cpu: 300m - memory: 256Mi - volumeMounts: - - name: code - mountPath: /app/app.py - subPath: app.py - volumes: - - name: code - configMap: - name: guest-helper ---- -apiVersion: v1 -kind: Service -metadata: - name: guest-helper -spec: - selector: - app: guest-helper - ports: - - name: http - port: 8081 - targetPort: 8081 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: guest-helper - annotations: - kubernetes.io/ingress.class: traefik - traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.tls: "true" - cert-manager.io/cluster-issuer: letsencrypt -spec: - tls: - - hosts: - - live.bstein.dev - secretName: live-othrys-tls - rules: - - host: live.bstein.dev - http: - paths: - - path: /guest-helper - pathType: Prefix - backend: - service: - name: guest-helper - port: - number: 8081 diff --git a/services/communication/kustomization.yaml b/services/communication/kustomization.yaml index 3c5f115..9cd7f38 100644 --- a/services/communication/kustomization.yaml +++ b/services/communication/kustomization.yaml @@ -22,5 +22,3 @@ resources: - atlasbot-deployment.yaml - seed-othrys-room.yaml - wellknown.yaml - - synapse-federation-service.yaml - - guest-helper.yaml diff --git a/services/communication/synapse-federation-service.yaml b/services/communication/synapse-federation-service.yaml deleted file mode 100644 index 5417c9e..0000000 --- a/services/communication/synapse-federation-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# services/communication/synapse-federation-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: synapse-federation -spec: - clusterIP: 10.43.60.60 - selector: - app.kubernetes.io/name: matrix-synapse - app.kubernetes.io/instance: othrys-synapse - ports: - - name: federation - port: 8448 - targetPort: 8008 - protocol: TCP