#! /bin/bash

DBNAME_ATTRIBUTE="report_db_name"
DBPROVIDER_ATTRIBUTE="externaldb_provider"

RHN_CONF="/etc/rhn/rhn.conf"
INTERACTIVE=1
INTERACTIVE_RETRIES=3

if [ 0$UID -gt 0 ]; then
    echo Run as root.
    exit 1
fi

print_help() {
    cat <<HELP
usage: uyuni-setup-reportdb-user [options]

options:
  --help 
            show this help message and exit
  --non-interactive
            Switches to non-interactive mode
  --dbuser=DBUSER
            Report DB User
  --dbpassword=DBPASSWORD
            Report DB Password
  --add
            Add the new user (case insensitive)
  --delete
            Delete the user (case insensitive)
  --modify
            Set a new password (case insensitive)

HELP
    exit 1
}

default_or_input() {
    local MSG="$1"
    local VARIABLE="$2"
    local DEFAULT="$3"
    local SILENT="$4"

    local INPUT
    local CURRENT_VALUE=${!VARIABLE}
    #in following code is used not so common expansion
    #var_a=${var_b:-word}
    #which is like: var_a = $var_b ? word
    DEFAULT=${CURRENT_VALUE:-$DEFAULT}
    local VARIABLE_ISSET=$(set | grep "^$VARIABLE=")

    echo -n "$MSG [$DEFAULT]: "
    if [ "$INTERACTIVE" = "1" ] &&  [ -z "$VARIABLE_ISSET" ]; then
        if [ "$SILENT" = 1 ]; then
          read -sr INPUT
        else
          read -r INPUT
        fi
    elif [ -z "$VARIABLE_ISSET" ]; then
        echo "$DEFAULT"
    else
        DEFAULT=${!VARIABLE}
        echo "$DEFAULT"
    fi
    if [ -z "$INPUT" ]; then
        if [ "$DEFAULT" = "y/N" ] || [ "$DEFAULT" = "Y/n" ]; then
            INPUT=$(yes_no "$DEFAULT")
        else
            INPUT="$DEFAULT"
        fi
    fi
    ACCUMULATED_ANSWERS+=$(printf "\n%q=%q" "$VARIABLE" "${INPUT:-$DEFAULT}")
    eval "$(printf "%q=%q" "$VARIABLE" "$INPUT")"
}

parse_password() {
  for i in $(seq $INTERACTIVE_RETRIES) ; do
    echo -n "Password: "
    read -sr DBPASSWORD
    echo
    echo -n "Password (again): "
    read -sr DBPASSWORD2
    echo
    [ "$DBPASSWORD" = "$DBPASSWORD2" ] && break
    echo "The password and confirmation password do not match. Retry ($i/$INTERACTIVE_RETRIES)"
    unset DBPASSWORD
  done
}

set_value() {
    local OPTION="$1"
    local VAR="$2"
    local ARG="$3"
    [[ "$ARG" =~ ^- ]] \
        && echo "$0: option $OPTION requires argument! Use answer file if your argument starts with '-'." \
        && print_help
    eval "$(printf "%q=%q" "$VAR" "$ARG")"
}

parse_properties() {
    ATTRIBUTE="$1"
    VAR="$2"
    VALUE=$(grep "^$ATTRIBUTE" $RHN_CONF |cut -d'=' -f2 | tail -n1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | tr -d '\n')
    eval "$(printf "%q=%q" "$VAR" "$VALUE")"
}

parse_properties $DBNAME_ATTRIBUTE DBNAME
parse_properties $DBPROVIDER_ATTRIBUTE DBPROVIDER

if [ -z $DBNAME ]; then
  echo "$DBNAME_ATTRIBUTE is missing. Exit"
  exit 1
fi

OPTS=$(getopt --longoptions=help,non-interactive,add,delete,modify,action:,dbuser:,dbpassword: -n '${0##*/}' -- h "$@")

if [ $? != 0 ] ; then
    print_help
fi

# It is getopt's responsibility to make this safe
eval set -- "$OPTS"

ACTION_COUNT=0
while : ; do
    case "$1" in
        --help|-h)  print_help;;
        --non-interactive) INTERACTIVE=0;;
        --dbuser) set_value "$1" DBUSER "$2"; shift;;
        --dbpassword) set_value "$1" DBPASSWORD "$2"; shift;;
        --add) ACTION="a" ACTION_COUNT=$((ACTION_COUNT+1)) ;;
        --delete) ACTION="d" ACTION_COUNT=$((ACTION_COUNT+1)) ;;
        --modify) ACTION="m" ACTION_COUNT=$((ACTION_COUNT+1)) ;;
        --) shift;
            if [ $# -gt 0 ] ; then
                echo "Error: Extra arguments found: $@"
                print_help
                exit 1
            fi
            break;;
        *) echo Error: Invalid option $1; exit 1;;
    esac
    shift
done

if [ "$INTERACTIVE" = "1" ] ; then
  echo "Report DB Name is: $DBNAME"
  for i in $(seq $INTERACTIVE_RETRIES) ; do
    default_or_input "[a]dd/[m]odify/[d]elete user (case insensitive). Default is " ACTION 'm'
      case "$ACTION" in
        a|m|d)
        break
        ;;
        *)
          echo "Invalid input. Please [a]dd/[m]odify/[d]elete"
          unset ACTION
        ;;
      esac
  done

  if [ -z $ACTION ]; then
    echo "Invalid input. Exit"
    exit 1
  fi

  default_or_input "User:" DBUSER ''
  DBUSER=$(echo $DBUSER | tr '[:upper:]' '[:lower:]')
  
  if [ "$ACTION" != "d" ]; then
    parse_password
    if [ -z $DBPASSWORD ]; then
      echo "Invalid password. Exit"
      exit 1
    fi
  fi

  default_or_input "Confirm? [y/n]" CONFIRM 'y'

  if [ "$CONFIRM" != "y" ]; then
    echo "Answer is not y. Exit"
    exit 0
  fi

else ### INTERACTIVE=0
  if [ "$ACTION_COUNT" != "1" ] ; then
    echo "Please provide only one action"
    exit 1
  fi
  
  if [ -z $DBUSER ]; then
    echo "User is missing. Exit"
    exit 1
  fi
  
  if [ -z $DBPASSWORD ]; then
    echo "Password is missing. Exit"
    exit 1
  fi

fi

echo $EXTERNAL
ADMIN_USERS=$(echo "SELECT usename FROM pg_catalog.pg_user WHERE usesuper='t' " | spacewalk-sql -select-mode - | tail -n +3 | head -n -2 | tr '[:upper:]' '[:lower:]')

for USER in $ADMIN_USERS; do
    if [ "$DBUSER" == "$USER" ]; then
        echo "This script is not allowed to change $USER, because it's an admin (only read-only user allowed)"
        exit 1
    fi
done

QUERY=""
case "$ACTION" in
  a)
    QUERY="CREATE ROLE ${DBUSER} WITH LOGIN PASSWORD '${DBPASSWORD}' NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION;
      GRANT CONNECT ON DATABASE ${DBNAME} TO ${DBUSER};
      GRANT USAGE ON SCHEMA public TO ${DBUSER};
      GRANT SELECT ON ALL TABLES IN SCHEMA public TO ${DBUSER};
      GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO ${DBUSER};"
  ;;
  m)
    QUERY="ALTER USER ${DBUSER} PASSWORD '${DBPASSWORD}';"
  ;;
  d)
    if [[ -n $DBPROVIDER && "${DBPROVIDER,,}" == "aws" ]] ; then
      QUERY="REVOKE SELECT ON ALL SEQUENCES IN SCHEMA public FROM ${DBUSER};
        REVOKE ALL ON ALL TABLES IN SCHEMA public FROM ${DBUSER};
        REVOKE ALL ON SCHEMA public FROM ${DBUSER};
        REVOKE CONNECT ON DATABASE ${DBNAME} FROM ${DBUSER};
        DROP ROLE ${DBUSER};"
    else
      QUERY="DROP OWNED BY ${DBUSER}; DROP ROLE ${DBUSER};"
    fi
  ;;
esac

echo $QUERY | spacewalk-sql --reportdb --select-mode -
