def test_verify_success_if_correct_information_supplied(): # Subtests: # a) Verify 'authbcrypt' table has new hash # b) Verify 'forgotpassword' row is removed. # > Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Force update link_time (required) resetpassword.prepare(pw_reset_token) form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) resetpassword.reset(form) # 'forgotpassword' row should not exist after a successful reset row_does_not_exist = d.engine.execute( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) assert row_does_not_exist.first() is None bcrypt_hash = d.engine.scalar( "SELECT hashsum FROM authbcrypt WHERE userid = %(id)s", id=user_id) assert bcrypt.checkpw(password.encode('utf-8'), bcrypt_hash.encode('utf-8'))
def forgetpassword_post_(request): resetpassword.request(email=request.POST['email']) return Response( define.errorpage( request.userid, "**Success!** Information on how to reset your password has been sent to your email address.", [["Return to the Home Page", "/"]]))
def test_password_reset_fails_if_attempted_from_different_ip_address(): # Two parts: Set forgot password record; attempt reset with incorrect IP Address in forgotpassword table vs. requesting IP # Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Change IP detected when request was made (required for test) d.engine.execute( "UPDATE forgotpassword SET address = %(addr)s WHERE token = %(token)s", addr="127.42.42.42", token=pw_reset_token) # Force update link_time (required) resetpassword.prepare(pw_reset_token) form_for_reset = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) with pytest.raises(WeasylError) as err: resetpassword.reset(form_for_reset) assert 'addressInvalid' == err.value.value
def test_emailIncorrect_WeasylError_if_email_address_doesnt_match_stored_email( ): # Two parts: Set forgot password record; attempt reset with incorrect email # Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Force update link_time (required) resetpassword.prepare(pw_reset_token) email_addr_mismatch = "*****@*****.**" form_for_reset = Bag(email=email_addr_mismatch, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) with pytest.raises(WeasylError) as err: resetpassword.reset(form_for_reset) assert 'emailIncorrect' == err.value.value
def POST(self): form = web.input(username="", email="", day="", month="", year="") resetpassword.request(form) return define.errorpage( self.user_id, "**Success!** A message containing information on " "how to reset your password has been sent to your email address.", [["Return to the Home Page", "/index"]])
def test_verify_success_if_valid_information_provided(): email_addr = "*****@*****.**" user_id = db_utils.create_user(email_addr=email_addr) form = Bag(email=email_addr) resetpassword.request(form) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) assert 100 == len(pw_reset_token) assert resetpassword.prepare(pw_reset_token)
def test_user_must_exist_for_a_forgotten_password_request_to_be_made(): email_addr = "*****@*****.**" form = Bag(email=email_addr) resetpassword.request(form) record_count = d.engine.scalar(""" SELECT COUNT(*) FROM forgotpassword """) assert record_count == 0
def test_user_must_exist_for_a_forgotten_password_request_to_be_made(): user_name = "test" email_addr = "*****@*****.**" form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) with pytest.raises(WeasylError) as err: resetpassword.request(form) assert 'loginRecordMissing' == err.value.value
def test_stale_records_get_deleted_when_function_is_called(): token_store = [] for i in range(20): user_name = "testPrepare%d" % (i, ) email_addr = "*****@*****.**" % (i, ) user_id = db_utils.create_user(email_addr=email_addr, username=user_name) form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) token_store.append(pw_reset_token) # All tokens should exist at this point for i in range(20): assert resetpassword.checktoken(token_store[i]) # Set 5 tokens to be two hours old (0,5) (7200) for i in range(0, 5): d.engine.execute( "UPDATE forgotpassword SET set_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 7200, token=token_store[i]) # Set 5 tokens to be 30 minutes old (5,10) (1800) for i in range(5, 10): d.engine.execute( "UPDATE forgotpassword SET set_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 1800, token=token_store[i]) # Set 5 tokens to be 10 minutes old for the last visit time (10,15) (600) for i in range(10, 15): d.engine.execute( "UPDATE forgotpassword SET link_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 600, token=token_store[i]) # Set 5 tokens to be 2 minutes old for the last visit time (10,15) (120) for i in range(15, 20): d.engine.execute( "UPDATE forgotpassword SET link_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 120, token=token_store[i]) # This should clear all tokens >1hr old, and all tokens >5 minutes from last visit (10 total) resetpassword.prepare('foo') # This range should be cleared (set_time > 3600) for i in range(0, 5): assert not resetpassword.checktoken(token_store[i]) # This range should still be present (set_time < 3600) for i in range(5, 10): assert resetpassword.checktoken(token_store[i]) # This range should be cleared (link_time > 300) for i in range(10, 15): assert not resetpassword.checktoken(token_store[i]) # This range should still be present (link_time < 300) for i in range(15, 20): assert resetpassword.checktoken(token_store[i])
def forgetpassword_post_(request): form = request.web_input(username="", email="", day="", month="", year="") resetpassword.request(form) return Response(define.errorpage( request.userid, "**Success!** A message containing information on " "how to reset your password has been sent to your email address.", [["Return to the Home Page", "/"]]))
def forgetpassword_post_(request): form = request.web_input(username="", email="", day="", month="", year="") resetpassword.request(form) return Response( define.errorpage( request.userid, "**Success!** A message containing information on " "how to reset your password has been sent to your email address.", [["Return to the Home Page", "/"]]))
def test_email_must_match_email_stored_in_DB(): email_addr = "*****@*****.**" user_id = db_utils.create_user(email_addr=email_addr) email_addr = "*****@*****.**" form = Bag(email=email_addr) resetpassword.request(form) query = d.engine.scalar(""" SELECT userid FROM forgotpassword WHERE userid = %(userid)s """, userid=user_id) assert not query
def forgetpassword_post_(request): form = request.web_input(email="") resetpassword.request(form) return Response(define.errorpage( request.userid, "**Success!** Provided the supplied email matches a user account in our " "records, information on how to reset your password has been sent to your " "email address.", [["Return to the Home Page", "/"]]))
def test_email_must_match_email_stored_in_DB(): user_name = "test" email_addr = "*****@*****.**" db_utils.create_user(email_addr=email_addr, username=user_name) email_addr = "*****@*****.**" form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) with pytest.raises(WeasylError) as err: resetpassword.request(form) assert 'emailInvalid' == err.value.value
def test_verify_success_if_valid_information_provided(): user_name = "test" email_addr = "*****@*****.**" user_id = db_utils.create_user(email_addr=email_addr, username=user_name) form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) assert 100 == len(pw_reset_token) assert resetpassword.checktoken(pw_reset_token)
def forgetpassword_post_(request): form = request.web_input(email="") resetpassword.request(form) return Response( define.errorpage( request.userid, "**Success!** Provided the supplied email matches a user account in our " "records, information on how to reset your password has been sent to your " "email address.", [["Return to the Home Page", "/"]]))
def test_link_time_field_is_updated_when_valid_token_supplied_to_function(): user_name = "test" email_addr = "*****@*****.**" user_id = db_utils.create_user(email_addr=email_addr, username=user_name) form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) resetpassword.prepare(pw_reset_token) link_time = d.engine.scalar("SELECT link_time FROM forgotpassword WHERE token = %(token)s", token=pw_reset_token) assert link_time >= d.get_time()
def test_verify_success_if_valid_information_provided(captured_tokens): email_addr = "*****@*****.**" username = "******" user_id = db_utils.create_user(username=username, email_addr=email_addr) resetpassword.request(email=email_addr) pw_reset_token = captured_tokens[email_addr] assert 25 == len(pw_reset_token) assert dict(resetpassword.prepare(pw_reset_token)) == { "userid": user_id, "email": email_addr, "username": username, }
def test_case_insensitive_local_part(captured_tokens): email_addr = "*****@*****.**" username = "******" user_id = db_utils.create_user(username=username, email_addr=email_addr.swapcase()) resetpassword.request(email=email_addr) pw_reset_token = captured_tokens[email_addr] assert 25 == len(pw_reset_token) assert dict(resetpassword.prepare(pw_reset_token)) == { "userid": user_id, "email": email_addr.swapcase(), "username": username, }
def test_verify_success_if_valid_information_provided(): user_name = "test" email_addr = "*****@*****.**" user_id = db_utils.create_user(email_addr=email_addr, username=user_name) form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form) pw_reset_token = d.engine.scalar( "SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) assert 100 == len(pw_reset_token) assert resetpassword.checktoken(pw_reset_token)
def test_emailIncorrect_WeasylError_if_username_doesnt_match_stored_username(): # Two parts: Set forgot password record; attempt reset with incorrect username # Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Force update link_time (required) resetpassword.prepare(pw_reset_token) user_name_mismatch = "nottheaccountname123" form_for_reset = Bag(email=email_addr, username=user_name_mismatch, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) with pytest.raises(WeasylError) as err: resetpassword.reset(form_for_reset) assert 'usernameIncorrect' == err.value.value
def test_stale_records_get_deleted_when_function_is_called(): token_store = [] for i in range(20): user_name = "testPrepare%d" % (i,) email_addr = "*****@*****.**" % (i,) user_id = db_utils.create_user(email_addr=email_addr, username=user_name) form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) token_store.append(pw_reset_token) # All tokens should exist at this point for i in range(20): assert resetpassword.checktoken(token_store[i]) # Set 5 tokens to be two hours old (0,5) (7200) for i in range(0, 5): d.engine.execute("UPDATE forgotpassword SET set_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 7200, token=token_store[i]) # Set 5 tokens to be 30 minutes old (5,10) (1800) for i in range(5, 10): d.engine.execute("UPDATE forgotpassword SET set_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 1800, token=token_store[i]) # Set 5 tokens to be 10 minutes old for the last visit time (10,15) (600) for i in range(10, 15): d.engine.execute("UPDATE forgotpassword SET link_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 600, token=token_store[i]) # Set 5 tokens to be 2 minutes old for the last visit time (10,15) (120) for i in range(15, 20): d.engine.execute("UPDATE forgotpassword SET link_time = %(time)s WHERE token = %(token)s", time=d.get_time() - 120, token=token_store[i]) # This should clear all tokens >1hr old, and all tokens >5 minutes from last visit (10 total) resetpassword.prepare('foo') # This range should be cleared (set_time > 3600) for i in range(0, 5): assert not resetpassword.checktoken(token_store[i]) # This range should still be present (set_time < 3600) for i in range(5, 10): assert resetpassword.checktoken(token_store[i]) # This range should be cleared (link_time > 300) for i in range(10, 15): assert not resetpassword.checktoken(token_store[i]) # This range should still be present (link_time < 300) for i in range(15, 20): assert resetpassword.checktoken(token_store[i])
def test_password_reset_fails_if_attempted_from_different_ip_address(): # Two parts: Set forgot password record; attempt reset with incorrect IP Address in forgotpassword table vs. requesting IP # Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Change IP detected when request was made (required for test) d.engine.execute("UPDATE forgotpassword SET address = %(addr)s WHERE token = %(token)s", addr="127.42.42.42", token=pw_reset_token) # Force update link_time (required) resetpassword.prepare(pw_reset_token) form_for_reset = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) with pytest.raises(WeasylError) as err: resetpassword.reset(form_for_reset) assert 'addressInvalid' == err.value.value
def test_stale_records_get_deleted_when_function_is_called(captured_tokens): email_addrs = list(map("test{}@weasyl.com".format, range(10))) for email_addr in email_addrs: db_utils.create_user(email_addr=email_addr) resetpassword.request(email=email_addr) # Set 5 tokens to be two hours old (0,5) for i in range(0, 5): d.engine.execute("UPDATE forgotpassword SET created_at = now() - INTERVAL '2 hours' WHERE email = %(email)s", email=email_addrs[i]) # Set 5 tokens to be 30 minutes old (5,10) for i in range(5, 10): d.engine.execute("UPDATE forgotpassword SET created_at = now() - INTERVAL '30 minutes' WHERE email = %(email)s", email=email_addrs[i]) # This range should be invalid (created_at > 3600) for i in range(0, 5): assert not resetpassword.prepare(captured_tokens[email_addrs[i]]) # This range should still be valid (created_at < 3600) for i in range(5, 10): assert resetpassword.prepare(captured_tokens[email_addrs[i]])
def test_verify_success_if_correct_information_supplied(): # Subtests: # a) Verify 'authbcrypt' table has new hash # b) Verify 'forgotpassword' row is removed. # > Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' form_for_request = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year) resetpassword.request(form_for_request) pw_reset_token = d.engine.scalar("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) # Force update link_time (required) resetpassword.prepare(pw_reset_token) form = Bag(email=email_addr, username=user_name, day=arrow.now().day, month=arrow.now().month, year=arrow.now().year, token=pw_reset_token, password=password, passcheck=password) resetpassword.reset(form) # 'forgotpassword' row should not exist after a successful reset row_does_not_exist = d.engine.execute("SELECT token FROM forgotpassword WHERE userid = %(id)s", id=user_id) assert row_does_not_exist.first() is None bcrypt_hash = d.engine.scalar("SELECT hashsum FROM authbcrypt WHERE userid = %(id)s", id=user_id) assert bcrypt.checkpw(password.encode('utf-8'), bcrypt_hash.encode('utf-8'))
def test_verify_success_if_correct_information_supplied(captured_tokens): # Subtests: # a) Verify 'authbcrypt' table has new hash # b) Verify 'forgotpassword' row is removed. # > Requirement: Get token set from request() user_id = db_utils.create_user(email_addr=email_addr, username=user_name) password = '******' resetpassword.request(email=email_addr) pw_reset_token = captured_tokens[email_addr] resetpassword.reset( token=pw_reset_token, password=password, passcheck=password, expect_userid=user_id, address=None, ) # 'forgotpassword' row should not exist after a successful reset record_count = d.engine.scalar("SELECT count(*) FROM forgotpassword") assert record_count == 0 bcrypt_hash = d.engine.scalar( "SELECT hashsum FROM authbcrypt WHERE userid = %(id)s", id=user_id) assert bcrypt.checkpw(password.encode('utf-8'), bcrypt_hash.encode('utf-8'))
def test_forgotten_password_request_always_made(): resetpassword.request(email="*****@*****.**") record_count = d.engine.scalar("SELECT count(*) FROM forgotpassword") assert record_count == 1