#!/bin/bash -e
# This is a hook to handle the changes to the mysql.user table in MariaDB 10.4+

# set DEBUG=y to enable verbose output
[[ -z "$DEBUG" ]] || set -x

# hooks are always called with two arguments
op=$1
state=$2

HOOK="[HOOK:$(basename "$0")]"

fatal() {
    echo "[$(basename "$0")] FATAL: $*" >&2
    logger -t tklbam -p err "$*"
    exit 1
}
warn() {
    echo "$HOOK WARN: $*" >&2
    logger -t tklbam -p warn "$HOOK $*"
}

info() {
    local quiet=$1
    shift
    # if quiet set don't echo; just log
    [[ -n "$quiet" ]] || echo "$HOOK INFO: $*"
    logger -t tklbam -p info "$HOOK $*"
}

migrate_db_not_set() {
    warn "MIGRATE_DB env var not set; DB restore of MySQL/MariaDB from TKL v16.x and earlier may fail"
    warn "If migration of old backup fails, please run 'tklbam-restore-rollback' and retry with 'MIGRATE_DB=y tklbam-restore ...'"
}

check_version() {
    local org_version
    local bak_version
    org_version=$(sed -En "s|turnkey-[a-z0-9-]+-([0-9]+)\.[0-9]+[a-z0-9]*-.*|\1|p" /etc/turnkey_version)
    bak_version=$(sed -En "s|turnkey-[a-z0-9-]+-([0-9]+)\.[0-9]+[a-z0-9]*-.*|\1|p" <<<"$TKLBAM_RESTORE_PROFILE_ID")
    if [[ "$org_version" -ge 17 ]] && [[ "$bak_version" -le 16 ]]; then
        echo "run_migration"
    else
        echo "skip_migration"
    fi
}

info quiet ":: op=$op state=$state pwd=$(pwd) ::"
info quiet "TKLBAM_RESTORE_PROFILE_ID: $TKLBAM_RESTORE_PROFILE_ID"

if [[ "$(check_version)" == "skip_migration" ]]; then
    info quiet "no DB migration required"
    exit 0
elif [[ ! -x /usr/bin/mysql ]] && [[ ! -x /usr/bin/mariadb ]]; then
    info quiet "No MySQL/MariaDB executalbe found - assuming no MySQL/MariaDB DB"
    exit 0
fi

if [[ "$state" == "pre" ]] && [[ "$op" == "restore" ]]; then
    info "invoked before Duplicity downloads backup archive."
    info quiet "Extras path = $(pwd)"
    info "nothing to do yet (DB migration may be required after restore)"
elif [[ "$state" == "inspect" ]] && [[ "$op" == "restore" ]]; then
    info "invoked before Duplicity downloads backup archive."
    info quiet "Extras path = $(pwd)"
    warn "legacy MySQL/MariaDB DB detected"
    warn "working around possible restore issue"
    mysqldump mysql > /tmp/mysql_db.sql || fatal "mysqldump failed"
    info "'mysql' DB dumped to /tmp/mysql_db.sql"
    mysql -e "DROP TABLE IF EXISTS mysql.global_priv; DROP VIEW IF EXISTS mysql.user;" \
        || fatal "dropping mysql.view failed"
    info "Table mysql.global_priv & view mysql.user dropped, continuing restore"
elif [[ "$state" == "post" ]]  && [[ "$op" == "restore" ]]; then
    info "hook invoked after backup restore."
    info quiet "Extras path = $(pwd)"
    if [[ -f "/tmp/mysql_db.sql" ]]; then
        warn "/tmp/mysql_db.sql exists"
        warn "assuming legacy MySQL/MariaDB DB; restarting service"
    else
        info quiet "no local MySQL/MariDB 'mysql' database backup located"
        # ensure no mariadb processes still running
        systemctl stop mariadb
        pkill mariadb || true

        # start mariadb with '--skip-grant-tables' - to fix permissions
        # pre/post exec commands taken from mariadb.service file, possibly not
        # all needed, but just in case...
        ## pre-exec
        /usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld
        systemctl unset-environment _WSREP_START_POSITION
        if [ ! -e /usr/bin/galera_recovery ]; then
           VAR=
        else
            if VAR=$(cd /usr/bin/..; /usr/bin/galera_recovery); then
                systemctl set-environment _WSREP_START_POSITION="$VAR"
            else
                exit 1
            fi
        fi
        ## exec
        su mysql -s /bin/bash -c "/usr/sbin/mariadbd --skip-grant-tables" &
        ## post-exec
        systemctl unset-environment _WSREP_START_POSITION
        /etc/mysql/debian-start
       
        # wait until mariadb socket is available
        tries=0
        sock="/var/run/mysqld/mysqld.sock"
        while [[ ! -S "$sock" ]]; do
            if [[ "$tries" -le 10 ]]; then
                sleep 1
            else
                fatal "FATAL: $sock not found after waiting $tries seconds"
            fi
            tries=$((tries+1))
        done

        # reset root@localhost and mysql@locahost users are authenticted by unix_socket
        mysql --wait --batch --execute \
                 "FLUSH PRIVILEGES; \
                  GRANT SELECT ON *.* TO root@localhost IDENTIFIED VIA unix_socket; \
                  GRANT SELECT ON *.* TO mysql@localhost IDENTIFIED VIA unix_socket;" \
            || fatal "resetting local unix_socket authentication failed"
        if [[ -f "/etc/mysql/debian.cnf" ]]; then
            # adjust /etc/mysql/debian.cnf if it uses the debian-sys-maint user
            if grep -q debian-sys-maint /etc/mysql/debian.cnf; then
                sed -i "1a # This file has been automatically adjusted by TKLBAM" /etc/mysql/debian.cnf
                sed -i "\|debian-sys-maint|s|||g; \|^password|s|^|#|; \|^basedir|s|^|#|;" /etc/mysql/debian.cnf
            fi
        fi
        # force upgrade to recreate the mysql.global_priv table and convert mysql.user from table to view
        mariadb-upgrade --force
        
        # kill mariadb background process and start service
        pkill mariadb || true
        systemctl start mariadb
        info "MariaDB restarted"
        info "Everything should be good to go"
    fi

elif [[ "$op" == "backup" ]]; then
    info quiet "nothing to do when backing up"
else
    fatal "bad hook invocation"
fi
