#!/usr/share/ucs-test/runner python2.7
## desc: Tests functionality of nested groups
## roles:
##  - domaincontroller_master
##  - domaincontroller_backup
## packages:
## - univention-admingrp-user-passwordreset
## exposure: dangerous

from __future__ import print_function
import univention.config_registry
from univention.testing.utils import fail
from univention.testing.ucr import UCSTestConfigRegistry
from univention.testing.udm import UCSTestUDM
import univention.testing.strings as uts
import univention.testing.utils as utils

default_password = 'univention'


class Account(object):

	def __init__(self, description, dn, name, password=default_password):
		self.description = description
		self.dn = dn
		self.name = name
		self.password = password

	def __str__(self):
		return '%s "%s"' % (self.description, self.name)


try:
	with UCSTestConfigRegistry() as ucr, UCSTestUDM() as udm:

		# Create new helpdesk group
		try:
			what = 'Helpdesk group'
			helpdesk_group1_dn, helpdesk_group1_name = udm.create_group()
			helpdesk_group1 = Account(what, helpdesk_group1_dn, helpdesk_group1_name)
		except Exception as exc:
			fail('Creating %s failed: %s' % (what, exc))
		else:
			print('Created %s' % (helpdesk_group1,))

		# Create new helpdesk user
		try:
			what = 'Helpdesk user'
			helpdesk_user1_dn, helpdesk_user1_name = udm.create_user()
			helpdesk_user1 = Account(what, helpdesk_user1_dn, helpdesk_user1_name)
		except Exception as exc:
			fail('Creating %s failed: %s' % (what, exc))
		else:
			print('Created %s' % (helpdesk_user1,))

		# Create new helpdesk user
		try:
			what = 'Helpdesk user'
			helpdesk_user2_dn, helpdesk_user2_name = udm.create_user()
			helpdesk_user2 = Account(what, helpdesk_user2_dn, helpdesk_user2_name)
		except Exception as exc:
			fail('Creating %s failed: %s' % (what, exc))
		else:
			print('Created %s' % (helpdesk_user2,))

		# Create new unprotected user
		try:
			what = 'Unprotected user'
			unprotected_user_dn, unprotected_user_name = udm.create_user()
			unprotected_user = Account(what, unprotected_user_dn, unprotected_user_name)
		except Exception as exc:
			fail('Creating %s failed: %s' % (what, exc))
		else:
			print('Created %s' % (unprotected_user,))

		# Add helpdesk user to helpdesk group
		try:
			what = 'helpdesk user'
			udm.modify_object('groups/group', dn=helpdesk_group1.dn, append={
				'users': [helpdesk_user1.dn]
			})
		except Exception as exc:
			fail('Adding %s to corresponding group %s failed: %s' % (helpdesk_user1, helpdesk_group1.name, exc))
		else:
			print('Added %s to corresponding group' % what)

		# Create second helpdesk group
		try:
			what = 'Helpdesk group'
			helpdesk_group2_dn, helpdesk_group2_name = udm.create_group()
			helpdesk_group2 = Account(what, helpdesk_group2_dn, helpdesk_group2_name)
		except Exception as exc:
			fail('Creating %s failed: %s' % (what, exc))
		else:
			print('Created %s' % (helpdesk_group2,))

		# Add second helpdesk user to second helpdesk group
		try:
			what = 'helpdesk user'
			udm.modify_object('groups/group', dn=helpdesk_group2.dn, append={
				'users': [helpdesk_user2.dn]
			})
		except Exception as exc:
			fail('Adding %s to corresponding group %s failed: %s' % (helpdesk_user2, helpdesk_group2.name, exc))
		else:
			print('Added %s to corresponding group' % what)

		# Create nested group
		try:
			udm.modify_object('groups/group', dn=helpdesk_group1.dn, append={
				'nestedGroup': [helpdesk_group2.dn]
			})
		except Exception as exc:
			fail('Cannot create nested group: %s' % (exc,))
		else:
			print('Created nested group')

		# Allow users to modify their password in Univention Directory Manager
		univention.config_registry.handler_set([
			'ldap/acl/user/passwordreset/accesslist/groups/helpdesk-a=%s' % (helpdesk_group1.dn,),
			'ldap/acl/user/passwordreset/protected/uid=Administrator',
			'ldap/acl/nestedgroups=no'
		])

		# Activate passwordreset ACLs:
		utils.restart_slapd()

		# Test if Helpdesk user can reset password of unprotected user
		try:
			udm.modify_object('users/user', binddn=helpdesk_user1.dn, bindpwd=helpdesk_user1.password, dn=unprotected_user.dn, set={
				'password': 'univention2',
				'overridePWHistory': 1,
				'overridePWLength': 1
			})
		except Exception as exc:
			fail('%s cannot reset password of %s: %s' % (helpdesk_user1, unprotected_user, exc))
		else:
			print('OK: %s reset password of %s successfully' % (helpdesk_user1, unprotected_user))

		# Test if nested helpdesk user can reset password of unprotected user
		try:
			udm.modify_object('users/user', binddn=helpdesk_user2.dn, bindpwd=helpdesk_user2.password, dn=unprotected_user.dn, set={
				'password': 'univention2',
				'overridePWHistory': 1,
				'overridePWLength': 1
			})
		except Exception:
			print('OK: Nested %s cannot reset password of %s, as it should be' % (helpdesk_user2, unprotected_user))
		else:
			fail('Nested %s can reset password of %s, but should not be able to' % (helpdesk_user2, unprotected_user))

		# Enable nested group tests
		univention.config_registry.handler_set(['ldap/acl/nestedgroups=yes'])
		utils.restart_slapd()

		# Test if helpdesk user can still reset password of unprotected user
		try:
			udm.modify_object('users/user', binddn=helpdesk_user1.dn, bindpwd=helpdesk_user1.password, dn=unprotected_user.dn, set={
				'password': uts.random_string(),
				'overridePWHistory': 1,
				'overridePWLength': 1
			})
		except Exception as exc:
			fail('%s can not set password of %s: %s' % (helpdesk_user1, unprotected_user, exc))
		else:
			print('OK: %s set password of %s successfully' % (helpdesk_user1, unprotected_user))

		# Test if nested helpdesk user can reset password of unprotected user
		try:
			udm.modify_object('users/user', binddn=helpdesk_user2.dn, bindpwd=helpdesk_user2.password, dn=unprotected_user.dn, set={
				'password': uts.random_string(),
				'overridePWHistory': 1,
				'overridePWLength': 1
			})
		except Exception as exc:
			fail('%s user can not reset password of %s: %s' % (helpdesk_user2, unprotected_user, exc))
		else:
			print('OK: %s user set password of %s successfully' % (helpdesk_user2, unprotected_user))
finally:
	# Important: deactivate LDAP ACLs again
	utils.restart_slapd()

# vim: set ft=python ts=4 noexpandtab :
