#!/usr/bin/env bash # mas_client_register — Registra/sincroniza clientes OAuth en Matrix Authentication Service (MAS) # via mas-cli config sync ejecutado en container Docker remoto a traves de SSH. set -euo pipefail mas_client_register() { local ssh_host="" local container="" local config_file="" local dry_run=false # Parse args while [[ $# -gt 0 ]]; do case "$1" in --ssh-host) ssh_host="$2" shift 2 ;; --container) container="$2" shift 2 ;; --config-file) config_file="$2" shift 2 ;; --dry-run) dry_run=true shift ;; --help|-h) cat >&2 <<'USAGE' mas_client_register - Sincroniza clientes OAuth en MAS via mas-cli config sync Usage: mas_client_register --ssh-host --container --config-file [--dry-run] Options: --ssh-host Alias SSH del VPS (ej. organic-machine.com) --container Nombre del container MAS (ej. element_matrix_chat-mas-1) --config-file Ruta en el VPS al mas/config.yaml (ej. /home/ubuntu/project/mas/config.yaml) --dry-run Solo valida config y muestra diff, sin aplicar cambios Output: JSON en stdout con status, applied, clients_total, clients_diff, stderr USAGE # emit minimal valid JSON so callers that parse stdout don't break echo '{"status":"help","applied":false,"clients_total":0,"clients_diff":[],"stderr":""}' return 0 ;; *) echo "mas_client_register: argumento desconocido: $1" >&2 return 1 ;; esac done # Validar argumentos obligatorios local errors=() [[ -z "$ssh_host" ]] && errors+=("--ssh-host es obligatorio") [[ -z "$container" ]] && errors+=("--container es obligatorio") [[ -z "$config_file" ]] && errors+=("--config-file es obligatorio") if [[ ${#errors[@]} -gt 0 ]]; then for err in "${errors[@]}"; do echo "ERROR: $err" >&2 done echo '{"status":"error","applied":false,"clients_total":0,"clients_diff":[],"stderr":"missing required arguments"}' return 1 fi # Verificar dependencias locales if ! command -v jq &>/dev/null; then echo "ERROR: jq no encontrado en el host local. Instalar: apt install jq / brew install jq" >&2 echo '{"status":"error","applied":false,"clients_total":0,"clients_diff":[],"stderr":"jq not found on local host"}' return 1 fi echo "mas_client_register: ssh-host=$ssh_host container=$container dry-run=$dry_run" >&2 # La ruta de config dentro del container siempre es /data/config.yaml (mount convention de MAS) local container_config="/data/config.yaml" # ---- PASO 1: Verificar sintaxis YAML con mas-cli config check ---- echo "mas_client_register: verificando sintaxis de config con mas-cli config check..." >&2 local check_stdout check_stderr check_exit check_stdout=$(ssh "$ssh_host" \ "docker exec ${container} mas-cli config check --config ${container_config}" 2>/tmp/mas_check_stderr_$$ || true) check_exit=$? check_stderr=$(cat /tmp/mas_check_stderr_$$ 2>/dev/null || true) rm -f /tmp/mas_check_stderr_$$ if [[ $check_exit -ne 0 ]]; then echo "mas_client_register: config check falló (exit=$check_exit)" >&2 echo "$check_stderr" >&2 local escaped_stderr escaped_stderr=$(printf '%s' "${check_stderr}" | jq -Rs '.') echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}" return 1 fi echo "mas_client_register: config check OK" >&2 # ---- PASO 2: dry-run o sync ---- if [[ "$dry_run" == "true" ]]; then # Ejecutar mas-cli config dump para mostrar el estado actual y lo que se aplicaria echo "mas_client_register: modo dry-run — ejecutando mas-cli config dump..." >&2 local dump_stdout dump_stderr dump_exit dump_stdout=$(ssh "$ssh_host" \ "docker exec ${container} mas-cli config dump --config ${container_config}" 2>/tmp/mas_dump_stderr_$$ || true) dump_exit=$? dump_stderr=$(cat /tmp/mas_dump_stderr_$$ 2>/dev/null || true) rm -f /tmp/mas_dump_stderr_$$ if [[ $dump_exit -ne 0 ]]; then echo "mas_client_register: config dump falló (exit=$dump_exit)" >&2 echo "$dump_stderr" >&2 local escaped_stderr escaped_stderr=$(printf '%s' "${dump_stderr}" | jq -Rs '.') echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}" return 1 fi # Extraer listado de clients del dump (buscar lineas con client_id o type: client) local clients_diff_raw clients_diff_raw=$(printf '%s\n' "$dump_stdout" | grep -E "client_id:|client_name:" | \ sed 's/^[[:space:]]*//' | head -50 || true) local diff_json diff_json=$(printf '%s\n' "$dump_stdout" | jq -Rs 'split("\n") | map(select(length > 0)) | map(ltrimstr(" "))' 2>/dev/null \ || echo '["(jq parse error — ver stderr)"]') local escaped_dump_stderr escaped_dump_stderr=$(printf '%s' "${dump_stderr}" | jq -Rs '.') echo "mas_client_register: dry-run completado. dump lines=$(echo "$dump_stdout" | wc -l)" >&2 jq -n \ --argjson diff "$diff_json" \ --argjson stderr_str "$escaped_dump_stderr" \ '{ status: "dry-run", applied: false, clients_total: ($diff | length), clients_diff: $diff, stderr: $stderr_str }' return 0 fi # ---- PASO 3: sync real ---- echo "mas_client_register: ejecutando mas-cli config sync --prune..." >&2 local sync_stdout sync_stderr sync_exit sync_stdout=$(ssh "$ssh_host" \ "docker exec ${container} mas-cli config sync --config ${container_config} --prune" \ 2>/tmp/mas_sync_stderr_$$ || true) sync_exit=$? sync_stderr=$(cat /tmp/mas_sync_stderr_$$ 2>/dev/null || true) rm -f /tmp/mas_sync_stderr_$$ echo "mas_client_register: sync exit=$sync_exit" >&2 if [[ -n "$sync_stderr" ]]; then echo "mas_client_register stderr: $sync_stderr" >&2 fi if [[ $sync_exit -ne 0 ]]; then local escaped_stderr escaped_stderr=$(printf '%s' "${sync_stderr}" | jq -Rs '.') echo "{\"status\":\"error\",\"applied\":false,\"clients_total\":0,\"clients_diff\":[],\"stderr\":${escaped_stderr}}" return 1 fi # Parsear output del sync para extraer lineas con cambios aplicados local diff_lines diff_lines=$(printf '%s\n' "$sync_stdout" | grep -E "^\s*(created|updated|deleted|unchanged|synced)" || true) local diff_json diff_json=$(printf '%s\n' "$sync_stdout" | jq -Rs 'split("\n") | map(select(length > 0))' 2>/dev/null \ || echo '[]') local clients_count clients_count=$(printf '%s\n' "$sync_stdout" | grep -cE "client" 2>/dev/null || echo 0) local escaped_sync_stderr escaped_sync_stderr=$(printf '%s' "${sync_stderr}" | jq -Rs '.') echo "mas_client_register: sync completado con exito" >&2 jq -n \ --argjson diff "$diff_json" \ --argjson total "$clients_count" \ --argjson stderr_str "$escaped_sync_stderr" \ '{ status: "ok", applied: true, clients_total: $total, clients_diff: $diff, stderr: $stderr_str }' } # Ejecutar si se llama directamente (no sourced) if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then mas_client_register "$@" fi