#!/usr/share/ucs-test/runner python
## desc: Test the allowed groupType changes
## tags: [udm,apptest]
## roles: [domaincontroller_master]
## exposure: dangerous
## packages:
##   - univention-config
##   - univention-directory-manager-tools

import univention.testing.utils as utils
import univention.testing.udm as udm_test

class GroupChangePossible(BaseException): pass

GROUP_TYPE_LOCAL="-2147483643"
GROUP_TYPE_DOMAIN_LOCAL="-2147483644"
GROUP_TYPE_GLOBAL="-2147483646"
GROUP_TYPE_UNIVERSAL="-2147483640"

def _test_local_group_change():
	with udm_test.UCSTestUDM() as udm:
		group1 = udm.create_group(adGroupType=GROUP_TYPE_LOCAL)[0]
		group2 = udm.create_group(adGroupType=GROUP_TYPE_LOCAL)[0]
		group3 = udm.create_group(adGroupType=GROUP_TYPE_LOCAL)[0]

		utils.wait_for_connector_replication()

		utils.verify_ldap_object(group1, {'univentionGroupType': [GROUP_TYPE_LOCAL]})
		utils.verify_ldap_object(group2, {'univentionGroupType': [GROUP_TYPE_LOCAL]})
		utils.verify_ldap_object(group3, {'univentionGroupType': [GROUP_TYPE_LOCAL]})

		try:
			udm.modify_object('groups/group', dn = group1, adGroupType=GROUP_TYPE_DOMAIN_LOCAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		try:
			udm.modify_object('groups/group', dn = group2, adGroupType=GROUP_TYPE_GLOBAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		try:
			udm.modify_object('groups/group', dn = group3, adGroupType=GROUP_TYPE_UNIVERSAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

def _test_domain_local_group_change():
	with udm_test.UCSTestUDM() as udm:
		group1 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group2 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group3 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]

		group4 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group5 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL,nestedGroup=group4)[0]
		group6 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group7 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL,nestedGroup=group6)[0]

		group8 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group9 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL,nestedGroup=group8)[0]
		group10 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group11 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL,nestedGroup=group10)[0]

		utils.wait_for_connector_replication()

		utils.verify_ldap_object(group1, {'univentionGroupType': [GROUP_TYPE_DOMAIN_LOCAL]})
		utils.verify_ldap_object(group2, {'univentionGroupType': [GROUP_TYPE_DOMAIN_LOCAL]})
		utils.verify_ldap_object(group3, {'univentionGroupType': [GROUP_TYPE_DOMAIN_LOCAL]})
		utils.verify_ldap_object(group4, {'univentionGroupType': [GROUP_TYPE_DOMAIN_LOCAL]})
		utils.verify_ldap_object(group5, {'univentionGroupType': [GROUP_TYPE_DOMAIN_LOCAL]})

		try:
			udm.modify_object('groups/group', dn = group1, adGroupType=GROUP_TYPE_LOCAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		try:
			udm.modify_object('groups/group', dn = group2, adGroupType=GROUP_TYPE_GLOBAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group3, adGroupType=GROUP_TYPE_UNIVERSAL)


		try:
			udm.modify_object('groups/group', dn = group5, adGroupType=GROUP_TYPE_UNIVERSAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			print 'E: Domain local group has another domain local group as member. Change to universal group was possible which should not be.'
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group6, adGroupType=GROUP_TYPE_UNIVERSAL)

		udm.modify_object('groups/group', dn = group9, adGroupType=GROUP_TYPE_UNIVERSAL)
		udm.modify_object('groups/group', dn = group11, adGroupType=GROUP_TYPE_UNIVERSAL)
	
def _test_global_group_change():
	with udm_test.UCSTestUDM() as udm:
		group1 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group2 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group3 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]

		group4 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group5 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL,nestedGroup=group4)[0]
		group6 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group7 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL,nestedGroup=group6)[0]

		group8 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group9 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL,nestedGroup=group8)[0]
		group10 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group11 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL,nestedGroup=group10)[0]

		utils.wait_for_connector_replication()

		utils.verify_ldap_object(group1, {'univentionGroupType': [GROUP_TYPE_GLOBAL]})
		utils.verify_ldap_object(group2, {'univentionGroupType': [GROUP_TYPE_GLOBAL]})
		utils.verify_ldap_object(group3, {'univentionGroupType': [GROUP_TYPE_GLOBAL]})
		utils.verify_ldap_object(group4, {'univentionGroupType': [GROUP_TYPE_GLOBAL]})
		utils.verify_ldap_object(group5, {'univentionGroupType': [GROUP_TYPE_GLOBAL]})

		try:
			udm.modify_object('groups/group', dn = group1, adGroupType=GROUP_TYPE_LOCAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		try:
			udm.modify_object('groups/group', dn = group2, adGroupType=GROUP_TYPE_DOMAIN_LOCAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group3, adGroupType=GROUP_TYPE_UNIVERSAL)

		udm.modify_object('groups/group', dn = group5, adGroupType=GROUP_TYPE_UNIVERSAL)

		try:
			udm.modify_object('groups/group', dn = group6, adGroupType=GROUP_TYPE_UNIVERSAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			print 'E: Gloabl group is member of another global group. Change to universal group was possible which should not be.'
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group9, adGroupType=GROUP_TYPE_UNIVERSAL)
		udm.modify_object('groups/group', dn = group11, adGroupType=GROUP_TYPE_UNIVERSAL)
	
def _test_universal_group_change():
	with udm_test.UCSTestUDM() as udm:
		group1 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group2 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group3 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]

		group4 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group5 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL,nestedGroup=group4)[0]
		group6 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL)[0]
		group7 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL,nestedGroup=group6)[0]

		group8 = udm.create_group(adGroupType=GROUP_TYPE_DOMAIN_LOCAL)[0]
		group9 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL,nestedGroup=group8)[0]
		group10 = udm.create_group(adGroupType=GROUP_TYPE_GLOBAL)[0]
		group11 = udm.create_group(adGroupType=GROUP_TYPE_UNIVERSAL,nestedGroup=group10)[0]

		utils.wait_for_connector_replication()

		utils.verify_ldap_object(group1, {'univentionGroupType': [GROUP_TYPE_UNIVERSAL]})
		utils.verify_ldap_object(group2, {'univentionGroupType': [GROUP_TYPE_UNIVERSAL]})
		utils.verify_ldap_object(group3, {'univentionGroupType': [GROUP_TYPE_UNIVERSAL]})

		try:
			udm.modify_object('groups/group', dn = group1, adGroupType=GROUP_TYPE_LOCAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group2, adGroupType=GROUP_TYPE_DOMAIN_LOCAL)

		udm.modify_object('groups/group', dn = group3, adGroupType=GROUP_TYPE_GLOBAL)

		try:
			udm.modify_object('groups/group', dn = group5, adGroupType=GROUP_TYPE_GLOBAL)
		except udm_test.UCSTestUDM_ModifyUDMObjectFailed:
			pass
		else:
			print 'E: Universal group has another universal group as member. Change to global group was possible which should not be.'
			raise GroupChangePossible

		udm.modify_object('groups/group', dn = group6, adGroupType=GROUP_TYPE_GLOBAL)

		udm.modify_object('groups/group', dn = group9, adGroupType=GROUP_TYPE_GLOBAL)
		udm.modify_object('groups/group', dn = group11, adGroupType=GROUP_TYPE_GLOBAL)
	
if __name__ == '__main__':

	_test_local_group_change()
	_test_domain_local_group_change()
	_test_global_group_change()
	_test_universal_group_change()
