<commit_before># Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals

import unittest, frappe, pyotp
from werkzeug.wrappers import Request
from werkzeug.test import EnvironBuilder
from frappe.auth import LoginManager, HTTPRequest
from frappe.twofactor import *
import time



class TestTwoFactor(unittest.TestCase):


	def setUp(self):
		self.http_requests = create_http_request()
		self.login_manager = frappe.local.login_manager
		self.user = self.login_manager.user

	def tearDown(self):
		tmp_id = frappe.local.response['tmp_id']
		frappe.local.response['verification'] = None
		frappe.local.response['tmp_id'] = None
		frappe.clear_cache(user=self.user)


	def test_should_run_2fa(self):
		'''Should return true if enabled.'''
		toggle_2fa_all_role(state=True)
		self.assertTrue(should_run_2fa(self.user))
		toggle_2fa_all_role(state=False)
		self.assertFalse(should_run_2fa(self.user))

	def test_get_cached_user_pass(self):
		'''Cached data should not contain user and pass before 2fa.'''
		user,pwd = get_cached_user_pass()
		self.assertTrue(all([not user, not pwd]))

	def test_authenticate_for_2factor(self):
		'''Verification obj and tmp_id should be set in frappe.local.'''
		authenticate_for_2factor(self.user)
		verification_obj = frappe.local.response['verification']
		tmp_id = frappe.local.response['tmp_id']
		self.assertTrue(verification_obj)
		self.assertTrue(tmp_id)
		for k in ['_usr','_pwd','_otp_secret']:
			self.assertTrue(frappe.cache().get('{0}{1}'.format(tmp_id,k)),
							'{} not available'.format(k))

	def test_two_factor_is_enabled_for_user(self):
		'''Should return true if enabled for user.'''
		toggle_2fa_all_role(state=True)
		self.assertTrue(two_factor_is_enabled_for_(self.user))
		toggle_2fa_all_role(state=False)
		self.assertFalse(two_factor_is_enabled_for_(self.user))

	def test_get_otpsecret_for_user(self):
		'''OTP secret should be set for user.'''
		self.assertTrue(get_otpsecret_for_(self.user))
		self.assertTrue(frappe.db.get_default(self.user + '_otpsecret'))

	def test_confirm_otp_token(self):
		'''Ensure otp is confirmed'''
		authenticate_for_2factor(self.user)
		tmp_id = frappe.local.response['tmp_id']
		otp = 'wrongotp'
		with self.assertRaises(frappe.AuthenticationError):
			confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id)
		otp = get_otp(self.user)		
		self.assertTrue(confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id))
		if frappe.flags.tests_verbose:
			print('Sleeping for 30secs to confirm token expires..')
		time.sleep(30)
		with self.assertRaises(frappe.AuthenticationError):
			confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id)

	def test_get_verification_obj(self):
		'''Confirm verification object is returned.'''
		otp_secret = get_otpsecret_for_(self.user)
		token = int(pyotp.TOTP(otp_secret).now())
		self.assertTrue(get_verification_obj(self.user,token,otp_secret))

	def test_render_string_template(self):
		'''String template renders as expected with variables.'''
		args = {'issuer_name':'Frappe Technologies'}
		_str = 'Verification Code from {{issuer_name}}'
		_str = render_string_template(_str,args)
		self.assertEqual(_str,'Verification Code from Frappe Technologies')


def set_request(**kwargs):
	builder = EnvironBuilder(**kwargs)
	frappe.local.request = Request(builder.get_environ())

def create_http_request():
	'''Get http request object.'''
	set_request(method='POST', path='login')
	enable_2fa()
	frappe.form_dict['usr'] = '<EMAIL>'
	frappe.form_dict['pwd'] = '<PASSWORD>'
	frappe.local.form_dict['cmd'] = 'login'
	http_requests = HTTPRequest()
	return http_requests

def enable_2fa():
	'''Enable Two factor in system settings.'''
	toggle_two_factor_auth(True)
	system_settings = frappe.get_doc('System Settings')
	system_settings.two_factor_method = 'OTP App'
	system_settings.save(ignore_permissions=True)
	frappe.db.commit()

def toggle_2fa_all_role(state=None):
	'''Enable or disable 2fa for 'all' role on the system.'''
	all_role = frappe.get_doc('Role','All')
	if state == None:
		state = False if all_role.two_factor_auth == True else False
	if state not in [True,False]:return
	all_role.two_factor_auth = state
	all_role.save(ignore_permissions=True)
	frappe.db.commit()

def get_otp(user):
	otp_secret = get_otpsecret_for_(user)
	otp = pyotp.TOTP(otp_secret)
	return otp.now()<commit_msg>[fix] tests<commit_after># Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals

import unittest, frappe, pyotp
from werkzeug.wrappers import Request
from werkzeug.test import EnvironBuilder
from frappe.auth import HTTPRequest
from frappe.twofactor import (should_run_2fa, authenticate_for_2factor, get_cached_user_pass,
	two_factor_is_enabled_for_, confirm_otp_token, get_otpsecret_for_, get_verification_obj,
	render_string_template)

import time

class TestTwoFactor(unittest.TestCase):
	def setUp(self):
		self.http_requests = create_http_request()
		self.login_manager = frappe.local.login_manager
		self.user = self.login_manager.user

	def tearDown(self):
		frappe.local.response['verification'] = None
		frappe.local.response['tmp_id'] = None
		disable_2fa()
		frappe.clear_cache(user=self.user)

	def test_should_run_2fa(self):
		'''Should return true if enabled.'''
		toggle_2fa_all_role(state=True)
		self.assertTrue(should_run_2fa(self.user))
		toggle_2fa_all_role(state=False)
		self.assertFalse(should_run_2fa(self.user))

	def test_get_cached_user_pass(self):
		'''Cached data should not contain user and pass before 2fa.'''
		user,pwd = get_cached_user_pass()
		self.assertTrue(all([not user, not pwd]))

	def test_authenticate_for_2factor(self):
		'''Verification obj and tmp_id should be set in frappe.local.'''
		authenticate_for_2factor(self.user)
		verification_obj = frappe.local.response['verification']
		tmp_id = frappe.local.response['tmp_id']
		self.assertTrue(verification_obj)
		self.assertTrue(tmp_id)
		for k in ['_usr','_pwd','_otp_secret']:
			self.assertTrue(frappe.cache().get('{0}{1}'.format(tmp_id,k)),
							'{} not available'.format(k))

	def test_two_factor_is_enabled_for_user(self):
		'''Should return true if enabled for user.'''
		toggle_2fa_all_role(state=True)
		self.assertTrue(two_factor_is_enabled_for_(self.user))
		toggle_2fa_all_role(state=False)
		self.assertFalse(two_factor_is_enabled_for_(self.user))

	def test_get_otpsecret_for_user(self):
		'''OTP secret should be set for user.'''
		self.assertTrue(get_otpsecret_for_(self.user))
		self.assertTrue(frappe.db.get_default(self.user + '_otpsecret'))

	def test_confirm_otp_token(self):
		'''Ensure otp is confirmed'''
		authenticate_for_2factor(self.user)
		tmp_id = frappe.local.response['tmp_id']
		otp = 'wrongotp'
		with self.assertRaises(frappe.AuthenticationError):
			confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id)
		otp = get_otp(self.user)
		self.assertTrue(confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id))
		if frappe.flags.tests_verbose:
			print('Sleeping for 30secs to confirm token expires..')
		time.sleep(30)
		with self.assertRaises(frappe.AuthenticationError):
			confirm_otp_token(self.login_manager,otp=otp,tmp_id=tmp_id)

	def test_get_verification_obj(self):
		'''Confirm verification object is returned.'''
		otp_secret = get_otpsecret_for_(self.user)
		token = int(pyotp.TOTP(otp_secret).now())
		self.assertTrue(get_verification_obj(self.user,token,otp_secret))

	def test_render_string_template(self):
		'''String template renders as expected with variables.'''
		args = {'issuer_name':'Frappe Technologies'}
		_str = 'Verification Code from {{issuer_name}}'
		_str = render_string_template(_str,args)
		self.assertEqual(_str,'Verification Code from Frappe Technologies')


def set_request(**kwargs):
	builder = EnvironBuilder(**kwargs)
	frappe.local.request = Request(builder.get_environ())

def create_http_request():
	'''Get http request object.'''
	set_request(method='POST', path='login')
	enable_2fa()
	frappe.form_dict['usr'] = '<EMAIL>'
	frappe.form_dict['pwd'] = '<PASSWORD>'
	frappe.local.form_dict['cmd'] = 'login'
	http_requests = HTTPRequest()
	return http_requests

def enable_2fa():
	'''Enable Two factor in system settings.'''
	system_settings = frappe.get_doc('System Settings')
	system_settings.enable_two_factor_auth = 1
	system_settings.two_factor_method = 'OTP App'
	system_settings.save(ignore_permissions=True)
	frappe.db.commit()

def disable_2fa():
	system_settings = frappe.get_doc('System Settings')
	system_settings.enable_two_factor_auth = 0
	system_settings.save(ignore_permissions=True)
	frappe.db.commit()

def toggle_2fa_all_role(state=None):
	'''Enable or disable 2fa for 'all' role on the system.'''
	all_role = frappe.get_doc('Role','All')
	if state == None:
		state = False if all_role.two_factor_auth == True else False
	if state not in [True,False]:return
	all_role.two_factor_auth = state
	all_role.save(ignore_permissions=True)
	frappe.db.commit()

def get_otp(user):
	otp_secret = get_otpsecret_for_(user)
	otp = pyotp.TOTP(otp_secret)
	return otp.now()
{'fraction_non_alphanumeric': 0.12053327505190689, 'fraction_numerical': 0.006119549775980767, 'mean_word_length': 6.4045307443365695, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5753924', 'n_tokens_mistral': 3411, 'n_tokens_neox': 3285, 'n_words': 590}