#!/usr/bin/bash
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 grommunio GmbH

set -e

PROGNAME="`basename $0`"
ADMIN_PASSWORD=''
AUTO_CONFIG='false'
KCADM='/opt/grommunio-keycloak/bin/kcadm.sh'
ADAPTOR_SCRIPT_DIR='/usr/share/grommunio-auth/adaptor-config-scripts'
ADAPTOR_CONFIG_DIR='/var/cache/grommunio-auth/adaptor-config'
GWEB_ADAPTOR_CONFIG='keycloak-grommunio-web.json'
GWEB_ADAPTOR_PUBKEY='keycloak-grommunio-web.bearer_pubkey'
GWEB_ADAPTOR_SCRIPT="${ADAPTOR_SCRIPT_DIR}/setup-gk-app-g-web"
GWEB_ADAPTOR_DEL_SCRIPT="${ADAPTOR_SCRIPT_DIR}/delete-gk-app-g-web"
GCHAT_ADAPTOR_CONFIG='keycloak-grommunio-chat.json'
GCHAT_ADAPTOR_PUBKEY='keycloak-grommunio-chat.bearer_pubkey'
GCHAT_ADAPTOR_SCRIPT="${ADAPTOR_SCRIPT_DIR}/setup-gk-app-g-chat"
GCHAT_ADAPTOR_DEL_SCRIPT="${ADAPTOR_SCRIPT_DIR}/delete-gk-app-g-chat"

KEYCLOAK_SERVER='http://127.0.0.1:9080/auth'
KEYCLOAK_LISTEN_PORT='9080'
ADAPTOR_CONFIG_AGE=480  # minutes

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


# calc_keycloak_server uses the keycloak templates
SHARED_TEMPLATES='
shared/grommunio/auto-config
shared/grommunio/admin-password
shared/grommunio/admin-password-again
shared/grommunio/admin-password-mismatch
shared/grommunio/admin-password-must-enter
shared/grommunio/site-fqdn
shared/grommunio-keycloak/endpoint-url
shared/grommunio-keycloak/listen-address
shared/grommunio-web/endpoint-url
shared/grommunio-chat/endpoint-url
'

configure_auth () {
	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"
	[ -z "$ADMIN_PASSWORD" ] && return 0

	calc_keycloak_server

	# Wait for keycloak to become available
        while ! ss -ltnH "( sport = :${KEYCLOAK_LISTEN_PORT} )" | grep "$KEYCLOAK_LISTEN_PORT" -q ; do
                sleep 1
        done
        sleep 3

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local BOOTSTRAP=0
	local REALM_ID=$(${KCADM} get realms/grommunio --fields id --format csv --noquotes 2>/dev/null)
	if [ -z "$REALM_ID" ]; then
		local CREALM_ID=$(${KCADM} create realms -i -s realm=grommunio -s enabled=true) 
		REALM_ID=$(${KCADM} get realms/grommunio --fields id --format csv --noquotes 2>/dev/null)
		BOOTSTRAP=1
	fi
	${KCADM} update realms/grommunio -s rememberMe=true -s ssoSessionMaxLifespanRememberMe=2592000
	${KCADM} update realms/grommunio -s "loginTheme=grommunio"

	local COMPONENT_IDS=$($KCADM get components -r grommunio --fields id,name,providerType --format csv --noquotes | fgrep grommunio |fgrep 'org.keycloak.storage.UserStorageProvider' |cut -d ',' -f 1)
	if [ -z "$COMPONENT_IDS" ]; then
		${KCADM} create components \
			-r grommunio \
			-s name="grommunio" \
			-s providerId="grommunio" \
			-s providerType="org.keycloak.storage.UserStorageProvider" \
			-s parentId="$REALM_ID" \
			-s 'config.enabled=["true"]' \
			-s 'config.cachePolicy=["DEFAULT"]'
	fi

	# Set up client scope
	local TMPL_DIR="/usr/share/grommunio-auth/templates"
	local tmpdir=`mktemp -d`
	local CLIENT_SCOPE_JSON='/etc/grommunio-auth/grommunio-client-scope.json'
	local TMP_CLIENT_SCOPE_JSON="${tmpdir}/grommunio-client-scope.json"
	esh -o "$TMP_CLIENT_SCOPE_JSON" "${TMPL_DIR}/grommunio-client-scope.json.esh"
	ucf --three-way --debconf-ok -Z "$TMP_CLIENT_SCOPE_JSON" "$CLIENT_SCOPE_JSON"
	ucfr grommunio-auth "$CLIENT_SCOPE_JSON"

	local CSID=$($KCADM get client-scopes -r grommunio --fields id,name --format csv --noquotes|grep grommunio-client|cut -d ',' -f 1)
	if [ -z "$CSID" ]; then
#		CSID=$($KCADM create client-scopes -r grommunio -i \
#			-s name="grommunio-client" \
#			-s description="Grommunio Client scope" \
#			-s protocol="openid-connect")
		$KCADM create "client-scopes" -x -r grommunio -f "$CLIENT_SCOPE_JSON"
	fi
	#$KCADM update "client-scopes/${CSID}" -x -r grommunio -f "$CLIENT_SCOPE_JSON"

	# clean up
	rm -rf "$tmpdir"

	if [ $BOOTSTRAP -eq 1 ]; then
		sleep 3
		# Run g-web client config if client on this system
		[ -x "$GWEB_ADAPTOR_SCRIPT" ] && client_web
		[ -x "$GCHAT_ADAPTOR_SCRIPT" ] && client_chat
	fi

}


delete_auth () {
	# If client(s) installed on this system, remove them first
	[ -x "$GWEB_ADAPTOR_DEL_SCRIPT" ] && delete_web
	[ -x "$GCHAT_ADAPTOR_DEL_SCRIPT" ] && delete_chat

	calc_keycloak_server

	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local REALM_ID=$(${KCADM} get realms/grommunio --fields id --format csv --noquotes 2>/dev/null)
	if [ -n "$REALM_ID" ]; then
		${KCADM} delete realms/grommunio
	fi
	# Clean up any cached export files
	rm -f ${ADAPTOR_CONFIG_DIR}/* || true
	rm -f ${ADAPTOR_CONFIG_DIR}/* || true
}

client_web () {
	calc_keycloak_server

	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"
	
	local WEB_ENDPOINT_URL='127.0.0.1'
	local WEB_ENDPOINT_FURL=''
	local WEB_SCHEME=''
	local WEB_FQDN=''
	local WEB_PORT=''
	local WEB_BASE_PATH=''
	db_get shared/grommunio/site-fqdn
	[ -n "$RET" ] && WEB_ENDPOINT_URL="$RET"
	db_get shared/grommunio-web/endpoint-url
	[ -n "$RET" ] && WEB_ENDPOINT_URL="$RET"
	if echo "$WEB_ENDPOINT_URL" | grep -qP '^[^/]+$'; then
		WEB_ENDPOINT_URL="https://${WEB_ENDPOINT_URL}/web"
	fi
	WEB_SCHEME=$(trurl "$WEB_ENDPOINT_URL" --get '{scheme}')
	WEB_FQDN=$(trurl "$WEB_ENDPOINT_URL" --get '{host}')
        WEB_PORT=$(trurl "$WEB_ENDPOINT_URL" --get '{port}')
	WEB_BASE_PATH=$(trurl "$WEB_ENDPOINT_URL" --get '{path}')
	[ "$WEB_BASE_PATH" = '/' ] && WEB_BASE_PATH=''
	if [ "$WEB_PORT" = '' ]; then
		[ "$WEB_SCHEME" = 'http' ] && WEB_PORT='80'
		[ "$WEB_SCHEME" = 'https' ] && WEB_PORT='443'
	fi
	WEB_ENDPOINT_FURL="${WEB_SCHEME}://${WEB_FQDN}:${WEB_PORT}${WEB_BASE_PATH}"

	# Set up client config
	local TMPL_DIR="/usr/share/grommunio-auth/templates"
	local tmpdir=`mktemp -d`
	local CLIENT_WEB_JSON='/etc/grommunio-auth/grommunio-client-web.json'
	local TMP_CLIENT_WEB_JSON="${tmpdir}/grommunio-client-web.json"
	esh -o "$TMP_CLIENT_WEB_JSON" "${TMPL_DIR}/grommunio-client-web.json.esh" \
		endpoint_url="$WEB_ENDPOINT_URL" endpoint_furl="$WEB_ENDPOINT_FURL"
	ucf --three-way --debconf-ok -Z "$TMP_CLIENT_WEB_JSON" "$CLIENT_WEB_JSON"
	ucfr grommunio-auth "$CLIENT_WEB_JSON"

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local CID=$(${KCADM} get clients -r grommunio --fields id,clientId --format csv --noquotes 2>/dev/null | grep grommunio-web | cut -d ',' -f 1)
	if [ -z "$CID" ]; then
		CID=$(${KCADM} create clients -r grommunio -i -f "$CLIENT_WEB_JSON")
	fi

	local OLD_UMASK=`umask`
	umask '0027'
	${KCADM} get clients/${CID}/installation/providers/keycloak-oidc-keycloak-json -r grommunio |sed -e 's#http#https#' -e 's#:9080##' > "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_CONFIG}"
	umask "$OLD_UMASK"

	unset http_proxy https_proxy
	echo "-----BEGIN PUBLIC KEY-----" > "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_PUBKEY}"
	echo "$(curl -s "${KEYCLOAK_SERVER}/realms/grommunio" | jq -r .public_key)" >> "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_PUBKEY}"
	echo "-----END PUBLIC KEY-----" >> "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_PUBKEY}"

	rm -rf "$tmpdir"

	# Run g-web adaptor config script if present
	[ -x "$GWEB_ADAPTOR_SCRIPT" ] && "$GWEB_ADAPTOR_SCRIPT"

	return 0
}

delete_web () {
	calc_keycloak_server

	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local CID=$(${KCADM} get clients -r grommunio --fields id,clientId --format csv --noquotes 2>/dev/null | grep grommunio-web | cut -d ',' -f 1)
	if [ -n "$CID" ]; then
		${KCADM} delete "clients/${CID}" -r grommunio
	fi
	# Clean up any cached export files
	rm -f "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_CONFIG}" || true
	rm -f "${ADAPTOR_CONFIG_DIR}/${GWEB_ADAPTOR_PUBKEY}" || true
	
	# Run g-web adaptor config script if present
	[ -x "$GWEB_ADAPTOR_DEL_SCRIPT" ] && "$GWEB_ADAPTOR_DEL_SCRIPT"

}

client_chat () {
	calc_keycloak_server

	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"
	
	local CHAT_ENDPOINT_URL='127.0.0.1'
	local CHAT_ENDPOINT_FURL=''
	local CHAT_SCHEME=''
	local CHAT_FQDN=''
	local CHAT_PORT=''
	local CHAT_BASE_PATH=''
	db_get shared/grommunio/site-fqdn
	[ -n "$RET" ] && CHAT_ENDPOINT_URL="$RET"
	db_get shared/grommunio-chat/endpoint-url
	[ -n "$RET" ] && CHAT_ENDPOINT_URL="$RET"
	if echo "$CHAT_ENDPOINT_URL" | grep -qP '^[^/]+$'; then
		CHAT_ENDPOINT_URL="https://${CHAT_ENDPOINT_URL}/chat"
	fi
	CHAT_SCHEME=$(trurl "$CHAT_ENDPOINT_URL" --get '{scheme}')
	CHAT_FQDN=$(trurl "$CHAT_ENDPOINT_URL" --get '{host}')
        CHAT_PORT=$(trurl "$CHAT_ENDPOINT_URL" --get '{port}')
	CHAT_BASE_PATH=$(trurl "$CHAT_ENDPOINT_URL" --get '{path}')
	[ "$CHAT_BASE_PATH" = '/' ] && CHAT_BASE_PATH=''
	if [ "$CHAT_PORT" = '' ]; then
		[ "$CHAT_SCHEME" = 'http' ] && CHAT_PORT='80'
		[ "$CHAT_SCHEME" = 'https' ] && CHAT_PORT='443'
	fi
	CHAT_ENDPOINT_FURL="${CHAT_SCHEME}://${CHAT_FQDN}:${CHAT_PORT}${CHAT_BASE_PATH}"

	# Set up client config
	local TMPL_DIR="/usr/share/grommunio-auth/templates"
	local tmpdir=`mktemp -d`
	local CLIENT_CHAT_JSON='/etc/grommunio-auth/grommunio-client-chat.json'
	local TMP_CLIENT_CHAT_JSON="${tmpdir}/grommunio-client-chat.json"
	esh -o "$TMP_CLIENT_CHAT_JSON" "${TMPL_DIR}/grommunio-client-chat.json.esh" \
		endpoint_url="$CHAT_ENDPOINT_URL" endpoint_furl="$CHAT_ENDPOINT_FURL"
	ucf --three-way --debconf-ok -Z "$TMP_CLIENT_CHAT_JSON" "$CLIENT_CHAT_JSON"
	ucfr grommunio-auth "$CLIENT_CHAT_JSON"

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local CID=$(${KCADM} get clients -r grommunio --fields id,clientId --format csv --noquotes 2>/dev/null | grep grommunio-chat | cut -d ',' -f 1)
	if [ -z "$CID" ]; then
		CID=$(${KCADM} create clients -r grommunio -i -f "$CLIENT_CHAT_JSON")
	fi

	local OLD_UMASK=`umask`
	umask '0027'
	${KCADM} get clients/${CID}/installation/providers/keycloak-oidc-keycloak-json -r grommunio |sed -e 's#http#https#' -e 's#:9080##' > "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_CONFIG}"
	umask "$OLD_UMASK"

	unset http_proxy https_proxy
	echo "-----BEGIN PUBLIC KEY-----" > "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_PUBKEY}"
	echo "$(curl -s "${KEYCLOAK_SERVER}/realms/grommunio" | jq -r .public_key)" >> "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_PUBKEY}"
	echo "-----END PUBLIC KEY-----" >> "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_PUBKEY}"

	rm -rf "$tmpdir"

	# Run g-chat adaptor config script if present
	[ -x "$GCHAT_ADAPTOR_SCRIPT" ] && "$GCHAT_ADAPTOR_SCRIPT"

	return 0
}

delete_chat () {
	calc_keycloak_server

	db_get shared/grommunio/admin-password
	ADMIN_PASSWORD="$RET"

	${KCADM} config credentials \
  		--server "${KEYCLOAK_SERVER}" --realm master --user admin --password "${ADMIN_PASSWORD}"
	local CID=$(${KCADM} get clients -r grommunio --fields id,clientId --format csv --noquotes 2>/dev/null | grep grommunio-chat | cut -d ',' -f 1)
	if [ -n "$CID" ]; then
		${KCADM} delete "clients/${CID}" -r grommunio
	fi
	# Clean up any cached export files
	rm -f "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_CONFIG}" || true
	rm -f "${ADAPTOR_CONFIG_DIR}/${GCHAT_ADAPTOR_PUBKEY}" || true
	
	# Run g-web adaptor config script if present
	[ -x "$GCHAT_ADAPTOR_DEL_SCRIPT" ] && "$GCHAT_ADAPTOR_DEL_SCRIPT"

}

clean_adaptor_config () {
	# Remove all files in any tree
	find "${ADAPTOR_CONFIG_DIR}" -mmin "+${ADAPTOR_CONFIG_AGE}" -type f -print0 | xargs -0r /usr/bin/shred -u || true
	# Remove any directories
	find "${ADAPTOR_CONFIG_DIR}" -mmin "+${ADAPTOR_CONFIG_AGE}" -type d -print0 | grep -zv "^${ADAPTOR_CONFIG_DIR}\$" | xargs -0r /usr/bin/rm -rf || true
	return 0
}

case "$PROGNAME" in
	setup-grommunio-auth)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		configure_auth configure ${ARGS}
		;;
	delete-grommunio-auth)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		delete_auth
		;;
	setup-gk-client-web)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		client_web
		;;
	delete-gk-client-web)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		delete_web
		;;
	setup-gk-client-chat)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		client_chat
		;;
	delete-gk-client-chat)
		check_if_root
		start_debconf -x grommunio-auth "$@"
		delete_chat
		;;
	clean-gk-adaptor-config)
		check_if_root
		clean_adaptor_config
		;;
esac


