#!/bin/bash

# Admin SSH access to THIS host. Manages the install user's authorized_keys —
# paste a public key to grant access — and, behind a lockout guard, sshd
# password authentication. Everything here is on-demand only: nothing runs
# during install or deploy. LibrePortal is the *server* here, so the admin
# brings their own public key; we never handle their private key.

# The user admins actually log in as (has sudo). Falls back to libreportal.
hostSshUser()
{
    echo "${sudo_user_name:-libreportal}"
}

hostSshHome()
{
    local u; u=$(hostSshUser)
    [[ "$u" == "root" ]] && { echo "/root"; return; }
    echo "/home/$u"
}

hostSshAuthKeysFile()
{
    echo "$(hostSshHome)/.ssh/authorized_keys"
}

# Refresh the WebUI access snapshot after a change. No-op if generator absent.
hostSshRefreshUi()
{
    declare -f webuiGenerateSshAccess >/dev/null 2>&1 && webuiGenerateSshAccess >/dev/null 2>&1
    return 0
}

hostSshEnsureDir()
{
    local u sshdir akf
    u=$(hostSshUser)
    sshdir="$(hostSshHome)/.ssh"
    akf=$(hostSshAuthKeysFile)
    sudo mkdir -p "$sshdir"
    sudo touch "$akf"
    sudo chmod 700 "$sshdir"
    sudo chmod 600 "$akf"
    sudo chown -R "$u":"$u" "$sshdir"
}

# Count valid authorized public keys.
hostSshKeyCount()
{
    local akf; akf=$(hostSshAuthKeysFile)
    sudo test -f "$akf" || { echo 0; return; }
    sudo grep -cvE '^[[:space:]]*($|#)' "$akf" 2>/dev/null || echo 0
}

# True when sshd currently allows password authentication.
hostSshPasswordAuthEnabled()
{
    local v
    v=$(sudo sshd -T 2>/dev/null | awk '/^passwordauthentication/ {print $2}')
    [[ -z "$v" ]] && v=$(grep -iE '^[[:space:]]*PasswordAuthentication' "$sshd_config" 2>/dev/null | tail -1 | awk '{print tolower($2)}')
    [[ "$v" == "no" ]] && return 1
    return 0   # default-on when unspecified
}

# Add a base64-encoded PUBLIC key to the install user's authorized_keys.
hostSshKeyAdd()
{
    local key_b64="$1"
    [[ -z "$key_b64" ]] && { isError "hostSshKeyAdd requires <base64-public-key>"; return 1; }

    local pub
    pub=$(echo "$key_b64" | base64 -d 2>/dev/null | tr -d '\r' | grep -vE '^[[:space:]]*$' | head -1)
    [[ -z "$pub" ]] && { isError "Empty key after decode"; return 1; }

    if ! printf '%s\n' "$pub" | ssh-keygen -l -f - >/dev/null 2>&1; then
        isError "Not a valid SSH public key (expected e.g. 'ssh-ed25519 AAAA... comment')"
        return 1
    fi

    hostSshEnsureDir
    local akf body
    akf=$(hostSshAuthKeysFile)
    body=$(awk '{print $2}' <<< "$pub")
    if sudo grep -qF "$body" "$akf" 2>/dev/null; then
        isNotice "That key is already authorized."
    else
        printf '%s\n' "$pub" | sudo tee -a "$akf" >/dev/null
        isSuccessful "SSH key authorized for $(hostSshUser)"
    fi
    sudo chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
    sudo chmod 600 "$akf"
    hostSshRefreshUi
}

# Remove the authorized key whose fingerprint matches $1. Guards against
# removing the last key while password auth is off (that would lock you out).
hostSshKeyRemove()
{
    local fp="$1"
    [[ -z "$fp" ]] && { isError "hostSshKeyRemove requires <fingerprint>"; return 1; }
    local akf; akf=$(hostSshAuthKeysFile)
    sudo test -f "$akf" || { isError "No authorized_keys file"; return 1; }

    if ! hostSshPasswordAuthEnabled && [[ "$(hostSshKeyCount)" -le 1 ]]; then
        isError "Refusing to remove the last key while password login is disabled — you'd be locked out. Re-enable password login first."
        return 1
    fi

    local tmp; tmp=$(mktemp)
    local removed=0 line lfp
    while IFS= read -r line; do
        if [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]]; then
            printf '%s\n' "$line" >> "$tmp"; continue
        fi
        lfp=$(printf '%s\n' "$line" | ssh-keygen -l -f - 2>/dev/null | awk '{print $2}')
        if [[ -n "$lfp" && "$lfp" == "$fp" ]]; then
            removed=1; continue
        fi
        printf '%s\n' "$line" >> "$tmp"
    done < <(sudo cat "$akf")

    if [[ "$removed" -eq 1 ]]; then
        sudo cp "$tmp" "$akf"
        sudo chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
        sudo chmod 600 "$akf"
        isSuccessful "Removed SSH key $fp"
    else
        isNotice "No key matched fingerprint $fp"
    fi
    rm -f "$tmp"
    hostSshRefreshUi
}

# Enable/disable sshd password authentication. Disabling is guarded: there
# must be at least one authorized key, or you'd lock yourself out.
hostSshSetPasswordAuth()
{
    local want="$1"   # on|off
    case "$want" in
        on|off) ;;
        *) isError "hostSshSetPasswordAuth requires on|off"; return 1 ;;
    esac

    if [[ "$want" == "off" && "$(hostSshKeyCount)" -lt 1 ]]; then
        isError "Refusing to disable password login with no authorized keys — add a key first or you'll be locked out."
        return 1
    fi

    local value="yes"; [[ "$want" == "off" ]] && value="no"
    local backup="${sshd_config}.libreportal.$(date +%s)"
    sudo cp "$sshd_config" "$backup"
    sudo sed -i '/^[[:space:]]*#\?[[:space:]]*PasswordAuthentication\b/d' "$sshd_config"
    echo "PasswordAuthentication $value" | sudo tee -a "$sshd_config" >/dev/null

    if ! sudo sshd -t 2>/dev/null; then
        isError "sshd config test failed — restoring backup, no change made."
        sudo cp "$backup" "$sshd_config"
        return 1
    fi
    sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd 2>/dev/null
    isSuccessful "Password login ${want} (sshd reloaded; backup at $backup)"
    hostSshRefreshUi
}
