#!/usr/bin/env bash
# =============================================================================
# onx-user-password — Reset Linux / FTP / WebDAV passwords
#
# Purpose:
#   Updates one or more credential stores for a hosting account depending on
#   the requested scope. Passwords must already be hashed by the caller where
#   expected (chpasswd accepts pre-hashed passwords in "$6$..." format, or
#   plain text when the caller has already applied server-side hashing).
#
# Input (stdin JSON):
#   {
#     "username": "onx_xxxx",
#     "password": "<cleartext or hashed>",   -- required
#     "scope":    "linux|ftp|webdisk|all"    -- default "all"
#   }
#
# Output (stdout JSON):
#   {"username":..., "updated":["linux","ftp","webdisk"]}
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail 4=rolled-back 5=rollback-failed
#
# Sudoers entry needed:
#   apache ALL=(root) NOPASSWD: /usr/local/onoxsoft/bin/onx-user-password
#   Defaults!/usr/local/onoxsoft/bin/onx-user-password !requiretty
#   Defaults!/usr/local/onoxsoft/bin/onx-user-password log_output, log_input
#
# Deployed to: /usr/local/onoxsoft/bin/onx-user-password
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

# ── Constants ─────────────────────────────────────────────────────────────────
WEBDISK_PASSWD_FILE="/etc/onox/webdisk.passwd"
VALID_SCOPES=("linux" "ftp" "webdisk" "all")

# ── Dependencies ──────────────────────────────────────────────────────────────
command -v jq       >/dev/null 2>&1 || { printf '{"error":"jq required"}\n' >&2; exit 2; }
command -v chpasswd >/dev/null 2>&1 || { printf '{"error":"chpasswd required"}\n' >&2; exit 2; }
require_root

# ── Read & parse stdin ────────────────────────────────────────────────────────
INPUT=$(cat)
onx_require_json "${INPUT}"

USERNAME=$(onx_json_get "${INPUT}" "username")
PASSWORD=$(onx_json_get "${INPUT}" "password")
SCOPE=$(onx_json_get    "${INPUT}" "scope" "all")

# ── Input validation ──────────────────────────────────────────────────────────
onx_validate_username "${USERNAME}"
[[ -z "${PASSWORD}" ]] && onx_die 1 "password is required"

SCOPE_VALID=false
for s in "${VALID_SCOPES[@]}"; do
    [[ "$s" == "${SCOPE}" ]] && SCOPE_VALID=true && break
done
[[ "${SCOPE_VALID}" == "true" ]] || onx_die 1 "invalid scope '${SCOPE}': must be linux|ftp|webdisk|all"

# ── Preflight ─────────────────────────────────────────────────────────────────
id "${USERNAME}" &>/dev/null || onx_die 2 "Linux user does not exist: ${USERNAME}"
mkdir -p "$(dirname "${WEBDISK_PASSWD_FILE}")"

# ── Apply passwords ───────────────────────────────────────────────────────────
UPDATED=()

# Linux password via chpasswd
if [[ "${SCOPE}" == "linux" || "${SCOPE}" == "all" ]]; then
    printf '%s:%s\n' "${USERNAME}" "${PASSWORD}" | chpasswd || \
        onx_die 3 "chpasswd failed for ${USERNAME}"
    onx_log "linux password updated: ${USERNAME}"
    UPDATED+=("linux")
fi

# FTP password via pure-pw
if [[ "${SCOPE}" == "ftp" || "${SCOPE}" == "all" ]]; then
    if command -v pure-pw >/dev/null 2>&1; then
        printf '%s\n%s\n' "${PASSWORD}" "${PASSWORD}" | \
            pure-pw passwd "${USERNAME}" -m 2>/dev/null || \
            onx_die 3 "pure-pw passwd failed for ${USERNAME}"
        onx_log "FTP password updated: ${USERNAME}"
        UPDATED+=("ftp")
    else
        onx_log "WARNING: pure-pw not installed, skipping FTP password"
    fi
fi

# WebDAV/WebDisk password via htpasswd
if [[ "${SCOPE}" == "webdisk" || "${SCOPE}" == "all" ]]; then
    if command -v htpasswd >/dev/null 2>&1; then
        htpasswd -b "${WEBDISK_PASSWD_FILE}" "${USERNAME}" "${PASSWORD}" || \
            onx_die 3 "htpasswd failed for ${USERNAME}"
        onx_log "webdisk password updated: ${USERNAME}"
        UPDATED+=("webdisk")
    else
        onx_log "WARNING: htpasswd not installed, skipping webdisk password"
    fi
fi

# ── Build updated array JSON ──────────────────────────────────────────────────
UPDATED_JSON=$(printf '%s\n' "${UPDATED[@]+"${UPDATED[@]}"}" | \
    jq -Rsc 'split("\n") | map(select(. != ""))')

# ── Output ────────────────────────────────────────────────────────────────────
printf '{"username":"%s","updated":%s}\n' "${USERNAME}" "${UPDATED_JSON}"
