#!/usr/share/ucs-test/runner python
## desc: ucs-school-reset-password-check
## roles: [domaincontroller_master]
## tags: [apptest]
## exposure: dangerous
## packages: [ucs-school-umc-users]

from univention.lib.umc_connection import UMCConnection
import itertools
import sys
import univention.testing.strings as uts
import univention.testing.ucr as ucr_test
import univention.testing.ucsschool as utu
import univention.testing.utils as utils

# test the authentication of the user name, password and return response status,
# else fails with an exception
def auth(host, username, password):
	connection = UMCConnection(host)
	data = connection.build_data({
		'username' : username,
		'password' : password
	})
	co = connection.get_connection()
	try:
		co.request('POST', '/umcp/auth', data)
		response = co.getresponse()
		return response.status
	except Exception as e:
		utils.fail("Auth exception: '%s' '%s' '%r'" % (str(e), type(e), e))

def test_pwd_reset(host, test_case):
	newpassword = uts.random_string()
	options = {
			'userDN': test_case[2][1],
			'newPassword': newpassword,
			'nextLogin': test_case[3]
			}
	connection = UMCConnection(host)
	connection.auth(test_case[0], 'univention')
	try:
		resetResult = connection.request('schoolusers/password/reset', options, test_case[1])
		if str(resetResult) != test_case[4]:
			# print 'FAIL reset result: %r, expected: %r' % (resetResult,test_case[4])
			utils.fail('umcp command schoolusers/password/reset result: %r, expected: %r' % (resetResult,test_case[4]))
		utils.wait_for_replication()
		utils.wait_for_connector_replication()
	except Exception as e:
		if test_case[4] in str(e):
			print 'Caught expected exception'
		else:
			utils.fail('Caught unexpected exception: %s' % e)

def get_user_type(users_dict, user_name):
	return next(key for (key,val) in users_dict.iteritems() if user_name in val)

def main():
	ucr =  ucr_test.UCSTestConfigRegistry()
	ucr.load()
	host = ucr.get('hostname')
	with utu.UCSTestSchool()  as schoolenv:
		school, oudn = schoolenv.create_ou(name_edudc=host)

		global_user_dn, global_user = schoolenv.create_global_user()
		school_admin_dn, school_admin = schoolenv.create_school_admin(school)
		domain_admin_dn, domain_admin = schoolenv.create_domain_admin(school)
		tea, tea_dn = schoolenv.create_user(school, is_teacher=True)
		stu, stu_dn = schoolenv.create_user(school)

		global_user2_dn, global_user2 = schoolenv.create_global_user()
		school_admin2_dn, school_admin2 = schoolenv.create_school_admin(school)
		domain_admin2_dn, domain_admin2 = schoolenv.create_domain_admin(school)
		tea2, tea2_dn = schoolenv.create_user(school, is_teacher=True)
		stu2, stu2_dn = schoolenv.create_user(school)

		utils.wait_for_replication_and_postrun()

		users_dict = {
				'global user':[global_user, global_user2],
				'school admin':[school_admin, school_admin2],
				'domain admin':[domain_admin, domain_admin2],
				'teacher':[tea, tea2],
				'student': [stu, stu2]
				}
		acting_users = [school_admin, domain_admin, tea, stu, global_user]
		target_users = [school_admin2, domain_admin2, tea2, stu2, global_user2]
		target_users_dn = [school_admin2_dn, domain_admin2_dn, tea2_dn, stu2_dn, global_user2_dn]
		targets = zip(target_users, target_users_dn)

		request_result = ['command forbidden']
		flavors = ['teacher', 'student']
		chg_pwd_on_nxt_login = [True, False]

		# calculating the number of existing test cases
		tests = itertools.product(
				acting_users,
				flavors,
				targets,
				chg_pwd_on_nxt_login,
				request_result,
				)
		length = len(list(tests))
		print 'Number of test cases = :', length

		tests = itertools.product(
				acting_users,
				flavors,
				targets,
				chg_pwd_on_nxt_login,
				request_result,
				)

		# Testing loop
		for i in xrange(length):
			# Get the next test case
			test_case = list(next(tests))

			# Print header for each test case
			print '\n * ', i, '-', get_user_type(users_dict, test_case[0]), ' => ', get_user_type(users_dict, test_case[2][0])
			print '[acting_user, flavor, (target_user, target_user_dn), chg_pwd_on_nxt_login, expected_reset_result]'
			print test_case

			#TODO remove when bug #35447 is fixed
			if (get_user_type(users_dict, test_case[0]) == 'school admin' and get_user_type(users_dict, test_case[2][0]) == 'school admin'):
				print 'SKIPPED see bug #35447'
				continue
			if (get_user_type(users_dict, test_case[0]) == 'school admin' and get_user_type(users_dict, test_case[2][0]) == 'domain admin'):
				print 'SKIPPED see bug #35447'
				continue
			if (get_user_type(users_dict, test_case[0]) == 'domain admin' and get_user_type(users_dict, test_case[2][0]) == 'global user'):
				print 'SKIPPED see bug #35447'
				continue

			# Treat some special cases
			if (get_user_type(users_dict,test_case[0]) == 'teacher' and test_case[1] == 'student'):
				test_case[4] = 'permission denied'
				if get_user_type(users_dict, test_case[2][0]) ==  'student':
					test_case[4] = 'True'

			if get_user_type(users_dict, test_case[0]) == 'school admin':
				test_case[4] = 'permission denied'
				if (get_user_type(users_dict, test_case[2][0]) ==  'student' or
						get_user_type(users_dict, test_case[2][0]) ==  'teacher'):
					test_case[4] = 'True'

			if get_user_type(users_dict, test_case[0]) == 'domain admin':
				test_case[4] = 'permission denied'
				if get_user_type(users_dict, test_case[2][0]) ==  'student':
					test_case[4] = 'True'

			# The actual test
			test_pwd_reset(host, test_case)

if __name__ == '__main__':
	sys.exit(main())
