def test_login_with_email_password_inactive_user(self): """Inactive user logging in with username and password.""" db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' # Inactive user add_user( db=db, new_user=NewUser( email=email, full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=False, password=password, password_repeat=password, activation_url='https://activate.com/activate', ), ) with pytest.raises(McAuthLoginException) as ex: login_with_email_password(db=db, email=email, password=password) # Make sure the error message explicitly states that login failed due to user not being active assert 'not active' in str(ex)
def test_regenerate_api_key(self): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' ip_address = '1.2.3.4' add_user( db=db, new_user=NewUser( email=email, full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ), ) # Get sample API keys user = login_with_email_password(db=db, email=email, password=password, ip_address=ip_address) assert user before_global_api_key = user.global_api_key() assert before_global_api_key before_per_ip_api_key = user.api_key_for_ip_address( ip_address=ip_address) assert before_per_ip_api_key assert before_global_api_key != before_per_ip_api_key # Regenerate API key, purge per-IP API keys regenerate_api_key(db=db, email=email) # Get sample API keys again user = login_with_email_password(db=db, email=email, password=password, ip_address=ip_address) assert user after_global_api_key = user.global_api_key() assert after_global_api_key after_per_ip_api_key = user.api_key_for_ip_address( ip_address=ip_address) assert after_per_ip_api_key # Make sure API keys are different assert before_global_api_key != after_global_api_key assert before_per_ip_api_key != after_per_ip_api_key
def change_password_with_old_password(db: DatabaseHandler, email: str, old_password: str, new_password: str, new_password_repeat: str) -> None: """Change password by entering old password.""" email = decode_object_from_bytes_if_needed(email) old_password = decode_object_from_bytes_if_needed(old_password) new_password = decode_object_from_bytes_if_needed(new_password) new_password_repeat = decode_object_from_bytes_if_needed( new_password_repeat) # Check if user exists try: user_info(db=db, email=email) except Exception: raise McAuthChangePasswordException( 'User with email address "%s" does not exist.' % email) if old_password == new_password: raise McAuthChangePasswordException( 'Old and new passwords are the same.') # Validate old password; fetch the hash from the database again because that hash might be outdated (e.g. if the # password has been changed already) db_password_old = db.query( """ SELECT auth_users_id, email, password_hash FROM auth_users WHERE email = %(email)s LIMIT 1 """, { 'email': email }).hash() if db_password_old is None or len(db_password_old) == 0: raise McAuthChangePasswordException( 'Unable to find the user in the database.') # Validate the password try: login_with_email_password(db=db, email=email, password=old_password) except Exception as ex: raise McAuthChangePasswordException( "Unable to log in with old password: %s" % str(ex)) # Execute the change try: change_password(db=db, email=email, new_password=new_password, new_password_repeat=new_password_repeat) except Exception as ex: raise McAuthChangePasswordException("Unable to change password: %s" % str(ex))
def test_login_with_api_key(): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' ip_address = '1.2.3.4' add_user( db=db, new_user=NewUser( email=email, full_name=full_name, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ), ) # Get sample API keys user = login_with_email_password(db=db, email=email, password=password, ip_address=ip_address) assert user global_api_key = user.global_api_key() assert global_api_key per_ip_api_key = user.api_key_for_ip_address(ip_address=ip_address) assert per_ip_api_key assert global_api_key != per_ip_api_key # Non-existent API key with pytest.raises(McAuthLoginException): login_with_api_key(db=db, api_key='Non-existent API key', ip_address=ip_address) # Global API key user = login_with_api_key(db=db, api_key=global_api_key, ip_address=ip_address) assert user assert user.email() == email assert user.global_api_key() == global_api_key # Per-IP API key user = login_with_api_key(db=db, api_key=per_ip_api_key, ip_address=ip_address) assert user assert user.email() == email
def test_login_with_email_password(): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' add_user( db=db, new_user=NewUser( email=email, full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ), ) # Successful login user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Unsuccessful login with pytest.raises(McAuthLoginException): login_with_email_password(db=db, email=email, password='******') # Subsequent login attempt after a failed one should be delayed by 1 second with pytest.raises(McAuthLoginException): login_with_email_password(db=db, email=email, password=password) # Successful login after waiting out the delay time.sleep(2) user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name
def test_add_user(self): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' new_user = NewUser( email=email, full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ) # Add user add_user(db=db, new_user=new_user) # Test logging in user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Faulty input with pytest.raises(McAuthRegisterException): # noinspection PyTypeChecker add_user(db=db, new_user=None) # Existing user with pytest.raises(McAuthRegisterException): add_user(db=db, new_user=new_user) # Existing user with uppercase email with pytest.raises(McAuthRegisterException): add_user( db=db, new_user=NewUser( email=email.upper(), full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url= '', # user is active, no need for activation URL ), ) # Invalid password with pytest.raises(McAuthUserException): add_user( db=db, new_user=NewUser( email='*****@*****.**', full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password='******', password_repeat='def', activation_url= '', # user is active, no need for activation URL ), ) # Nonexistent roles with pytest.raises(McAuthRegisterException): add_user( db=db, new_user=NewUser( email='*****@*****.**', full_name=full_name, has_consented=True, notes='Test test test', role_ids=[42], active=True, password=password, password_repeat=password, activation_url= '', # user is active, no need for activation URL ), ) # Both the user is set as active and the activation URL is set with pytest.raises(McAuthUserException): add_user( db=db, new_user=NewUser( email='*****@*****.**', full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='https://activate-user.com/activate', ), ) # User is neither active not the activation URL is set with pytest.raises(McAuthUserException): add_user( db=db, new_user=NewUser( email='*****@*****.**', full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=False, password=password, password_repeat=password, activation_url='', ), )
def test_change_password_with_reset_token(self): # FIXME test changing password for user A using reset token from user B db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' add_user( db=db, new_user=NewUser( email=email, full_name=full_name, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ), ) # Successful login user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Make sure password reset token is not set password_reset_token_hash = db.query(""" SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, {'email': email}).flat() assert password_reset_token_hash[0] is None # Send password reset link password_reset_url = 'https://reset-password.com/reset' final_password_reset_url = _generate_password_reset_token( db=db, email=email, password_reset_link=password_reset_url, ) assert final_password_reset_url assert password_reset_url in final_password_reset_url final_password_reset_uri = furl(final_password_reset_url) assert final_password_reset_uri.args['email'] assert final_password_reset_uri.args['password_reset_token'] # Make sure password reset token is set password_reset_token_hash = db.query(""" SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, {'email': email}).flat() assert password_reset_token_hash[0] is not None # Change password new_password = '******' change_password_with_reset_token( db=db, email=email, password_reset_token=final_password_reset_uri.args['password_reset_token'], new_password=new_password, new_password_repeat=new_password, ) # Make sure password reset token has been reset after changing password password_reset_token_hash = db.query(""" SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, {'email': email}).flat() assert password_reset_token_hash[0] is None # Unsuccessful login with old password with pytest.raises(McAuthLoginException): login_with_email_password(db=db, email=email, password=password) # Imposed delay after unsuccessful login time.sleep(2) # Successful login with new password user = login_with_email_password(db=db, email=email, password=new_password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Incorrect password reset token _generate_password_reset_token( db=db, email=email, password_reset_link=password_reset_url, ) with pytest.raises(McAuthChangePasswordException): change_password_with_reset_token( db=db, email=email, password_reset_token='incorrect password reset token', new_password=new_password, new_password_repeat=new_password, ) # Changing for nonexistent user final_password_reset_url = _generate_password_reset_token( db=db, email=email, password_reset_link=password_reset_url, ) with pytest.raises(McAuthChangePasswordException): change_password_with_reset_token( db=db, email='*****@*****.**', password_reset_token=furl(final_password_reset_url).args['password_reset_token'], new_password=new_password, new_password_repeat=new_password, ) # Passwords don't match final_password_reset_url = _generate_password_reset_token( db=db, email=email, password_reset_link=password_reset_url, ) with pytest.raises(McAuthChangePasswordException): change_password_with_reset_token( db=db, email=email, password_reset_token=furl(final_password_reset_url).args['password_reset_token'], new_password='******', new_password_repeat='not match', )
def test_change_password(): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' add_user( db=db, new_user=NewUser( email=email, full_name=full_name, has_consented=True, notes='Test test test', role_ids=[1], active=True, password=password, password_repeat=password, activation_url='', # user is active, no need for activation URL ), ) # Successful login user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Change password new_password = '******' change_password( db=db, email=email, new_password=new_password, new_password_repeat=new_password, do_not_inform_via_email=True, ) # Unsuccessful login with old password with pytest.raises(McAuthLoginException): login_with_email_password(db=db, email=email, password=password) # Imposed delay after unsuccessful login time.sleep(2) # Successful login with new password user = login_with_email_password(db=db, email=email, password=new_password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Changing for nonexistent user with pytest.raises(McAuthChangePasswordException): change_password( db=db, email='*****@*****.**', new_password=new_password, new_password_repeat=new_password, do_not_inform_via_email=True, ) # Passwords don't match with pytest.raises(McAuthChangePasswordException): change_password( db=db, email=email, new_password='******', new_password_repeat='not match', do_not_inform_via_email=True, )
def test_activate_user_via_token(self): db = connect_to_db() email = '*****@*****.**' password = '******' full_name = 'Test user login' activation_url = 'https://activate.com/activate' # Add inactive user add_user( db=db, new_user=NewUser( email=email, full_name=full_name, notes='Test test test', role_ids=[1], active=False, # not active, needs to be activated password=password, password_repeat=password, activation_url=activation_url, ), ) # Test logging in with pytest.raises(McAuthLoginException) as ex: login_with_email_password(db=db, email=email, password=password) # Make sure the error message explicitly states that login failed due to user not being active assert 'not active' in str(ex) # Make sure activation token is set activation_token_hash = db.query( """ SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, { 'email': email }).flat() assert activation_token_hash assert len(activation_token_hash) == 1 assert len(activation_token_hash[0]) > 0 # Send password reset link final_activation_url = _generate_user_activation_token( db=db, email=email, activation_link=activation_url, ) final_activation_uri = furl(final_activation_url) assert final_activation_uri.args['email'] activation_token = final_activation_uri.args['activation_token'] assert activation_token # Make sure activation token is (still) set activation_token_hash = db.query( """ SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, { 'email': email }).flat() assert activation_token_hash assert len(activation_token_hash) == 1 assert len(activation_token_hash[0]) > 0 # Activate user activate_user_via_token(db=db, email=email, activation_token=activation_token) # Imposed delay after unsuccessful login time.sleep(2) # Test logging in user = login_with_email_password(db=db, email=email, password=password) assert user assert isinstance(user, CurrentUser) assert user.email() == email assert user.full_name() == full_name # Make sure activation token is not set anymore activation_token_hash = db.query( """ SELECT password_reset_token_hash FROM auth_users WHERE email = %(email)s """, { 'email': email }).flat() assert activation_token_hash assert len(activation_token_hash) == 1 assert activation_token_hash[0] is None # Incorrect activation token _generate_user_activation_token(db=db, email=email, activation_link=activation_url) with pytest.raises(McAuthRegisterException): activate_user_via_token( db=db, email=email, activation_token='incorrect activation token') # Activating nonexistent user final_activation_url = _generate_user_activation_token( db=db, email=email, activation_link=activation_url, ) final_activation_uri = furl(final_activation_url) activation_token = final_activation_uri.args['activation_token'] with pytest.raises(McAuthRegisterException): activate_user_via_token(db=db, email='*****@*****.**', activation_token=activation_token)