diff --git a/.dockerignore b/.dockerignore index 0b51345cbdb..625ac9f24a2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -11,6 +11,7 @@ !Cargo.lock !Cargo.toml !build_rust.py +!modules rust/target synapse/*.so diff --git a/infra/k8s/admin_token.txt b/infra/k8s/admin_token.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/infra/k8s/fluffy-httproute.yaml b/infra/k8s/fluffy-httproute.yaml new file mode 100644 index 00000000000..1ca5bda3650 --- /dev/null +++ b/infra/k8s/fluffy-httproute.yaml @@ -0,0 +1,15 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: fluffy-route +spec: + parentRefs: + - name: gateway + sectionName: https-fluffy + hostnames: + - "fluffy.nexojornal.com.br" + rules: + - backendRefs: + - name: fluffy + namespace: default + port: 80 diff --git a/infra/k8s/fluffy-service.yaml b/infra/k8s/fluffy-service.yaml new file mode 100644 index 00000000000..a1ff06b9eae --- /dev/null +++ b/infra/k8s/fluffy-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: fluffy +spec: + type: NodePort + selector: + app: fluffy + ports: + - port: 80 + targetPort: 80 + nodePort: 30007 diff --git a/infra/k8s/fluffy.yaml b/infra/k8s/fluffy.yaml new file mode 100644 index 00000000000..0ddd51a3497 --- /dev/null +++ b/infra/k8s/fluffy.yaml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: fluffy +spec: + replicas: 1 + selector: + matchLabels: + app: fluffy + template: + metadata: + labels: + app: fluffy + spec: + containers: + - name: fluffy + image: docker.buzzlabs.com.br/fluffy-grupos + imagePullPolicy: Always + ports: + - containerPort: 80 + imagePullSecrets: + - name: global-regcred diff --git a/infra/k8s/migration-job.yaml b/infra/k8s/migration-job.yaml new file mode 100644 index 00000000000..48ebd17d53b --- /dev/null +++ b/infra/k8s/migration-job.yaml @@ -0,0 +1,55 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: synapse-migrations +spec: + template: + spec: + restartPolicy: Never + containers: + - name: migration + image: postgres:15 + command: ["/bin/sh", "-c"] + args: + - | + echo "Esperando banco subir..." + until pg_isready -h postgres -U synapse; do + sleep 2 + done + + echo "Rodando migrations..." + + PGPASSWORD=senhaDoBD psql -h postgres -U userDoBD -d synapse < /dev/null; do + sleep 2 + done + + echo "Fazendo login..." + + RESPONSE=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/v3/login" \ + -H "Content-Type: application/json" \ + -d "{ + \"type\": \"m.login.password\", + \"identifier\": { + \"type\": \"m.id.user\", + \"user\": \"$EMAIL\" + }, + \"password\": \"$PASSWORD\" + }") + + ACCESS_TOKEN=$(echo "$RESPONSE" | jq -r '.access_token') + USER_ID=$(echo "$RESPONSE" | jq -r '.user_id') + + if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then + echo "Erro ao logar" + exit 1 + fi + + echo "Tornando admin..." + + PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -c \ + "UPDATE users SET admin = 1 WHERE name = '$USER_ID';" + + echo "$ACCESS_TOKEN" > "$TOKEN_FILE" + + echo "Finalizado" + echo "Mantendo container vivo..." + tail -f /dev/null diff --git a/infra/k8s/synapse-service.yaml b/infra/k8s/synapse-service.yaml new file mode 100644 index 00000000000..bb2a7ca24d4 --- /dev/null +++ b/infra/k8s/synapse-service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: synapse +spec: + type: NodePort + selector: + app: synapse + ports: + - port: 3000 + targetPort: 3000 + nodePort: 30008 diff --git a/infra/k8s/synapse.yaml b/infra/k8s/synapse.yaml new file mode 100644 index 00000000000..db8a5f5c46c --- /dev/null +++ b/infra/k8s/synapse.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: synapse +spec: + replicas: 1 + selector: + matchLabels: + app: synapse + template: + metadata: + labels: + app: synapse + spec: + containers: + + # 🧠 SYNAPSE + - name: synapse + image: docker.buzzlabs.com.br/synapse + imagePullPolicy: Always + ports: + - containerPort: 3000 + volumeMounts: + # 📁 volume persistente + - name: data + mountPath: /data + + # 📜 arquivos do configmap (injeção dentro do /data) + - name: config + mountPath: /data/homeserver.yaml + subPath: homeserver.yaml + + - name: config + mountPath: /data/localhost.log.config + subPath: localhost.log.config + + - name: config + mountPath: /data/localhost.signing.key + subPath: localhost.signing.key + + # 🔥 INIT ADMIN (SIDECAR) + - name: init-admin + image: docker.buzzlabs.com.br/synapse + imagePullPolicy: Always + + command: ["/bin/sh", "/scripts/init-admin.sh"] + volumeMounts: + - name: scripts + mountPath: /scripts + + - name: data + mountPath: /data + + imagePullSecrets: + - name: global-regcred + volumes: + # 💾 persistência + - name: data + persistentVolumeClaim: + claimName: synapse-pvc + + # 📜 script + - name: scripts + configMap: + name: synapse-scripts + defaultMode: 0755 + + # ⚙️ config do synapse + - name: config + configMap: + name: synapse-config diff --git a/infra/synapse-docker/Dockerfile b/infra/synapse-docker/Dockerfile new file mode 100644 index 00000000000..005b7a56b97 --- /dev/null +++ b/infra/synapse-docker/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3.11-slim + +WORKDIR /app + +RUN apt-get update && apt-get install -y \ + build-essential libffi-dev libssl-dev libjpeg-dev zlib1g-dev \ + jq curl libpq-dev gcc postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" + +RUN pip install --upgrade pip +RUN pip install "prometheus_client<0.20" +RUN pip install "matrix-synapse[all]" +RUN pip install --upgrade "pyOpenSSL>=24.2.1" "cryptography>=43,<48" + +# código do synapse (com suas modificações locais) +COPY synapse /app/synapse +COPY rust /app/rust +COPY modules /app/modules +COPY pyproject.toml Cargo.toml Cargo.lock build_rust.py README.rst /app/ + +RUN pip install -e /app + +ENV PYTHONPATH=/app + +EXPOSE 3000 +CMD ["python", "-m", "synapse.app.homeserver", "--config-path", "/data/homeserver.yaml"] diff --git a/infra/synapse-docker/data/admin_token.txt b/infra/synapse-docker/data/admin_token.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/infra/synapse-docker/data/homeserver.log b/infra/synapse-docker/data/homeserver.log new file mode 100644 index 00000000000..e69de29bb2d diff --git a/infra/synapse-docker/data/homeserver.yaml b/infra/synapse-docker/data/homeserver.yaml new file mode 100644 index 00000000000..7216261af71 --- /dev/null +++ b/infra/synapse-docker/data/homeserver.yaml @@ -0,0 +1,81 @@ +# Configuration file for Synapse. +# +# This is a YAML file: see [1] for a quick introduction. Note in particular +# that *indentation is important*: all the elements of a list or dictionary +# should have the same indentation. +# +# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html +# +# For more information on how to configure Synapse, including a complete accounting of +# each option, go to docs/usage/configuration/config_documentation.md or +# https://element-hq.github.io/synapse/latest/usage/configuration/config_documentation.html +server_name: "localhost" +pid_file: /data/homeserver.pid +listeners: + - port: 3000 + tls: false + type: http + x_forwarded: true + bind_addresses: ["0.0.0.0"] + resources: + - names: [client, federation] + compress: false +# database: +# name: sqlite3 +# args: +# database: /home/livia/BuzzLabs/synapse/homeserver.db +database: + name: psycopg2 + args: + user: userDoBD + password: senhaDoBD + database: synapse + host: postgres + port: 5432 + cp_min: 5 + cp_max: 10 + +log_config: "/data/localhost.log.config" +loggers: + modules.invite: + level: INFO + modules.discover: + level: INFO +media_store_path: /data/media_store +# registration_shared_secret: "ze9EepjAcX_12d~wp2Pe:@;Z2_pTe=JREzXL992Q~@uEBq=1Me" +report_stats: false +macaroon_secret_key: "..." +form_secret: "..." +signing_key_path: "/data/localhost.signing.key" +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true + +registration_requires_token: false +enable_registration: false +enable_3pid_lookup: false + +enable_admin_api: true +admin_api: + shared_secret: "..." +registration_shared_secret: "..." +# enable_registration_without_verification: true +password_config: + enabled: true + localdb_enabled: false +password_providers: + - module: modules.rest_auth_provider.rest_auth_provider.RestAuthProvider + config: + api_base: "https://paywall.nexojornal.com.br" + timeout: 5 +admins: + - "@admin:localhost" # IMPORTANTE!!! PRECISA ADAPTAR CASO A CASO + +modules: + - module: modules.room_service.module.RoomServiceModule + config: + admin_user_id: "@admin:localhost" # IMPORTANTE!!! PRECISA ADAPTAR CASO A CASO + admin_token_file: "/data/admin_token.txt" + homeserver: "http://synapse:3000" + - module: modules.bundle_service.module.BundleServiceModule +# vim:ft=yaml diff --git a/infra/synapse-docker/data/localhost.log.config b/infra/synapse-docker/data/localhost.log.config new file mode 100644 index 00000000000..ca411cf0611 --- /dev/null +++ b/infra/synapse-docker/data/localhost.log.config @@ -0,0 +1,20 @@ +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + level: INFO + +root: + level: INFO + handlers: [console] + +disable_existing_loggers: false diff --git a/infra/synapse-docker/data/localhost.signing.key b/infra/synapse-docker/data/localhost.signing.key new file mode 100644 index 00000000000..82674fec41a --- /dev/null +++ b/infra/synapse-docker/data/localhost.signing.key @@ -0,0 +1 @@ +ed25519 a_6f43 qD+jwIjY9XtkerdSe57YuD1kx+AvCUVVOI7hMtCVUX0 diff --git a/infra/synapse-docker/docker-compose.yml b/infra/synapse-docker/docker-compose.yml new file mode 100644 index 00000000000..b31bae86b28 --- /dev/null +++ b/infra/synapse-docker/docker-compose.yml @@ -0,0 +1,36 @@ +services: + db: + image: postgres:15 + restart: always + environment: + POSTGRES_DB: synapse + POSTGRES_USER: userDoDB + POSTGRES_PASSWORD: senhaDoDB + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C" + volumes: + - db_data:/var/lib/postgresql/data + - ./migrations:/docker-entrypoint-initdb.d + synapse: + build: + context: .. + dockerfile: synapse-docker/Dockerfile + container_name: synapse + depends_on: + - db + restart: unless-stopped + + volumes: + - ./data:/data + - ./scripts:/scripts + ports: + - "3000:3000" + command: > + sh -c " + python -m synapse.app.homeserver --config-path /data/homeserver.yaml & + echo 'Esperando Synapse iniciar...' + sleep 10 + /scripts/init-admin.sh + wait + " +volumes: + db_data: diff --git a/infra/synapse-docker/migrations/001_init.sql b/infra/synapse-docker/migrations/001_init.sql new file mode 100644 index 00000000000..f1ad13b846e --- /dev/null +++ b/infra/synapse-docker/migrations/001_init.sql @@ -0,0 +1,30 @@ +-- 001_init.sql + +CREATE TABLE public.bundles ( + bundle_id uuid PRIMARY KEY, + bundle_name text NOT NULL, + price int4 NOT NULL, + created_at timestamp DEFAULT now(), + updated_at timestamp DEFAULT now(), + created_by text NOT NULL, + status text DEFAULT 'draft' NOT NULL +); + +CREATE TABLE public.bundle_rooms ( + bundle_id uuid NOT NULL, + room_id text NOT NULL, + PRIMARY KEY (bundle_id, room_id), + FOREIGN KEY (bundle_id) + REFERENCES public.bundles(bundle_id) + ON DELETE CASCADE +); + +CREATE TABLE public.room_business ( + room_id text PRIMARY KEY, + room_kind text NOT NULL, + access_type text NOT NULL, + visible bool NOT NULL, + price int4 DEFAULT 0, + keyword text UNIQUE, + created_at int8 NOT NULL +); diff --git a/infra/synapse-docker/scripts/init-admin.sh b/infra/synapse-docker/scripts/init-admin.sh new file mode 100644 index 00000000000..f1537e0d852 --- /dev/null +++ b/infra/synapse-docker/scripts/init-admin.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -e + +TOKEN_FILE="/data/admin_token.txt" +HOMESERVER_URL="http://synapse:3000" + +DB_HOST="postgres" +DB_USER="userDoBD" +DB_NAME="synapse" +DB_PASSWORD="senhaDoBD" + +EMAIL="matheus.silva@buzzlabs.com.br" +PASSWORD='Xablau3521@!' + +echo "Removendo token antigo (se existir)..." +rm -f "$TOKEN_FILE" + +echo "Esperando Synapse subir..." +until curl -s "$HOMESERVER_URL/_matrix/client/versions" > /dev/null; do + sleep 2 +done + +echo "Fazendo login via RestAuthProvider..." + +RESPONSE=$(curl -s -X POST "$HOMESERVER_URL/_matrix/client/v3/login" \ + -H "Content-Type: application/json" \ + -d "{ + \"type\": \"m.login.password\", + \"identifier\": { + \"type\": \"m.id.user\", + \"user\": \"$EMAIL\" + }, + \"password\": \"$PASSWORD\" + }") + +echo "Resposta: $RESPONSE" + +ACCESS_TOKEN=$(echo "$RESPONSE" | jq -r '.access_token') +USER_ID=$(echo "$RESPONSE" | jq -r '.user_id') + +if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then + echo "Erro ao logar via paywall" + exit 1 +fi + +echo "Login OK: $USER_ID" + +echo "Tornando usuário admin global..." + +PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -c \ +"UPDATE users SET admin = 1 WHERE name = '$USER_ID';" + +echo "Salvando token..." + +echo "$ACCESS_TOKEN" > "$TOKEN_FILE" +chmod 644 "$TOKEN_FILE" + +echo "Setup completo: usuário é admin + token salvo" +echo "Setup completo — mantendo container vivo..." + +tail -f /dev/null diff --git a/modules/room_service/module.py b/modules/room_service/module.py index a509096f3d8..18269aebde4 100644 --- a/modules/room_service/module.py +++ b/modules/room_service/module.py @@ -1,5 +1,7 @@ # module.py import logging +import time +import os from synapse.api.errors import SynapseError from synapse.module_api import ModuleApi @@ -21,7 +23,17 @@ class RoomServiceModule: def __init__(self, config, api: ModuleApi): self.hs = api._hs admin_user_id = config["admin_user_id"] - admin_token = config["admin_token"] + admin_token_file = config["admin_token_file"] + + for _ in range(30): # tenta por ~30s + if os.path.exists(admin_token_file): + with open(admin_token_file, "r") as f: + admin_token = f.read().strip() + break + time.sleep(1) + else: + admin_token = None + homeserver = config["homeserver"] service = RoomService( diff --git a/modules/room_service/service.py b/modules/room_service/service.py index 2badbb1e4f9..8816f4db864 100644 --- a/modules/room_service/service.py +++ b/modules/room_service/service.py @@ -781,6 +781,14 @@ async def _admin_join(self, room_id: str, user_id: str): body_str = body.decode(errors="ignore") + logger.info( + "admin_join: room=%s user=%s code=%s body=%s", + room_id, + user_id, + response.code, + body_str, + ) + if response.code == 200: return "joined"