#!/bin/bash
#
# Univention open-xchange integration
#
# Copyright (C) 2008-2017 Univention GmbH <http://www.univention.de/>
#
# and
#     iKu Systems & Services GmbH & Co. KG
#
# http://www.iku-systems.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

. /usr/share/univention-ox/ox-lib.sh || exit 1
. /usr/share/univention-lib/all.sh || die "Failed to load all.sh library."

eval "$(univention-config-registry shell)"

main () {
	check_params "$@"
	check_join
	check_context
	setup_vars
	echo "First context in UCS Domain, setting default entries."
	register_service_ox
	update_ea_defaults

	prepare_oxadmin_secret

	if list_context
	then
		echo "Context '$OXCONTEXTNAME' already exists; re-using."
	elif create_context
	then
		echo "$OXCONTEXTNAME has been created successfully."
	else
		die 1 "Failed to create context '$OXCONTEXTNAME'."
	fi

	ox_restart ||
		die "Open-Xchange daemon failed to restart."

	register_oxcontext

	register_oxdomain
	update_context_domain

	register_oxadmin

	setup_listener
	wait_replication ||
		echo "oxadmin not found yet... going on..." >&2
	echo "Done."
	sleep 5s

	update_context_admin
}

check_params () {
	BINDARGS=()
	while [ $# -ge 1 ]
	do
		case "$1" in
		--help|-h) usage ; exit 0 ;;
		--context) CONTEXTNUM="${2:?missing context number}" ; shift 2 ;;
		--bind*) BINDARGS+=("$1" "$2") ; shift 2 ;;
		*) die 2 "Unknown option: $1" ;;
		esac
	done
	case "$server_role" in
	domaincontroller_*) ;;
	memberserver) [ -n "$BINDARGS" ] || die 2 "Missing LDAP credentials." ;;
	*) die "Unknown server role '$server_role'." ;;
	esac
}
usage () {
	cat <<-__USAGE__
	usage: ${0##*/} [options]

	Options:
	 --help, -h           Show this help
	 --context NUM        Overwrite default context number (default: 10)
	 --bind* STR          LDAP Bind credentials
	__USAGE__
}

check_join () {
	msg "Checking join status..."
	[ -e "/usr/share/univention-join/.joined" ] ||
		die "The server has not joined yet"
}
check_context () {
	msg "Checking for Open-Xchange context in LDAP..."
	OXCONTEXTNAME="context${CONTEXTNUM:=10}"
	if ox_context_check_ldap "$OXCONTEXTNAME"
	then
		echo "New context '$OXCONTEXTNAME' will be created." >&2
	else
		echo "Existing context '$OXCONTEXTNAME' will be re-used." >&2
	fi
}

register_service_ox () {
	msg "Registering Open-Xchange service on host in LDAP..."
	ucs_addServiceToLocalhost "ox" ${BINDARGS+"${BINDARGS[@]}"} ||
		die "Failed to register service 'ox' on host in LDAP."
}

update_ea_defaults () {
	# Note: default values at extended_attributes of usertemplates do not have any effect while creating new users! (Bug #22326)
	msg "Updating default values in LDAP..."
	univention-directory-manager settings/extended_attribute modify ${BINDARGS+"${BINDARGS[@]}"} \
		--dn "cn=oxLanguage,cn=open-xchange,cn=custom attributes,cn=univention,$ldap_base" \
		--set default="$OXLANG"
	univention-directory-manager settings/extended_attribute modify ${BINDARGS+"${BINDARGS[@]}"} \
		--dn "cn=oxTimeZone,cn=open-xchange,cn=custom attributes,cn=univention,$ldap_base" \
		--set default="$OXTIMEZONE"
}

register_oxdomain () {
	msg "Registering Open-Xchange mail domain in LDAP..."
	local res
	univention-directory-manager oxmail/oxdomain create ${BINDARGS+"${BINDARGS[@]}"} \
		--ignore_exists \
		--position "cn=domain,cn=mail,$ldap_base" \
		--set name="$CONTEXTDOMAIN" \
		--set oxImapServer="$OXIMAPSERVER" \
		--set oxContextName="$OXCONTEXTNAME" && return 0
	res="$(univention-directory-manager oxmail/oxdomain list ${BINDARGS+"${BINDARGS[@]}"} \
		--filter "(&(name=$CONTEXTDOMAIN)(!(&(oxImapServer=$OXIMAPSERVER)(oxContextName=$OXCONTEXTNAME))))" |
		sed -e '1d;/: None$/d')"
	[ -z "$res" ] && return 0
	exec >&2
	echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
	echo "The mail domain '$CONTEXTDOMAIN' is currently registered as:"
	echo "$res"
	echo
	echo "If you're sure the mail domain is no longer used like this, remove the"
	echo "mail domain or change the IMAP server of the mail domain to point to"
	echo "this host through UMC or on the command line using"
	echo
	echo "  univention-directory-manager oxmail/oxdomain modify \\"
	ox_print_bind '    %s \\\n'
	echo "    --dn 'cn=$CONTEXTDOMAIN,cn=domain,cn=mail,$ldap_base' \\"
	echo "    --set oxImapServer='$OXIMAPSERVER'"
	echo
	echo "After that re-run the join script through UMC or on the command line using"
	echo
	echo "  univention-run-join-scripts"
	echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
	die "Aborting now."
}

setup_listener () {
	local MODULES="/usr/lib/univention-directory-listener/system"
	ln -s -f -t "$MODULES" /usr/share/univention-ox/listener/ox-groups.py
	ln -s -f -t "$MODULES" /usr/share/univention-ox/listener/ox-resource.py
	ln -s -f -t "$MODULES" /usr/share/univention-ox/listener/ox-user.py
	deb-systemd-invoke restart univention-directory-listener.service
}

register_oxadmin () {
	msg "Creating context administrator in LDAP..."
	univention-directory-manager users/user create ${BINDARGS+"${BINDARGS[@]}"} \
		--ignore_exists \
		--position "cn=users,$ldap_base" \
		--set username="$CONTEXTADMIN" \
		--set lastname="Admin" \
		--set firstname="OX" \
		--set password="$CONTEXTADMINPW" \
		--set overridePWLength=1 \
		--set mailPrimaryAddress="$CONTEXTADMINMAIL" \
		--set oxDisplayName="OX Admin" \
		--set oxAccess="premium" \
		--set oxTimeZone="$OXTIMEZONE" \
		--set oxLanguage="$OXLANG" \
		--set isOxUser=OK ||
		die "Failed to create user '$CONTEXTADMIN' in LDAP."

	univention-directory-manager users/user modify ${BINDARGS+"${BINDARGS[@]}"} \
		--dn "uid=$CONTEXTADMIN,cn=users,$ldap_base" \
		--append mailAlternativeAddress="abuse@$CONTEXTDOMAIN" \
		--append mailAlternativeAddress="postmaster@$CONTEXTDOMAIN" \
		--set overridePWLength=1 \
		--set overridePWHistory=1 \
		--set password="$CONTEXTADMINPW" ||
		die "Failed to setup user '$CONTEXTADMIN' in LDAP."
}

wait_replication () {
	msg "Waiting for replication..."
	local max=${1:-600} step=${2:-5} rem
	printf "Waiting up to %ds for user '$CONTEXTADMIN' to be replicated..." "$max" >&2
	for ((rem=max;rem>0;rem+=-step))
	do
		# FIXME: Pass "$@" to univention-ldapsearch
		[ -n "$(univention-ldapsearch -LLL "(uid=$CONTEXTADMIN)" dn)" ] &&
			{ echo >&2 ; return 0 ; }
		sleep "$step"
		printf "%d " "$rem" >&2
	done
	echo "FAILED" >&2
	return 1
}

update_context_domain () {
	msg "Updating Open-Xchange mail context..."
	/usr/sbin/wait_for_ox_server
	ox_retry \
	"$OXADMINPATH/changecontext" \
		--adminuser "$OXADMINMASTER" \
		--adminpass "$OXADMINMASTERPW" \
		--contextid "$CONTEXTNUM" \
		--addmapping "$CONTEXTDOMAIN"
}
update_context_admin () {
	msg "Updating Open-Xchange administrator..."
	/usr/sbin/wait_for_ox_server
	ox_retry \
	"$OXADMINPATH/changeuser" \
		--adminuser "$CONTEXTADMIN" \
		--adminpass "$CONTEXTADMINPW" \
		--contextid "$CONTEXTNUM" \
		--username "$CONTEXTADMIN"  \
		--aliases "$CONTEXTADMINMAIL,abuse@$CONTEXTDOMAIN,postmaster@$CONTEXTDOMAIN"  \
		--email "$CONTEXTADMINMAIL"  \
		--email1 "$CONTEXTADMINMAIL"  \
		--smtpserver localhost  \
		--imapserver "$OXIMAPSERVER"  \
		--imaplogin "$CONTEXTADMINMAIL"  \
		--defaultsenderaddress "$CONTEXTADMINMAIL"  \
		--language "$OXLANG"  \
		--timezone "$OXTIMEZONE"  \
		--mailenabled true  \
		--access-contacts on  \
		--access-webmail on  \
		--access-calendar on  \
		--access-delegate-tasks on  \
		--access-tasks on  \
		--access-edit-public-folder on  \
		--access-infostore on  \
		--access-read-create-shared-Folders on  \
		--access-ical on  \
		--access-vcard on  \
		--access-webdav on  \
		--access-webdav-xml on  \
		--access-edit-resource on  \
		--access-global-address-book-disabled off ||
		die "Failed to make user '$CONTEXTADMIN' admin."
}


main "$@"
exit $?
