def test_basic_login(db): # Create our test user using signup _quick_signup() with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.NEED_PASSWORD with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Authenticate( auth_pb2.AuthReq(user="******", password="******")) reply_token = get_session_cookie_token(metadata_interceptor) with session_scope() as session: token = (session.execute( select(UserSession).join(User, UserSession.user_id == User.id). where(User.username == "frodo").where( UserSession.token == reply_token)).scalar_one_or_none()).token assert token # log out with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Deauthenticate(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={reply_token}"), ))
def test_unsuccessful_login(db): # Invalid email, user doesn't exist with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Login( auth_pb2.LoginReq( user=f"{random_hex(12)}@couchers.org.invalid")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.USER_NOT_FOUND # Invalid id with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.USER_NOT_FOUND # Invalid username with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.USER_NOT_FOUND testing_email = f"{random_hex(12)}@couchers.org.invalid" # No Password user_without_pass, _ = generate_user(hashed_password=None) with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login( auth_pb2.LoginReq(user=user_without_pass.username)) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL
def test_basic_login(db): # Create our test user using signup test_basic_signup(db) with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL # backdoor to find login token with session_scope() as session: entry = session.query(LoginToken).one() login_token = entry.token with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token)) reply_token = get_session_cookie_token(metadata_interceptor) with session_scope() as session: token = (session.query(UserSession).filter( User.username == "frodo").filter( UserSession.token == reply_token).one_or_none()) assert token # log out with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Deauthenticate( empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={reply_token}"), ))
def test_logout_invalid_token(db): # Create our test user using signup test_basic_signup(db) with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL # backdoor to find login token with session_scope() as session: entry = session.query(LoginToken).one() login_token = entry.token with auth_api_session() as (auth_api, metadata_interceptor): auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token)) reply_token = get_session_cookie_token(metadata_interceptor) # delete all login tokens with session_scope() as session: session.query(LoginToken).delete() # log out with non-existent token should still return a valid result with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Deauthenticate(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={reply_token}"), )) reply_token = get_session_cookie_token(metadata_interceptor) # make sure we set an empty cookie assert reply_token == ""
def test_signup_invalid_email(db): with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="frodo", email="a"))) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_EMAIL with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="frodo", email="a@b"))) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_EMAIL with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="frodo", email="a@b."))) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_EMAIL with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="frodo", email="[email protected]"))) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_EMAIL
def test_logout_invalid_token(db): # Create our test user using signup _quick_signup() with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.NEED_PASSWORD with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Authenticate( auth_pb2.AuthReq(user="******", password="******")) reply_token = get_session_cookie_token(metadata_interceptor) # delete all login tokens with session_scope() as session: session.execute(delete(LoginToken)) # log out with non-existent token should still return a valid result with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Deauthenticate(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={reply_token}"), )) reply_token = get_session_cookie_token(metadata_interceptor) # make sure we set an empty cookie assert reply_token == ""
def test_basic_signup(db): with auth_api_session(db) as auth_api: reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**")) assert reply.next_step == auth_pb2.SignupRes.SignupStep.SENT_SIGNUP_EMAIL # read out the signup token directly from the database for now with session_scope(db) as session: entry = session.query(SignupToken).filter( SignupToken.email == "*****@*****.**").one_or_none() signup_token = entry.token with auth_api_session(db) as auth_api: reply = auth_api.SignupTokenInfo( auth_pb2.SignupTokenInfoReq(signup_token=signup_token)) assert reply.email == "*****@*****.**" with auth_api_session(db) as auth_api: reply = auth_api.CompleteSignup( auth_pb2.CompleteSignupReq( signup_token=signup_token, username="******", name="Räksmörgås", city="Minas Tirith", birthdate="1980-12-31", gender="Robot", hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, )) assert isinstance(reply.token, str)
def test_signup_invalid_birthdate(db): with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**")) assert reply.next_step == auth_pb2.SignupRes.SignupStep.SENT_SIGNUP_EMAIL # read out the signup token directly from the database for now with session_scope() as session: entry = session.query(SignupToken).filter( SignupToken.email == "*****@*****.**").one() signup_token = entry.token with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.SignupTokenInfo( auth_pb2.SignupTokenInfoReq(signup_token=signup_token)) assert reply.email == "*****@*****.**" with auth_api_session() as (auth_api, metadata_interceptor), pytest.raises( grpc.RpcError) as e: reply = auth_api.CompleteSignup( auth_pb2.CompleteSignupReq( signup_token=signup_token, username="******", name="Räksmörgås", city="Minas Tirith", birthdate="9999-12-31", # arbitrary future birthdate gender="Robot", hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, lat=1, lng=1, radius=100, accept_tos=True, )) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_BIRTHDATE
def test_basic_login_without_password(db): # Create our test user using signup _quick_signup() with session_scope() as session: user = session.execute(select(User)).scalar_one() user.hashed_password = None with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL # backdoor to find login token with session_scope() as session: entry = session.execute(select(LoginToken)).scalar_one() login_token = entry.token with auth_api_session() as (auth_api, metadata_interceptor): auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token)) reply_token = get_session_cookie_token(metadata_interceptor) with session_scope() as session: token = (session.execute( select(UserSession).join(User, UserSession.user_id == User.id). where(User.username == "frodo").where( UserSession.token == reply_token)).scalar_one_or_none()).token assert token # log out with auth_api_session() as (auth_api, metadata_interceptor): auth_api.Deauthenticate(empty_pb2.Empty(), metadata=(("cookie", f"couchers-sesh={reply_token}"), ))
def test_UsernameValid(db): with auth_api_session() as (auth_api, metadata_interceptor): assert auth_api.UsernameValid( auth_pb2.UsernameValidReq(username="******")).valid with auth_api_session() as (auth_api, metadata_interceptor): assert not auth_api.UsernameValid( auth_pb2.UsernameValidReq(username="")).valid
def test_UsernameValid(db): with auth_api_session(db) as auth_api: assert auth_api.UsernameValid( auth_pb2.UsernameValidReq(username="******")).valid with auth_api_session(db) as auth_api: assert not auth_api.UsernameValid( auth_pb2.UsernameValidReq(username="")).valid
def test_full_delete_account_with_recovery(db): user, token = generate_user() user_id = user.id with account_session(token) as account: with pytest.raises(grpc.RpcError) as e: account.DeleteAccount(account_pb2.DeleteAccountReq()) assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION assert e.value.details() == errors.MUST_CONFIRM_ACCOUNT_DELETE # Check the right email is sent with patch("couchers.email.queue_email") as mock: account.DeleteAccount(account_pb2.DeleteAccountReq(confirm=True)) mock.assert_called_once() (_, _, _, subject, _, _), _ = mock.call_args assert subject == "[TEST] Confirm your Couchers.org account deletion" with session_scope() as session: token_o = session.execute(select(AccountDeletionToken)).scalar_one() token = token_o.token user = session.execute( select(User).where(User.id == user_id)).scalar_one() assert token_o.user == user assert not user.is_deleted assert not user.undelete_token assert not user.undelete_until with auth_api_session() as (auth_api, metadata_interceptor): auth_api.ConfirmDeleteAccount( auth_pb2.ConfirmDeleteAccountReq(token=token, )) with session_scope() as session: assert not session.execute( select(AccountDeletionToken)).scalar_one_or_none() with session_scope() as session: user = session.execute( select(User).where(User.id == user_id)).scalar_one() assert user.is_deleted assert user.undelete_token assert user.undelete_until > now() undelete_token = user.undelete_token with auth_api_session() as (auth_api, metadata_interceptor): auth_api.RecoverAccount( auth_pb2.RecoverAccountReq(token=undelete_token, )) with session_scope() as session: assert not session.execute( select(AccountDeletionToken)).scalar_one_or_none() user = session.execute( select(User).where(User.id == user_id)).scalar_one() assert not user.is_deleted assert not user.undelete_token assert not user.undelete_until
def test_successful_login(db): user, _ = generate_user() # Valid email login with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user=user.email)) assert reply.next_step == auth_pb2.LoginRes.LoginStep.NEED_PASSWORD # Valid username login with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user=user.username)) assert reply.next_step == auth_pb2.LoginRes.LoginStep.NEED_PASSWORD
def test_ChangeEmail_tokens_two_hour_window(db): def two_hours_one_minute_in_future(): return now() + timedelta(hours=2, minutes=1) def one_minute_ago(): return now() - timedelta(minutes=1) new_email = f"{random_hex()}@couchers.org.invalid" user, token = generate_user(hashed_password=None) with account_session(token) as account: account.ChangeEmail(account_pb2.ChangeEmailReq(new_email=new_email, )) with session_scope() as session: user = session.execute( select(User).where(User.id == user.id)).scalar_one() old_email_token = user.old_email_token new_email_token = user.new_email_token with patch("couchers.servicers.auth.now", one_minute_ago): with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: auth_api.ConfirmChangeEmail( auth_pb2.ConfirmChangeEmailReq( change_email_token=old_email_token, )) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_TOKEN with pytest.raises(grpc.RpcError) as e: auth_api.ConfirmChangeEmail( auth_pb2.ConfirmChangeEmailReq( change_email_token=new_email_token, )) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_TOKEN with patch("couchers.servicers.auth.now", two_hours_one_minute_in_future): with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: auth_api.ConfirmChangeEmail( auth_pb2.ConfirmChangeEmailReq( change_email_token=old_email_token, )) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_TOKEN with pytest.raises(grpc.RpcError) as e: auth_api.ConfirmChangeEmail( auth_pb2.ConfirmChangeEmailReq( change_email_token=new_email_token, )) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_TOKEN
def test_successful_authenticate(db): user, _ = generate_user(hashed_password=hash_password("password")) # Authenticate with username with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Authenticate( auth_pb2.AuthReq(user=user.username, password="******")) assert not reply.jailed # Authenticate with email with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Authenticate( auth_pb2.AuthReq(user=user.email, password="******")) assert not reply.jailed
def test_banned_user(db): _quick_signup() with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.NEED_PASSWORD with session_scope() as session: session.execute(select(User)).scalar_one().is_banned = True with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: auth_api.Authenticate( auth_pb2.AuthReq(user="******", password="******")) assert e.value.details() == "Your account is suspended."
def test_multiple_delete_tokens(db): """ Make sure deletion tokens are deleted on delete """ user, token = generate_user() user_id = user.id with account_session(token) as account: account.DeleteAccount(account_pb2.DeleteAccountReq(confirm=True)) account.DeleteAccount(account_pb2.DeleteAccountReq(confirm=True)) account.DeleteAccount(account_pb2.DeleteAccountReq(confirm=True)) with session_scope() as session: assert session.execute( select(func.count()).select_from( AccountDeletionToken)).scalar_one() == 3 token = session.execute( select(AccountDeletionToken)).scalars().first().token with auth_api_session() as (auth_api, metadata_interceptor): auth_api.ConfirmDeleteAccount( auth_pb2.ConfirmDeleteAccountReq(token=token, )) with session_scope() as session: assert not session.execute( select(AccountDeletionToken)).scalar_one_or_none()
def test_ChangeEmail_wrong_token(db, fast_passwords): password = random_hex() new_email = f"{random_hex()}@couchers.org.invalid" user, token = generate_user(db, hashed_password=hash_password(password)) with account_session(db, token) as account: account.ChangeEmail( account_pb2.ChangeEmailReq( password=wrappers_pb2.StringValue(value=password), new_email=new_email, )) with session_scope(db) as session: user_updated = (session.query(User).filter(User.id == user.id).filter( User.new_email == new_email).filter( User.new_email_token_created <= func.now()).filter( User.new_email_token_expiry >= func.now())).one() token = user_updated.new_email_token with auth_api_session(db) as auth_api: with pytest.raises(grpc.RpcError) as e: res = auth_api.CompleteChangeEmail( auth_pb2.CompleteChangeEmailReq( change_email_token="wrongtoken", )) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == errors.INVALID_TOKEN with session_scope(db) as session: user_updated2 = session.query(User).filter(User.id == user.id).one() assert user_updated2.email == user.email
def test_ChangeEmail(db, fast_passwords): password = random_hex() new_email = f"{random_hex()}@couchers.org.invalid" user, token = generate_user(db, hashed_password=hash_password(password)) with account_session(db, token) as account: account.ChangeEmail( account_pb2.ChangeEmailReq( password=wrappers_pb2.StringValue(value=password), new_email=new_email, )) with session_scope(db) as session: user_updated = (session.query(User).filter(User.id == user.id).filter( User.new_email == new_email).filter( User.new_email_token_created <= func.now()).filter( User.new_email_token_expiry >= func.now())).one() token = user_updated.new_email_token with auth_api_session(db) as auth_api: res = auth_api.CompleteChangeEmail( auth_pb2.CompleteChangeEmailReq(change_email_token=token, )) with session_scope(db) as session: user_updated2 = session.query(User).filter(User.id == user.id).one() assert user_updated2.email == new_email assert user_updated2.new_email is None assert user_updated2.new_email_token is None # check there's no valid tokens left with session_scope(db) as session: assert (session.query(User).filter( User.new_email_token_created <= func.now()).filter( User.new_email_token_expiry >= func.now())).count() == 0
def test_purge_signup_tokens(db): with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**")) # send email process_job() with session_scope() as session: signup_token = session.query(SignupToken).one() signup_token.expiry = func.now() assert session.query(SignupToken).count() == 1 queue_job(BackgroundJobType.purge_signup_tokens, empty_pb2.Empty()) # purge tokens process_job() with session_scope() as session: assert session.query(SignupToken).count() == 0 with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 2 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_banned_user(db): test_basic_signup(db) with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL with session_scope() as session: login_token = session.query(LoginToken).one().token with session_scope() as session: session.query(User).one().is_banned = True with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError): auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token))
def test_unsuccessful_authenticate(db): user, _ = generate_user(hashed_password=hash_password("password")) # Invalid password with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Authenticate( auth_pb2.AuthReq(user=user.username, password="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD # Invalid username with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Authenticate( auth_pb2.AuthReq(user="******", password="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD # Invalid email with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Authenticate( auth_pb2.AuthReq(user=f"{random_hex(12)}@couchers.org.invalid", password="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD # Invalid id with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Authenticate( auth_pb2.AuthReq(user="******", password="******")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD # No Password user_without_pass, _ = generate_user(hashed_password=None) with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.Authenticate( auth_pb2.AuthReq(user=user_without_pass.username, password="******")) assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION assert e.value.details() == errors.NO_PASSWORD
def test_enforce_community_memberships_for_user(testing_communities): """ Make sure the user is added to the right communities on signup """ with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="testing", email="*****@*****.**"), account=auth_pb2.SignupAccount( username="******", password="******", birthdate="1970-01-01", gender="Bot", hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST, city="Country 1, Region 1, City 2", # lat=8, lng=1 is equivalent to creating this coordinate with create_coordinate(8) lat=8, lng=1, radius=500, accept_tos=True, ), feedback=auth_pb2.ContributorForm(), accept_community_guidelines=wrappers_pb2.BoolValue(value=True), )) with session_scope() as session: email_token = (session.execute( select(SignupFlow).where(SignupFlow.flow_token == res.flow_token)).scalar_one().email_token) with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.SignupFlow( auth_pb2.SignupFlowReq(email_token=email_token)) user_id = res.auth_res.user_id # now check the user is in the right communities with session_scope() as session: w_id = get_community_id(session, "Global") c1_id = get_community_id(session, "Country 1") c1r1_id = get_community_id(session, "Country 1, Region 1") c1r1c2_id = get_community_id(session, "Country 1, Region 1, City 2") token = get_session_cookie_token(metadata_interceptor) with communities_session(token) as api: res = api.ListUserCommunities(communities_pb2.ListUserCommunitiesReq()) assert [c.community_id for c in res.communities] == [w_id, c1_id, c1r1_id, c1r1c2_id]
def test_login_tokens_invalidate_after_use(db): test_basic_signup(db) with auth_api_session(db) as auth_api: reply = auth_api.Login(auth_pb2.LoginReq(user="******")) assert reply.next_step == auth_pb2.LoginRes.LoginStep.SENT_LOGIN_EMAIL with session_scope(db) as session: login_token = session.query(LoginToken).one_or_none().token with auth_api_session(db) as auth_api: session_token = auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token)).token with auth_api_session(db) as auth_api, pytest.raises(grpc.RpcError): # check we can't login again auth_api.CompleteTokenLogin( auth_pb2.CompleteTokenLoginReq(login_token=login_token))
def test_signup_continue_with_email(db): testing_email = f"{random_hex(12)}@couchers.org.invalid" with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.SignupFlow( auth_pb2.SignupFlowReq( basic=auth_pb2.SignupBasic(name="frodo", email=testing_email))) flow_token = res.flow_token assert flow_token # continue with same email, should just send another email to the user with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: res = auth_api.SignupFlow( auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic( name="frodo", email=testing_email))) assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION assert e.value.details() == errors.SIGNUP_FLOW_EMAIL_STARTED_SIGNUP
def test_password_reset(db): user, token = generate_user(hashed_password=hash_password("mypassword")) with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.ResetPassword( auth_pb2.ResetPasswordReq(user=user.username, )) with session_scope() as session: token = session.execute(select(PasswordResetToken)).scalar_one().token with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.CompletePasswordReset( auth_pb2.CompletePasswordResetReq(password_reset_token=token)) with session_scope() as session: user = session.execute(select(User)).scalar_one() assert not user.has_password
def test_password_reset(db, fast_passwords): user, token = generate_user(hashed_password=hash_password("mypassword")) with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.ResetPassword( auth_pb2.ResetPasswordReq(user=user.username, )) with session_scope() as session: token = session.query(PasswordResetToken).one().token with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.CompletePasswordReset( auth_pb2.CompletePasswordResetReq(password_reset_token=token)) with session_scope() as session: user = session.query(User).one() assert user.hashed_password is None
def test_password_reset_invalid_token(db): password = random_hex() user, token = generate_user(hashed_password=hash_password(password)) with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.ResetPassword( auth_pb2.ResetPasswordReq(user=user.username, )) with auth_api_session() as (auth_api, metadata_interceptor), pytest.raises( grpc.RpcError) as e: res = auth_api.CompletePasswordReset( auth_pb2.CompletePasswordResetReq( password_reset_token="wrongtoken")) assert e.value.code() == grpc.StatusCode.NOT_FOUND assert e.value.details() == errors.INVALID_TOKEN with session_scope() as session: user = session.execute(select(User)).scalar_one() assert user.hashed_password == hash_password(password)
def test_signup_existing_email(db): # Signed up user user, _ = generate_user() with auth_api_session() as (auth_api, metadata_interceptor): with pytest.raises(grpc.RpcError) as e: reply = auth_api.SignupFlow( auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic( name="frodo", email=user.email))) assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION assert e.value.details() == errors.SIGNUP_FLOW_EMAIL_TAKEN
def test_password_reset_no_such_user(db): user, token = generate_user() with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.ResetPassword( auth_pb2.ResetPasswordReq(user="******", )) with session_scope() as session: res = session.execute(select(PasswordResetToken)).scalar_one_or_none() assert res is None