#!/bin/sh

. /usr/lib/live/config.sh

## live-config(7) - System Configuration Components
## Copyright (C) 2016-2020 The Debian Live team
## Copyright (C) 2006-2015 Daniel Baumann <mail@daniel-baumann.ch>
## Copyright (C) 2025 MiniOS <https://minios.dev>
##
## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
## This is free software, and you are welcome to redistribute it
## under certain conditions; see COPYING for details.

set -e

BEXT="sb"

Cmdline() {
    # Reading kernel command line
    for _PARAMETER in ${LIVE_CONFIG_CMDLINE}; do
        case "${_PARAMETER}" in
        from=*)
            FROM="${_PARAMETER#*from=}"
            ;;
        toram)
            TORAM="true"
            ;;
        live-config.username=* | username=*)
            LIVE_USERNAME="${_PARAMETER#*username=}"
            ;;
        live-config.link-user-dirs | link-user-dirs)
            LIVE_LINK_USER_DIRS="true"
            ;;
        live-config.bind-user-dirs | bind-user-dirs)
            LIVE_BIND_USER_DIRS="true"
            ;;
        live-config.user-dirs-path | user-dirs-path)
            LIVE_USER_DIRS_PATH="${_PARAMETER#*user-dirs-path=}"
            ;;
        live-config.debug | debug)
            LIVE_CONFIG_DEBUG=true
            ;;
        esac
    done
}

Init() {
    # Setting debug mode if enabled
    if [ "${LIVE_CONFIG_DEBUG}" = true ]; then
        set -x
    fi

    # Checking if package is installed or already configured
    if ! pkg_is_installed "user-setup" ||
        ! component_was_executed "user-setup"; then
        exit 0
    fi

    echo -n " user-ssh"
}

Config() {
    if [ -z "$FROM" ] || echo "$FROM" | grep 'http://' || [ -d "/run/initramfs/memory/iso" ]; then
        FROM="minios"
    elif [ -f /run/initramfs/var/log/from.log ]; then
        FROM=$(cat /run/initramfs/var/log/from.log)
    fi

    # search for bundles in the mounted directory
    if [ "$(find "/run/initramfs/memory/data/$FROM" -maxdepth 1 -name "*.$BEXT" 2>/dev/null)" != "" ]; then
        # we found at least one bundle/module here
        FROM=$(echo "/run/initramfs/memory/data/$FROM" | tr -s "/" | sed -r "s:/[^/]+/[.][.]/:/:g")
    elif [ "$(find "/run/initramfs/memory/iso/$FROM" -maxdepth 1 -name "*.$BEXT" 2>/dev/null)" != "" ]; then
        FROM=$(echo "/run/initramfs/memory/iso/$FROM" | tr -s "/" | sed -r "s:/[^/]+/[.][.]/:/:g")
    fi
    MEDIA="$FROM"

    echo "Checking if the media is writable or if TORAM mode is enabled"
    if ! test -w "$MEDIA" || [ "$TORAM" = "true" ]; then
        WRITABLE="false"
        echo "The media is not writable or the system is running in TORAM mode."
    else
        WRITABLE="true"
        echo "The media is writable."
    fi

    # Path to the marker file for storing last authkeys sync time
    STATE_FILE="/var/lib/live/config/last-authkeys-sync-time"

    # Get current time in seconds since epoch
    NOW=$(date +%s)

    # Flag indicating that system time is incorrect (has been reset)
    SKIP_TIME_CHECK=false

    # Check the marker of the previous synchronization
    if [ -f "$STATE_FILE" ]; then
        LAST_SYNC=$(cat "$STATE_FILE")
        if [ "$NOW" -lt "$LAST_SYNC" ]; then
            echo "ERROR: System time appears wrong. Skipping timestamp-based authkeys sync."
            SKIP_TIME_CHECK=true
        fi
    fi

    echo "Starting sync of authorized_keys for all users"

    # --- Function: determine whether to copy src ($1) to dst ($2)
    should_copy() {
        # $1 = source path, $2 = destination path
        if [ "$SKIP_TIME_CHECK" = true ]; then
            # if time is reset — only copy when destination does not exist
            [ ! -f "$2" ]
        else
            # otherwise — copy if dst missing or src is newer than dst
            [ ! -f "$2" ] || [ "$1" -nt "$2" ]
        fi
    }

    # Function to sync keys for a specific user
    sync_user_keys() {
        local USERNAME="$1"
        local USER_HOME
        local USER_KEYS_FILE="$MEDIA/authorized_keys.$USERNAME"
        
        # Determine home directory
        case "$USERNAME" in
            root)
                USER_HOME="/root"
                ;;
            *)
                USER_HOME="/home/$USERNAME"
                ;;
        esac

        # Skip if user doesn't exist
        if ! id "$USERNAME" >/dev/null 2>&1; then
            return
        fi

        # Skip if no keys file for this user
        if [ ! -f "$USER_KEYS_FILE" ]; then
            return
        fi

        echo "Processing keys for user: $USERNAME"

        # Prepare SSH directory
        if [ ! -d "$USER_HOME/.ssh" ]; then
            echo "Creating SSH directory for $USERNAME"
            mkdir -p "$USER_HOME/.ssh" || {
                echo "ERROR: Failed to create directory '$USER_HOME/.ssh'"
                return 1
            }
            chmod 700 "$USER_HOME/.ssh" || {
                echo "ERROR: Failed to set permissions on '$USER_HOME/.ssh'"
                return 1
            }
            chown "$USERNAME:$USERNAME" "$USER_HOME/.ssh" || {
                echo "ERROR: Failed to set ownership on '$USER_HOME/.ssh'"
                return 1
            }
        fi

        # --- Sync from media to home ---
        if should_copy "$USER_KEYS_FILE" "$USER_HOME/.ssh/authorized_keys"; then
            echo "Copying $USER_KEYS_FILE -> $USER_HOME/.ssh/authorized_keys"
            cp -fp "$USER_KEYS_FILE" "$USER_HOME/.ssh/authorized_keys" || {
                echo "ERROR: copy failed for user $USERNAME"
                return 1
            }
            chmod 600 "$USER_HOME/.ssh/authorized_keys" || {
                echo "ERROR: Failed to set permissions on $USER_HOME/.ssh/authorized_keys"
                return 1
            }
            chown "$USERNAME:$USERNAME" "$USER_HOME/.ssh/authorized_keys" || {
                echo "ERROR: Failed to set ownership on $USER_HOME/.ssh/authorized_keys"
                return 1
            }
        # --- If writable, sync back from home to media ---
        elif [ "$WRITABLE" = "true" ] && [ -f "$USER_HOME/.ssh/authorized_keys" ] && should_copy "$USER_HOME/.ssh/authorized_keys" "$USER_KEYS_FILE"; then
            echo "Copying $USER_HOME/.ssh/authorized_keys -> $USER_KEYS_FILE"
            cp -fp "$USER_HOME/.ssh/authorized_keys" "$USER_KEYS_FILE" || {
                echo "ERROR: reverse copy failed for user $USERNAME"
                return 1
            }
        fi
    }

    # Find all authorized_keys.* files on media and sync for each user
    for KEYS_FILE in "$MEDIA"/authorized_keys.*; do
        if [ -f "$KEYS_FILE" ]; then
            USERNAME=$(basename "$KEYS_FILE" | sed 's/^authorized_keys\.//')
            if [ -n "$USERNAME" ] && [ "$USERNAME" != "*" ]; then
                sync_user_keys "$USERNAME"
            fi
        fi
    done

    # Update the marker if the system time is valid
    if [ "$SKIP_TIME_CHECK" = "false" ]; then
        echo "$NOW" >"$STATE_FILE" || echo "WARNING: Could not write authkeys state file"
    fi

    echo "Sync completed"

    # Creating state file
    #touch /var/lib/live/config/user-ssh
}

Cmdline
Init
Config
