#!/bin/bash

# Copyright (c) Veeam Software Group GmbH

set -eE -u -o pipefail

SCRIPT_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")"); readonly SCRIPT_DIR;
source "$SCRIPT_DIR/lib/error-handle.bash"
source "$SCRIPT_DIR/lib/optparser.bash"
source "$SCRIPT_DIR/lib/verbose.bash"

setlocale en_US.utf8 || :
# shellcheck disable=SC2034
declare -A op=()
declare -A ARGS=()

optparser-init op \
    --desc "Add or modify a role in the PostgreSQL database."
optparser-addopt op --name "user" --narg 1 \
    --help "user (role) name"
optparser-addopt op -s "-o" -l "--role-option" --narg '*' \
    --add-choice SUPERUSER --add-choice NOSUPERUSER \
    --add-choice CREATEDB --add-choice NOCREATEDB \
    --add-choice CREATEROLE --add-choice NOCREATEROLE \
    --add-choice INHERIT --add-choice NOINHERIT \
    --add-choice LOGIN --add-choice NOLOGIN \
    --add-choice REPLICATION --add-choice NOREPLICATION \
    --add-choice BYPASSRLS --add-choice NOBYPASSRLS \
    --help "add role option"
optparser-addopt op -s "-p" -l "--passwd" --narg 1 \
    --help "environment variable name in which a password is stored"
optparser-addopt op -l "--nullpasswd" \
    --help "remove a role's password"
optparser-addopt op -s "-v" -l "--verbose" \
    --help "provide more detailed output"
optparser-addopt op -s "-h" -l "--help" \
    --help "show this help message and exit"
optparser-ignore-required op help
optparser-parse op ARGS "$@" || exit 1
[[ -n ${ARGS[help]:-} ]] && { optparser-help op; exit 0; }
[[ -n ${ARGS[verbose]:-} ]] && { verbose-enable; }
[[ ${ARGS[user]} =~ ^[a-z][a-z0-9_.-]{2,21}$ ]] || die "$0: invalid user name"

[[ $EUID -eq 0 ]] || die "script should be run as root"

trap-init

eval "$("$SCRIPT_DIR/pgsql-pkginfo")"
[[ -n ${VCTL_PGSQL_PSQL:-} ]] || die "failed to find psql binary"

sql=()
[[ -v "${ARGS[passwd]:-}" ]] && sql+=("\getenv passwd ${ARGS[passwd]}")
sql+=(
    'DO'
    "\$do\$"
    'BEGIN'
    "   IF not EXISTS(SELECT FROM pg_catalog.pg_roles WHERE rolname = '${ARGS[user]}')"
    "   THEN"
    "       CREATE ROLE \"${ARGS[user]}\" $(strarray-join " " "${ARGS[role-option]:-}");"
    "   ELSE"
    "       ALTER ROLE \"${ARGS[user]}\" $(strarray-join " " "${ARGS[role-option]:-}");"
    "   END IF;"
    "END"
    "\$do\$;"
)
[[ -v "${ARGS[passwd]:-}" ]] && sql+=("ALTER ROLE \"${ARGS[user]}\" WITH PASSWORD :'passwd';")
[[ -n "${ARGS[nullpasswd]:-}" ]] && sql+=("ALTER ROLE \"${ARGS[user]}\" WITH PASSWORD NULL;")

verbose-printf "%s\n" "${sql[@]}"
runuser -u postgres -- "$VCTL_PGSQL_PSQL" -A -x -q -v ON_ERROR_STOP=1 < <(printf "%s\n" "${sql[@]}")
