#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" source "${script_dir}/lib-compose-project.sh" compose_file="" env_file="" app_service="app" app_id="qortal_integration" occ_path="" runtime_mode="compose" usage() { cat <<'USAGE' Usage: ./scripts/diagnose-qortal-gateway-route.sh --compose-file --env-file [options] Inspect whether the qortal_integration gateway routes are registered in the running Nextcloud instance and whether the live app path matches repo source. Options: --compose-file Docker compose file to inspect (required) --env-file Env file to inspect (required) --app-service Nextcloud app service name (default: app) --app-id App id to inspect (default: qortal_integration) --occ-path Host Nextcloud occ path for host-hybrid installs -h, --help Show this help USAGE } ensure_docker_access() { local docker_path="" docker_path="$(type -P docker || true)" if [[ -z "${docker_path}" ]]; then echo "docker is required" exit 1 fi if "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=("${docker_path}") return 0 fi if ! command -v sudo >/dev/null 2>&1; then echo "docker is installed but this user cannot access it, and sudo is unavailable." exit 1 fi if sudo -n "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=(sudo "${docker_path}") return 0 fi echo "docker requires elevated privileges on this machine." echo "You may be prompted for your sudo password." if sudo "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=(sudo "${docker_path}") return 0 fi echo "Unable to access docker, even with sudo." exit 1 } docker() { "${DOCKER_CMD[@]}" "$@" } occ() { if [[ "${runtime_mode}" == "host" ]]; then if [[ -z "${occ_path}" || ! -f "${occ_path}" ]]; then echo "Missing host occ path: ${occ_path}" >&2 return 1 fi if command -v sudo >/dev/null 2>&1; then sudo -u www-data php "${occ_path}" "$@" return $? fi if command -v runuser >/dev/null 2>&1; then runuser -u www-data -- php "${occ_path}" "$@" return $? fi php "${occ_path}" "$@" return $? fi docker compose -f "${compose_file}" --env-file "${env_file}" exec -T --user www-data "${app_service}" php occ "$@" } tail_nextcloud_log() { local log_file="" if [[ "${runtime_mode}" == "host" ]]; then log_file="$(occ config:system:get logfile 2>/dev/null | tr -d '\r' || true)" if [[ -z "${log_file}" ]]; then return 1 fi if [[ -f "${log_file}" ]]; then tail -n 200 "${log_file}" return 0 fi return 1 fi docker compose -f "${compose_file}" --env-file "${env_file}" exec -T "${app_service}" sh -lc ' if [ -f /var/www/html/data/nextcloud.log ]; then tail -n 200 /var/www/html/data/nextcloud.log fi ' 2>/dev/null } while [[ $# -gt 0 ]]; do case "$1" in --compose-file) compose_file="${2:-}" shift 2 ;; --compose-file=*) compose_file="${1#*=}" shift ;; --env-file) env_file="${2:-}" shift 2 ;; --env-file=*) env_file="${1#*=}" shift ;; --app-service) app_service="${2:-}" shift 2 ;; --app-service=*) app_service="${1#*=}" shift ;; --app-id) app_id="${2:-}" shift 2 ;; --app-id=*) app_id="${1#*=}" shift ;; --occ-path) occ_path="${2:-}" runtime_mode="host" shift 2 ;; --occ-path=*) occ_path="${1#*=}" runtime_mode="host" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" usage exit 1 ;; esac done if [[ -z "${compose_file}" || -z "${env_file}" ]]; then usage exit 1 fi if [[ "${compose_file}" != /* ]]; then compose_file="${repo_root}/${compose_file}" fi if [[ "${env_file}" != /* ]]; then env_file="${repo_root}/${env_file}" fi if [[ ! -f "${compose_file}" ]]; then echo "Missing compose file: ${compose_file}" exit 1 fi if [[ ! -f "${env_file}" ]]; then echo "Missing env file: ${env_file}" exit 1 fi export_compose_project_name_from_env "${env_file}" || true ensure_docker_access echo "Qortal gateway route diagnostics" echo " compose_file=${compose_file}" echo " env_file=${env_file}" echo " compose_project=${COMPOSE_PROJECT_NAME:-}" echo " runtime_mode=${runtime_mode}" if [[ "${runtime_mode}" == "host" ]]; then echo " occ_path=${occ_path}" fi echo " app_service=${app_service}" echo " app_id=${app_id}" echo echo "Compose status:" docker compose -f "${compose_file}" --env-file "${env_file}" ps || true echo echo "App enabled state:" occ app:list 2>/dev/null | grep -n "${app_id}" || true echo echo "Runtime app path:" app_path="$(occ app:getpath "${app_id}" 2>/dev/null | tr -d '\r' || true)" if [[ -z "${app_path}" ]]; then echo " " else echo " ${app_path}" fi route_file_has_gateway="0" if [[ -n "${app_path}" && -f "${app_path}/appinfo/routes.php" ]]; then if grep -q 'gateway#proxy\|/gateway/{path}' "${app_path}/appinfo/routes.php"; then route_file_has_gateway="1" fi fi echo echo "Gateway route registration:" route_output="$(occ app:routes "${app_id}" 2>&1 || true)" printf '%s\n' "${route_output}" | grep -n 'gateway\|account\|qapps' || true if [[ "${runtime_mode}" == "host" && "${route_file_has_gateway}" == "1" ]]; then echo " gateway routes present in appinfo/routes.php" elif ! printf '%s\n' "${route_output}" | grep -q 'gateway'; then echo " gateway routes not present in OCC output" fi echo echo "Relevant app config:" for key in qortal_node_url external_auth_node_url qortal_gateway_url nextcloud_public_url sc_mode qapps_debug_enabled external_auth_app_id external_auth_app_secret external_auth_node_api_key; do value="$(occ config:app:get "${app_id}" "${key}" 2>/dev/null | tr -d '\r' || true)" if [[ -z "${value}" ]]; then value="" elif [[ "${key}" == *secret* || "${key}" == *api_key* ]]; then value="" fi echo " ${key}=${value}" done if [[ -n "${app_path}" ]]; then echo echo "Live GatewayController markers:" if [[ "${runtime_mode}" == "host" ]]; then grep -n 'X-QI-Gateway-Powered-Fallback-Used\|function proxy\|function getLogger\|gateway_proxy_response' "${app_path}/lib/Controller/GatewayController.php" || true else docker compose -f "${compose_file}" --env-file "${env_file}" exec -T "${app_service}" sh -lc " grep -n 'X-QI-Gateway-Powered-Fallback-Used\\|function proxy\\|function getLogger\\|gateway_proxy_response' '${app_path}/lib/Controller/GatewayController.php' || true " 2>/dev/null || true fi echo echo "Live routes.php gateway entries:" if [[ "${runtime_mode}" == "host" ]]; then grep -n 'gateway#proxy\|/gateway/{path}' "${app_path}/appinfo/routes.php" || true else docker compose -f "${compose_file}" --env-file "${env_file}" exec -T "${app_service}" sh -lc " grep -n \"gateway#proxy\\|/gateway/{path}\" '${app_path}/appinfo/routes.php' || true " 2>/dev/null || true fi fi echo echo "Recent Nextcloud log lines mentioning qortal_integration or gateway:" tail_nextcloud_log 2>/dev/null | grep -E 'qortal_integration|gateway_proxy|GatewayController' || true