#!/bin/bash

set -e

PROGNAME="`basename $0`"
BOOTSTRAPPED=0
ADMIN_PASSWORD=''
TMP_ADMIN_PASSWORD=''
LISTEN_HOST=''
LISTEN_PORT=''
AUTO_CONFIG='false'

. /usr/share/grommunio-pkg-bits/scripts/setup-include.sh

SHARED_TEMPLATES='
shared/grommunio/auto-config
shared/grommunio/admin-password
shared/grommunio/admin-password-again
shared/grommunio/admin-password-mismatch
shared/grommunio/admin-password-display
shared/grommunio/site-fqdn
shared/grommunio-keycloak/endpoint-url
shared/grommunio-keycloak/listen-address
shared/grommunio-keycloak/allow-from-networks
'
PKG_TEMPLATES='
grommunio-keycloak/internal/db-purge
'

configure_keycloak () {
	# Detect if Keycloak already set up
	db_get grommunio-keycloak/db/dbname || true
	local TEST_DB_NAME="$RET"
	if [ -n "$TEST_DB_NAME" ]; then
		[ -f "/etc/dbconfig-common/grommunio-keycloak.conf" ] && BOOTSTRAPPED=1
	fi

        # Create and intiliaze DB
        . /usr/share/dbconfig-common/dpkg/postinst.mysql
        # you can overwrite the default database encoding, LC_COLLATE and LC_CTYPE
        dbc_mysql_createdb_encoding="UTF8"
        dbc_sql_substitutions="yes"
        dbc_go grommunio-keycloak "$@"

        # Source db config
        local SOURCED_DB_CONFIG=0
        if [ -r /etc/dbconfig-common/grommunio-keycloak.conf ]; then
                . /etc/dbconfig-common/grommunio-keycloak.conf && SOURCED_DB_CONFIG=1

                # Fix purge flag - this is created by dbconfig-mysql
		local DB_PURGE=''
                if db_get grommunio-keycloak/internal/db-purge; then
                	DB_PURGE="$RET"
		fi
                [ -z "$DB_PURGE" ] && DB_PURGE="true"
                db_set grommunio-keycloak/purge "$DB_PURGE"
        fi

	# grommnuio-keycloak.conf
	local LISTEN_ADDR='127.0.0.1:8090'
	local ENDPOINT_URL='localhost'
	local FQDN=''
	local BASE_PATH=''
	local SCHEME=''
	db_get shared/grommunio/site-fqdn
	[ -n "$RET" ] && ENDPOINT_URL="$RET"
	db_get shared/grommunio-keycloak/endpoint-url
	[ -n "$RET" ] && ENDPOINT_URL="$RET"
	if echo "$ENDPOINT_URL" | grep -qP '^[^/]+$'; then
		ENDPOINT_URL="https://${ENDPOINT_URL}/auth"
	fi
	BASE_PATH=$(trurl "$ENDPOINT_URL" --get '{path}')
	[ "$BASE_PATH" = '/' ] && BASE_PATH=''
	FQDN=$(trurl "$ENDPOINT_URL" --get '{host}')
	SCHEME=$(trurl "$ENDPOINT_URL" --get '{scheme}')
	db_get shared/grommunio-keycloak/listen-address
	local LISTEN_ADDR="$RET"
	# Use trurl to get listen host and port
	if echo "$LISTEN_ADDR" | grep -qP '^[^/]+$'; then
		local LISTEN_URL="http://${LISTEN_ADDR}"
	fi
	LISTEN_HOST=$(trurl "$LISTEN_URL" --get '{host}')
	LISTEN_PORT=$(trurl "$LISTEN_URL" --get '{port}')
	[ "$LISTEN_HOST" = '127.0.0.1' ] && LISTEN_HOST='localhost'
	[ "$LISTEN_HOST" = '[::1]' ] && LISTEN_HOST='localhost6'

	local TMPL_DIR="/usr/share/grommunio-keycloak/templates"
	local tmpdir=`mktemp -d`
	# manipulate umask so passwords are never exposed to users
	local OLD_UMASK=`umask`
	umask 0027

	# Process keycloak.conf
	local KEYCLOAK_CONF="/etc/grommunio-keycloak/keycloak.conf"
	local TMP_KEYCLOAK_CONF="${tmpdir}/keycloak.conf"
	local DB_TYPE='mariadb'
	local DB_HOST='localhost'
	local DB_PORT='3306'
	local DB_NAME='grommunio_keycloak'
	local DB_USER='grommunio_keycloak'
	local DB_PASSWORD='KnockKnock'
	if [ $SOURCED_DB_CONFIG -eq 1 ]; then
		[ "$dbc_dbtype" = 'mysql' ] && DB_TYPE='mariadb'
		[ "$dbc_dbtype" = 'pgsql' ] && DB_TYPE='postgres'
		DB_HOST="$dbc_dbserver"
		DB_PORT="$dbc_dbport"
		DB_NAME="$dbc_dbname"
		DB_USER="$dbc_dbuser"
		DB_PASSWORD="$dbc_dbpass"
	fi
	esh -o "$TMP_KEYCLOAK_CONF" "${TMPL_DIR}/grommunio-keycloak.conf.esh" \
		fqdn="$FQDN" db_type="$DB_TYPE" db_host="$DB_HOST" db_port="$DB_PORT" \
		db_name="$DB_NAME" db_user="$DB_USER" db_password="$DB_PASSWORD" \
		listen_host="$LISTEN_HOST" listen_port="$LISTEN_PORT" base_path="$BASE_PATH"
	# Restore original umask - finished with passwords
	umask "$OLD_UMASK"
	ucf --three-way --debconf-ok -Z "$TMP_KEYCLOAK_CONF" "$KEYCLOAK_CONF" && KEYCLOAK_RELOAD=1
	ucfr grommunio-keycloak "$KEYCLOAK_CONF"
	chown groauth:gromox "$KEYCLOAK_CONF"

	# Process nginx upstreams.d
	local NGINX_UPSTREAM="/etc/grommunio-common/nginx/upstreams.d/grommunio-auth.conf"
	local TMP_NGINX_UPSTREAM="${tmpdir}/nginx-upstream.conf"
	esh -o "$TMP_NGINX_UPSTREAM" "${TMPL_DIR}/nginx-upstream-conf.esh" \
		listen_host="$LISTEN_HOST" listen_port="$LISTEN_PORT"
	ucf --three-way --debconf-ok -Z "$TMP_NGINX_UPSTREAM" "$NGINX_UPSTREAM" && NGINX_RELOAD=1
	ucfr grommunio-keycloak "$NGINX_UPSTREAM"

	# Process nginx auth_allow.conf
	local NGINX_AUTH_ALLOW="/etc/grommunio-common/nginx/auth_allow.conf"
	local TMP_NGINX_AUTH_ALLOW="${tmpdir}/nginx-auth_allow.conf"
	db_get shared/grommunio-keycloak/allow-from-networks
	local ALLOW_FROM_NETWORKS="$RET"
	esh -o "$TMP_NGINX_AUTH_ALLOW" "${TMPL_DIR}/nginx-auth_allow-conf.esh" \
		allow_from_networks="$ALLOW_FROM_NETWORKS"
	ucf --three-way --debconf-ok -Z "$TMP_NGINX_AUTH_ALLOW" "$NGINX_AUTH_ALLOW" && NGINX_RELOAD=1
	ucfr grommunio-keycloak "$NGINX_AUTH_ALLOW"

	if [ "$AUTO_CONFIG" = true ]; then
                # Handle admin web service URL config.json
                local TMP_ADMIN_WEB_CONFIG="${tmpdir}/admin_web_config.json"
                if [ -f "$ADMIN_WEB_CONFIG" ]; then
                        jq '.authWebAddress |= "'${ENDPOINT_URL}'"' "$ADMIN_WEB_CONFIG" > "$TMP_ADMIN_WEB_CONFIG"
                        mv "$TMP_ADMIN_WEB_CONFIG" "$ADMIN_WEB_CONFIG"
                fi
	fi

	rm -rf "$tmpdir"

	if [ $BOOTSTRAPPED -eq 0 ]; then
		# Get admin password
		db_get shared/grommunio/admin-password
		ADMIN_PASSWORD="$RET"
	
		if [ "$AUTO_CONFIG" = true ]; then
			# Create TMP_ADMIN_PASSWORD
			TMP_ADMIN_PASSWORD=`randpw 16`
		else
			TMP_ADMIN_PASSWORD="$ADMIN_PASSWORD"
		fi
		TMP_ADMIN_PASSWORD="$TMP_ADMIN_PASSWORD" /opt/grommunio-keycloak/bin/kc.sh bootstrap-admin user --username temp-admin --password:env "TMP_ADMIN_PASSWORD"
	fi

}

delete_bootstrap_admin_if_exists() {
	local bootstrap_user_id
	bootstrap_user_id=$(/opt/grommunio-keycloak/bin/kcadm.sh get users -r master -q exact=true -q username='temp-admin' | jq -r '.[0].id')
	# Defensive programming
	if [ -n "$bootstrap_user_id" ]; then
		/opt/grommunio-keycloak/bin/kcadm.sh delete users/"$bootstrap_user_id" -r master
	fi
}

post_start_keycloak () {
	local admin_user_id
	[ $BOOTSTRAPPED -ne 0 ] && return 0
	[ "$AUTO_CONFIG" != 'true' ] && return 0
	if [ -z "$ADMIN_PASSWORD" -o -z "$TMP_ADMIN_PASSWORD" ]; then
		echo "${PROGNAME}: passwords must be set to proceed with admin account creation" 1>&2
		exit 5
	fi
	if [ -z "$LISTEN_HOST" -o -z "$LISTEN_PORT" ]; then
		echo "${PROGNAME}: listen address must be set to proceed with admin account creation" 1>&2
		exit 5
	fi
	while ! ss -ltnH "( sport = :${LISTEN_PORT} )" | grep "$LISTEN_PORT" -q ; do
		sleep 1
	done
	sleep 3
	/opt/grommunio-keycloak/bin/kcadm.sh config credentials \
		--realm master --user temp-admin --password "$TMP_ADMIN_PASSWORD" \
		--server "http://${LISTEN_HOST}:${LISTEN_PORT}/auth"
	admin_user_id=$(/opt/grommunio-keycloak/bin/kcadm.sh get users -r master -q exact=true -q username='admin' | jq -r '.[0].id')
	if [ "$admin_user_id"  = 'null' ]; then
		/opt/grommunio-keycloak/bin/kcadm.sh create users \
			--realm master -s username=admin -s enabled=true
		/opt/grommunio-keycloak/bin/kcadm.sh set-password \
			--realm master --username admin --new-password "$ADMIN_PASSWORD"
		/opt/grommunio-keycloak/bin/kcadm.sh add-roles \
			--uusername admin --rolename admin --rolename default-roles-master
	fi
	delete_bootstrap_admin_if_exists
	return 0
}

case "$PROGNAME" in
	setup-grommunio-keycloak)
		check_if_root

		start_debconf -x 'grommunio-keycloak' "$@"
		configure_keycloak ${ARGS}
		if test "$AUTO_CONFIG" = 'true'; then
			systemctl enable grommunio-keycloak.service
			systemctl restart grommunio-keycloak.service
		else
			STATUS=$(systemctl is-active grommunio-keycloak.service||true)
			systemctl restart grommunio-keycloak.service
		fi
		post_start_keycloak
		if test "$AUTO_CONFIG" != 'true'; then
			test "$STATUS" != 'active' && systemctl stop grommunio-keycloak.service
		fi

		;;
	clean-keycloak-db|clean-grommunio-keycloak-db)
		check_if_root
		clean_dbconfig_db -x 'grommunio-keycloak'
		;;
esac
