#!/usr/bin/env bash
# install.sh — instala o wrapper SSH do Assistente RH num Sabichao (dev ou prod).
# Idempotente: pode ser corrido varias vezes sem duplicar nada.
#
# Uso (correr como root DENTRO do CT alvo):
#   ALVO=dev FROM_IP=192.168.69.150 \
#   PUB_CONSULTA="ssh-ed25519 AAAA... assistente-consulta@ct117" \
#   PUB_APPLY="ssh-ed25519 AAAA... assistente-apply@ct117" \
#     ./install.sh
#
# ALVO=prod instala SO a chave de consulta (a chave de apply so entra a partir
# da Fase 5, decisao do doc 03). PUB_APPLY pode ficar vazio em prod.
#
# Variaveis:
#   ALVO       "dev" ou "prod" (obrigatorio)
#   FROM_IP    IP de onde as ligacoes sao aceites, para from= no authorized_keys
#              (obrigatorio) — normalmente o CT do assistente (assistente-dev / assistente prod)
#   PUB_CONSULTA  chave publica de consulta (obrigatoria)
#   PUB_APPLY     chave publica de apply (obrigatoria em dev; opcional em prod)
#   RELEASE    nome da release (default: timestamp)
#   SRC_SKILL  pasta com inserir.php/portal_lookup.php/fichas_email.php
#              (default: /root/assistente-src se existir, senao a pasta deste script)

set -euo pipefail
umask 022

: "${ALVO:?defina ALVO=dev ou ALVO=prod}"
: "${FROM_IP:?defina FROM_IP=<ip de origem permitido>}"
: "${PUB_CONSULTA:?defina PUB_CONSULTA=<chave publica de consulta>}"

if [ "$ALVO" != "dev" ] && [ "$ALVO" != "prod" ]; then
    echo "ALVO tem de ser 'dev' ou 'prod'" >&2
    exit 1
fi
if [ "$ALVO" = "dev" ] && [ -z "${PUB_APPLY:-}" ]; then
    echo "ALVO=dev exige tambem PUB_APPLY (as duas chaves sao instaladas em dev)" >&2
    exit 1
fi
if [ "$(id -u)" != "0" ]; then
    echo "corre como root" >&2
    exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SRC_SKILL="${SRC_SKILL:-}"
if [ -z "$SRC_SKILL" ]; then
    if [ -d /root/assistente-src ]; then
        SRC_SKILL=/root/assistente-src
    else
        SRC_SKILL="$SCRIPT_DIR"
    fi
fi

echo "== 1. utilizador tecnico 'assistente' =="
if ! id assistente >/dev/null 2>&1; then
    useradd --system --home-dir /opt/assistente --shell /bin/bash --no-create-home assistente
    echo "utilizador 'assistente' criado."
else
    echo "utilizador 'assistente' ja existe."
fi
# Campo da password no /etc/shadow: '*' (sem password possivel, conta so por
# chave), nunca deixar vazio.
usermod -p '*' assistente

echo "== 2. estrutura /opt/assistente =="
mkdir -p /opt/assistente/bin /opt/assistente/releases /opt/assistente/run /opt/assistente/etc
# StrictModes do sshd exige que o home do utilizador (nao os subdiretorios de
# release) seja dono do proprio utilizador tecnico, senao a chave publica e
# silenciosamente recusada ("key is not allowed", sem mais detalhe no log) —
# testado e confirmado em dev 2026-09-22. 755 (nao 700): StrictModes so exige
# "nao escrivel por outros", nao exige fechado a leitura/travessia — e o
# www-data (que corre inserir.php/portal_lookup.php/fichas_email.php via sudo,
# ver secao 7) precisa de atravessar este diretorio para chegar a bin/current.
chown assistente:assistente /opt/assistente
chmod 755 /opt/assistente
chown root:root /opt/assistente/releases /opt/assistente/etc
chmod 755 /opt/assistente/releases /opt/assistente/etc

echo "$ALVO" > /opt/assistente/etc/alvo
chmod 644 /opt/assistente/etc/alvo
echo "alvo gravado: $ALVO"

echo "== 3. release versionada (root-owned) =="
RELEASE="${RELEASE:-$(date +%Y%m%d%H%M%S)}"
REL_DIR="/opt/assistente/releases/$RELEASE"
if [ -d "$REL_DIR" ]; then
    echo "release $RELEASE ja existe, a reusar."
else
    mkdir -p "$REL_DIR"
    for f in inserir.php portal_lookup.php fichas_email.php; do
        if [ ! -f "$SRC_SKILL/$f" ]; then
            echo "falta $SRC_SKILL/$f — aborta" >&2
            exit 1
        fi
        cp "$SRC_SKILL/$f" "$REL_DIR/$f"
    done
    cp "$SCRIPT_DIR/wrapper.php" "$REL_DIR/wrapper.php"
    cp "$SCRIPT_DIR/assistente-wrapper" "$REL_DIR/assistente-wrapper"
    cp "$SCRIPT_DIR/ficha_pdf.php" "$REL_DIR/ficha_pdf.php"
    chown -R root:root "$REL_DIR"
    chmod 755 "$REL_DIR"
    chmod 644 "$REL_DIR"/*.php
    chmod 755 "$REL_DIR/assistente-wrapper"
    echo "release $RELEASE instalada em $REL_DIR"
fi

echo "== 4. symlink 'current' =="
ln -sfn "$REL_DIR" /opt/assistente/bin/current
chown -h root:root /opt/assistente/bin/current
WRAPPER_ENTRYPOINT="/opt/assistente/bin/current/assistente-wrapper"

echo "== 5. pasta de idempotencia do apply =="
mkdir -p /var/lib/assistente/apply
chown assistente:assistente /var/lib/assistente/apply
chmod 700 /var/lib/assistente/apply

echo "== 6. home do utilizador tecnico e .ssh =="
mkdir -p /opt/assistente/.ssh
chmod 700 /opt/assistente/.ssh

AUTH_KEYS=/opt/assistente/.ssh/authorized_keys
touch "$AUTH_KEYS"

# Reescreve sempre a linha da chave (remove a anterior, se existir, e acrescenta
# a atual) para que uma reinstalacao tambem atualize from=/command= se mudarem,
# nao so a primeira instalacao.
LINHA_CONSULTA="from=\"$FROM_IP\",command=\"$WRAPPER_ENTRYPOINT consulta\",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding $PUB_CONSULTA"
grep -vF "$PUB_CONSULTA" "$AUTH_KEYS" > "$AUTH_KEYS.tmp" 2>/dev/null || true
mv "$AUTH_KEYS.tmp" "$AUTH_KEYS"
echo "$LINHA_CONSULTA" >> "$AUTH_KEYS"
echo "chave de consulta escrita/atualizada."

if [ -n "${PUB_APPLY:-}" ]; then
    LINHA_APPLY="from=\"$FROM_IP\",command=\"$WRAPPER_ENTRYPOINT apply\",no-pty,no-port-forwarding,no-agent-forwarding,no-X11-forwarding $PUB_APPLY"
    grep -vF "$PUB_APPLY" "$AUTH_KEYS" > "$AUTH_KEYS.tmp" 2>/dev/null || true
    mv "$AUTH_KEYS.tmp" "$AUTH_KEYS"
    echo "$LINHA_APPLY" >> "$AUTH_KEYS"
    echo "chave de apply escrita/atualizada."
fi

chown -R assistente:assistente /opt/assistente/.ssh
chmod 600 "$AUTH_KEYS"

echo "== 7. sudoers minimo =="
# Testado em dev 2026-09-22: a pasta funcoes/ do webroot (dev e prod) e 0700
# www-data:www-data — mesmo consulta.portal_lookup/dry_run/apply, que so
# precisam de ligar a BD, falham a ler os helpers do repo (require_once) se
# corridos como 'assistente'. Por isso TODAS as chamadas a inserir.php,
# portal_lookup.php e fichas_email.php correm via sudo -u www-data, com SETENV
# para passar DB_*/SABICHAO_* sem os gravar em ficheiro nenhum. sudoers restrito
# aos 3 scripts da release corrente (symlink /opt/assistente/bin/current), sem
# shell generico.
SUDOERS_FILE=/etc/sudoers.d/assistente-wrapper
cat > "$SUDOERS_FILE" <<EOF
# Gerido por install.sh do projeto Assistente RH. Nao editar a mao.
Defaults:assistente !requiretty
assistente ALL=(www-data) NOPASSWD:SETENV: /usr/bin/php /opt/assistente/bin/current/inserir.php *
assistente ALL=(www-data) NOPASSWD:SETENV: /usr/bin/php /opt/assistente/bin/current/portal_lookup.php *
assistente ALL=(www-data) NOPASSWD:SETENV: /usr/bin/php /opt/assistente/bin/current/fichas_email.php *
assistente ALL=(www-data) NOPASSWD:SETENV: /usr/bin/php /opt/assistente/bin/current/ficha_pdf.php *
EOF
chmod 440 "$SUDOERS_FILE"
visudo -cf "$SUDOERS_FILE" >/dev/null

echo "== instalacao concluida =="
echo "alvo: $ALVO"
echo "release: $RELEASE (current -> $REL_DIR)"
echo "authorized_keys: $AUTH_KEYS"
