Files
Qortal-Nextcloud-Integration/scripts/ensure-nextcloud-office-config.sh

292 lines
7.1 KiB
Bash
Executable File

#!/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"
verify_only="0"
usage() {
cat <<'USAGE'
Usage: ./scripts/ensure-nextcloud-office-config.sh --compose-file <file> --env-file <file> [options]
Ensures Nextcloud Office / Collabora configuration matches env values.
Options:
--compose-file <path> Docker compose file to use (required)
--env-file <path> Env file to use (required)
--app-service <name> Nextcloud app service name (default: app)
--verify-only Do not attempt repairs; only verify current state
-h, --help Show this help
USAGE
}
read_kv() {
local key="$1"
local line
line="$(grep -m1 -E "^${key}=" "${env_file}" || true)"
if [[ -z "${line}" ]]; then
return 1
fi
echo "${line#*=}"
}
trim_csv() {
local raw="${1:-}"
local cleaned
cleaned="$(echo "${raw}" | tr -d '[:space:]')"
cleaned="${cleaned#,}"
cleaned="${cleaned%,}"
echo "${cleaned}"
}
profile_enabled() {
local profiles="$1"
local name="$2"
[[ ",${profiles}," == *",${name},"* ]]
}
compute_public_url() {
local domain="$1"
local https_port="$2"
if [[ -z "${domain}" ]]; then
echo ""
return 0
fi
if [[ -n "${https_port}" && "${https_port}" != "443" ]]; then
echo "https://${domain}:${https_port}"
else
echo "https://${domain}"
fi
}
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[@]}" "$@"
}
compose_cmd() {
docker compose -f "${compose_file}" --env-file "${env_file}" "$@"
}
occ_exec() {
compose_cmd exec -T --user www-data "${app_service}" php occ "$@"
}
occ_exec_quiet_retry() {
local rc=1
local max_attempts="${OCC_RETRY_ATTEMPTS:-6}"
local retry_sleep="${OCC_RETRY_SLEEP_SECONDS:-4}"
local attempt
if [[ $# -eq 0 ]]; then
return 1
fi
for attempt in $(seq 1 "${max_attempts}"); do
occ_exec "$@" >/dev/null 2>&1
rc=$?
if [[ "${rc}" -eq 0 ]]; then
return 0
fi
sleep "${retry_sleep}"
done
return "${rc}"
}
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
;;
--verify-only)
verify_only="1"
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
profiles="$(trim_csv "$(read_kv "COMPOSE_PROFILES" || true)")"
if ! profile_enabled "${profiles}" "office"; then
echo "Office profile not enabled in ${env_file}; nothing to do."
exit 0
fi
if ! occ_exec status >/dev/null 2>&1; then
echo "Nextcloud OCC is not ready in service '${app_service}'."
exit 1
fi
collabora_public_url="$(read_kv "COLLABORA_PUBLIC_URL" || true)"
collabora_public_url="${collabora_public_url%/}"
if [[ -z "${collabora_public_url}" ]]; then
collabora_domain="$(read_kv "COLLABORA_DOMAIN" || true)"
public_https_port="$(read_kv "PUBLIC_HTTPS_PORT" || true)"
if [[ -z "${public_https_port}" ]]; then
public_https_port="$(read_kv "CADDY_HTTPS_PORT" || true)"
fi
collabora_public_url="$(compute_public_url "${collabora_domain}" "${public_https_port}")"
fi
if [[ -z "${collabora_public_url}" ]]; then
echo "Missing COLLABORA_PUBLIC_URL or COLLABORA_DOMAIN while office profile is enabled."
exit 1
fi
status=0
office_enable_status=0
office_wopi_status=0
office_public_wopi_status=0
echo "Ensuring Nextcloud Office configuration..."
echo " compose_file=${compose_file}"
echo " env_file=${env_file}"
echo " collabora_public_url=${collabora_public_url}"
if [[ "${verify_only}" != "1" ]]; then
if occ_exec_quiet_retry app:enable --force richdocuments; then
office_enable_status=0
else
office_enable_status=1
occ_exec_quiet_retry app:install richdocuments >/dev/null 2>&1 || true
if occ_exec_quiet_retry app:enable --force richdocuments; then
office_enable_status=0
else
office_enable_status=1
fi
fi
if occ_exec_quiet_retry config:app:set richdocuments wopi_url --value="${collabora_public_url}"; then
office_wopi_status=0
else
office_wopi_status=1
fi
if occ_exec_quiet_retry config:app:set richdocuments public_wopi_url --value="${collabora_public_url}"; then
office_public_wopi_status=0
else
office_public_wopi_status=1
fi
fi
if [[ "${office_enable_status}" -ne 0 || "${office_wopi_status}" -ne 0 || "${office_public_wopi_status}" -ne 0 ]]; then
status=1
fi
if ! occ_exec app:list --enabled 2>/dev/null | grep -qE '^[[:space:]]+- richdocuments:'; then
echo "richdocuments app is not enabled."
status=1
fi
current_wopi_url="$(occ_exec config:app:get richdocuments wopi_url 2>/dev/null | tr -d '\r' || true)"
current_public_wopi_url="$(occ_exec config:app:get richdocuments public_wopi_url 2>/dev/null | tr -d '\r' || true)"
if [[ "${current_wopi_url%/}" != "${collabora_public_url}" ]]; then
echo "richdocuments wopi_url mismatch: ${current_wopi_url:-<empty>}"
status=1
fi
if [[ "${current_public_wopi_url%/}" != "${collabora_public_url}" ]]; then
echo "richdocuments public_wopi_url mismatch: ${current_public_wopi_url:-<empty>}"
status=1
fi
echo "Office verification summary:"
echo " richdocuments_enabled=$([[ "${status}" -eq 0 ]] && echo yes || echo check_failed)"
echo " wopi_url=${current_wopi_url:-<empty>}"
echo " public_wopi_url=${current_public_wopi_url:-<empty>}"
if [[ "${status}" -eq 0 ]]; then
echo "Office configuration verified."
else
echo "Office configuration verification failed."
fi
exit "${status}"