def test_friend_request_accepted_email(db): with session_scope() as session: from_user, api_token_from = generate_user() to_user, api_token_to = generate_user() key = random_hex(32) filename = random_hex(32) + ".jpg" session.add( Upload( key=key, filename=filename, creator_user_id=from_user.id, ) ) session.commit() to_user, api_token_to = generate_user(avatar_key=key) friend_relationship = FriendRelationship(from_user=from_user, to_user=to_user, status=FriendStatus.accepted) session.add(friend_relationship) with patch("couchers.email.queue_email") as mock: send_friend_request_accepted_email(friend_relationship) assert mock.call_count == 1 (sender_name, sender_email, recipient, subject, plain, html), _ = mock.call_args assert recipient == from_user.email assert "friend" in subject.lower() assert from_user.name in plain assert from_user.name in html assert to_user.name in subject assert to_user.name in plain assert to_user.name in html assert to_user.avatar.thumbnail_url not in plain assert to_user.avatar.thumbnail_url in html assert f"{config['BASE_URL']}/user/{to_user.username}" in plain assert f"{config['BASE_URL']}/user/{to_user.username}" in html
def test_report_email(db): with session_scope(db): user_author, api_token_author = generate_user(db) user_reported, api_token_reported = generate_user(db) complaint = Complaint(author_user=user_author, reported_user=user_reported, reason=random_hex(64), description=random_hex(256)) message_id = random_hex(64) @create_autospec def mock_send_email(sender_name, sender_email, recipient, subject, plain, html): assert recipient == "*****@*****.**" assert complaint.author_user.username in plain assert complaint.author_user.username in html assert complaint.reported_user.username in plain assert complaint.reported_user.username in html assert complaint.reason in plain assert complaint.reason in html assert complaint.description in plain assert complaint.description in html assert "report" in subject.lower() return message_id with patch("couchers.email.send_email", mock_send_email) as mock: send_report_email(complaint) assert mock.call_count == 1
def test_friend_request_email(db): with session_scope() as session: to_user, api_token_to = generate_user() # little trick here to get the upload correctly without invalidating users key = random_hex(32) filename = random_hex(32) + ".jpg" session.add( Upload( key=key, filename=filename, creator_user_id=to_user.id, ) ) session.commit() from_user, api_token_from = generate_user(avatar_key=key) friend_relationship = FriendRelationship(from_user=from_user, to_user=to_user, status=FriendStatus.pending) session.add(friend_relationship) with patch("couchers.email.queue_email") as mock: send_friend_request_email(friend_relationship) assert mock.call_count == 1 (sender_name, sender_email, recipient, subject, plain, html), _ = mock.call_args assert recipient == to_user.email assert "friend" in subject.lower() assert to_user.name in plain assert to_user.name in html assert from_user.name in subject assert from_user.name in plain assert from_user.name in html assert from_user.avatar.thumbnail_url not in plain assert from_user.avatar.thumbnail_url in html assert f"{config['BASE_URL']}/connections/friends/" in plain assert f"{config['BASE_URL']}/connections/friends/" in html
def test_report_email(db): with session_scope(): user_author, api_token_author = generate_user() user_reported, api_token_reported = generate_user() complaint = Complaint(author_user=user_author, reported_user=user_reported, reason=random_hex(64), description=random_hex(256)) with patch("couchers.email.queue_email") as mock: send_report_email(complaint) assert mock.call_count == 1 (sender_name, sender_email, recipient, subject, plain, html), _ = mock.call_args assert recipient == "*****@*****.**" assert complaint.author_user.username in plain assert complaint.author_user.username in html assert complaint.reported_user.username in plain assert complaint.reported_user.username in html assert complaint.reason in plain assert complaint.reason in html assert complaint.description in plain assert complaint.description in html assert "report" in subject.lower()
def test_media_upload(db): user, token = generate_user("tester") media_bearer_token = random_hex(32) with api_session(token) as api: res = api.InitiateMediaUpload(empty_pb2.Empty()) params = parse_qs(urlparse(res.upload_url).query) data = urlsafe_b64decode(params["data"][0]) response = media_pb2.UploadRequest.FromString(data) key = response.key filename = random_hex(32) req = media_pb2.UploadConfirmationReq(key=key, filename=filename) with session_scope() as session: # make sure it exists session.query(InitiatedUpload).filter(InitiatedUpload.key == key).one() with media_session(media_bearer_token) as media: res = media.UploadConfirmation(req) with session_scope() as session: # make sure it exists upload = (session.query(Upload).filter(Upload.key == key).filter( Upload.filename == filename).filter( Upload.creator_user_id == user.id).one()) with session_scope() as session: # make sure it was deleted assert not session.query(InitiatedUpload).one_or_none()
def test_host_request_email(db): with session_scope() as session: to_user, api_token_to = generate_user() # little trick here to get the upload correctly without invalidating users key = random_hex(32) filename = random_hex(32) + ".jpg" session.add( Upload( key=key, filename=filename, creator_user_id=to_user.id, )) session.commit() from_user, api_token_from = generate_user(avatar_key=key) from_date = "2020-01-01" to_date = "2020-01-05" conversation = Conversation() message = Message( conversation=conversation, author_id=from_user.id, text=random_hex(64), message_type=MessageType.text, ) host_request = HostRequest( conversation=conversation, from_user=from_user, to_user=to_user, from_date=from_date, to_date=to_date, status=HostRequestStatus.pending, from_last_seen_message_id=message.id, ) session.add(host_request) with patch("couchers.email.queue_email") as mock: send_host_request_email(host_request) assert mock.call_count == 1 (sender_name, sender_email, recipient, subject, plain, html), _ = mock.call_args assert recipient == to_user.email assert "host request" in subject.lower() assert to_user.name in plain assert to_user.name in html assert from_user.name in plain assert from_user.name in html assert from_date in plain assert from_date in html assert to_date in plain assert to_date in html assert from_user.avatar.thumbnail_url not in plain assert from_user.avatar.thumbnail_url in html assert f"{config['BASE_URL']}/messages/hosting/" in plain assert f"{config['BASE_URL']}/messages/hosting/" in html
def test_host_request_email(db): with session_scope(db) as session: from_user, api_token_from = generate_user(db) to_user, api_token_to = generate_user(db) from_date = "2020-01-01" to_date = "2020-01-05" conversation = Conversation() message = Message() message.conversation_id = conversation.id message.author_id = from_user.id message.text = random_hex(64) host_request = HostRequest( conversation_id=conversation.id, from_user=from_user, to_user=to_user, from_date=from_date, to_date=to_date, status=HostRequestStatus.pending, from_last_seen_message_id=message.id, ) message_id = random_hex(64) @create_autospec def mock_send_email(sender_name, sender_email, recipient, subject, plain, html): assert recipient == to_user.email assert "host request" in subject.lower() assert to_user.name in plain assert to_user.name in html assert from_user.name in plain assert from_user.name in html assert from_date in plain assert from_date in html assert to_date in plain assert to_date in html assert from_user.avatar_url not in plain assert from_user.avatar_url in html assert f"{config['BASE_URL']}/hostrequests/" in plain assert f"{config['BASE_URL']}/hostrequests/" in html return message_id with patch("couchers.email.send_email", mock_send_email) as mock: send_host_request_email(host_request) assert mock.call_count == 1
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 send_smtp_email(sender_name, sender_email, recipient, subject, plain, html): """ Sends out the email through SMTP, settings from config. Returns a models.Email object that can be straight away added to the database. """ message_id = random_hex() msg = MIMEMultipart("alternative") msg["Subject"] = subject msg["From"] = email.utils.formataddr((sender_name, sender_email)) msg["To"] = recipient msg["X-Couchers-ID"] = message_id msg.attach(MIMEText(plain, "plain")) msg.attach(MIMEText(html, "html")) with smtplib.SMTP(config["SMTP_HOST"], config["SMTP_PORT"]) as server: server.ehlo() server.starttls() # stmplib docs recommend calling ehlo() before and after starttls() server.ehlo() server.login(config["SMTP_USERNAME"], config["SMTP_PASSWORD"]) server.sendmail(sender_email, recipient, msg.as_string()) return Email( id=message_id, sender_name=sender_name, sender_email=sender_email, recipient=recipient, subject=subject, plain=plain, html=html, )
def test_ChangeEmail_sends_proper_emails_has_password(db, fast_passwords): password = random_hex() new_email = f"{random_hex()}@couchers.org.invalid" user, token = generate_user(hashed_password=hash_password(password)) with account_session(token) as account: account.ChangeEmail( account_pb2.ChangeEmailReq( password=wrappers_pb2.StringValue(value=password), new_email=new_email, )) with session_scope() as session: jobs = (session.execute( select(BackgroundJob).where( BackgroundJob.job_type == BackgroundJobType.send_email)).scalars().all()) assert len(jobs) == 2 payload_for_notification_email = jobs[0].payload payload_for_confirmation_email_new_address = jobs[1].payload unique_string_notification_email_as_bytes = b"You requested that your email on Couchers.org be changed to" unique_string_for_confirmation_email_new_email_address_as_bytes = ( b"You requested that your email be changed to this email address on Couchers.org" ) assert unique_string_notification_email_as_bytes in payload_for_notification_email assert (unique_string_for_confirmation_email_new_email_address_as_bytes in payload_for_confirmation_email_new_address)
def InitiateMediaUpload(self, request, context): key = random_hex() created = now() expiry = created + timedelta(minutes=20) with session_scope() as session: upload = InitiatedUpload(key=key, created=created, expiry=expiry, initiator_user_id=context.user_id) session.add(upload) session.commit() req = media_pb2.UploadRequest( key=upload.key, type=media_pb2.UploadRequest.UploadType.IMAGE, created=Timestamp_from_datetime(upload.created), expiry=Timestamp_from_datetime(upload.expiry), max_width=2000, max_height=1600, ).SerializeToString() data = urlsafe_b64encode(req).decode("utf8") sig = urlsafe_b64encode(generate_hash_signature(req, config["MEDIA_SERVER_SECRET_KEY"])).decode("utf8") path = "upload?" + urlencode({"data": data, "sig": sig}) return api_pb2.InitiateMediaUploadRes( upload_url=urls.media_upload_url(path), expiry=Timestamp_from_datetime(expiry), )
def test_friend_request_email(db): with session_scope(db) as session: from_user, api_token_from = generate_user(db) to_user, api_token_to = generate_user(db) friend_relationship = FriendRelationship(from_user=from_user, to_user=to_user, status=FriendStatus.pending) message_id = random_hex(64) @create_autospec def mock_send_email(sender_name, sender_email, recipient, subject, plain, html): assert recipient == to_user.email assert "friend" in subject.lower() assert to_user.name in plain assert to_user.name in html assert from_user.name in subject assert from_user.name in plain assert from_user.name in html assert from_user.avatar_url not in plain assert from_user.avatar_url in html assert f"{config['BASE_URL']}/friends/" in plain assert f"{config['BASE_URL']}/friends/" in html return message_id with patch("couchers.email.send_email", mock_send_email) as mock: send_friend_request_email(friend_relationship) assert mock.call_count == 1
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_logging_interceptor_all_ignored(): # error codes that should not be touched by the interceptor pass_through_status_codes = [ # we can't abort with OK # grpc.StatusCode.OK, grpc.StatusCode.CANCELLED, grpc.StatusCode.UNKNOWN, grpc.StatusCode.INVALID_ARGUMENT, grpc.StatusCode.DEADLINE_EXCEEDED, grpc.StatusCode.NOT_FOUND, grpc.StatusCode.ALREADY_EXISTS, grpc.StatusCode.PERMISSION_DENIED, grpc.StatusCode.UNAUTHENTICATED, grpc.StatusCode.RESOURCE_EXHAUSTED, grpc.StatusCode.FAILED_PRECONDITION, grpc.StatusCode.ABORTED, grpc.StatusCode.OUT_OF_RANGE, grpc.StatusCode.UNIMPLEMENTED, grpc.StatusCode.INTERNAL, grpc.StatusCode.UNAVAILABLE, grpc.StatusCode.DATA_LOSS, ] for status_code in pass_through_status_codes: message = random_hex() def TestRpc(request, context): context.abort(status_code, message) with interceptor_dummy_api(TestRpc, interceptors=[ErrorSanitizationInterceptor()]) as call_rpc: with pytest.raises(grpc.RpcError) as e: call_rpc(empty_pb2.Empty()) assert e.value.code() == status_code assert e.value.details() == message
def test_GetAccountInfo_regression(db): # there was a bug in evaluating `has_completed_profile` on the backend (in python) # when about_me is None but the user has a key, it was failing because len(about_me) doesn't work on None uploader_user, _ = generate_user() with session_scope() as session: key = random_hex(32) filename = random_hex(32) + ".jpg" session.add( Upload( key=key, filename=filename, creator_user_id=uploader_user.id, )) session.commit() user, token = generate_user(about_me=None, avatar_key=key) with account_session(token) as account: res = account.GetAccountInfo(empty_pb2.Empty())
def test_ChangePassword_regression(db, fast_passwords): # send_password_changed_email wasn't working # user has old password and is changing to new password old_password = random_hex() new_password = random_hex() user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue(value=old_password), new_password=wrappers_pb2.StringValue(value=new_password), )) with session_scope() as session: updated_user = session.execute( select(User).where(User.id == user.id)).scalar_one() assert updated_user.hashed_password == hash_password(new_password)
def test_ChangePassword_normal_no_password(db, fast_passwords): # user has old password and is changing to new password, but didn't supply old password old_password = random_hex() new_password = random_hex() user, token = generate_user(db, hashed_password=hash_password(old_password)) with account_session(db, token) as account: with pytest.raises(grpc.RpcError) as e: account.ChangePassword( account_pb2.ChangePasswordReq( new_password=wrappers_pb2.StringValue( value=new_password), )) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.MISSING_PASSWORD with session_scope(db) as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(old_password)
def test_ChangePassword_normal(db, fast_passwords): # user has old password and is changing to new password old_password = random_hex() new_password = random_hex() user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: with patch("couchers.servicers.account.send_password_changed_email") as mock: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue(value=old_password), new_password=wrappers_pb2.StringValue(value=new_password), ) ) mock.assert_called_once() with session_scope() as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(new_password)
def test_ChangePassword_normal_long_password(db, fast_passwords): # user has old password and is changing to new password, but used short password old_password = random_hex() new_password = random_hex(length=1000) user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: with pytest.raises(grpc.RpcError) as e: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue(value=old_password), new_password=wrappers_pb2.StringValue(value=new_password), ) ) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.PASSWORD_TOO_LONG with session_scope() as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(old_password)
def generate_user(db, *_, **kwargs): """ Create a new user, return session token The user is detached from any session, and you can access its static attributes, but you can't modify it Use this most of the time """ auth = Auth(db) with session_scope(db) as session: # default args username = "******" + random_hex(16) user_opts = { "username": username, "email": f"{username}@dev.couchers.org", # password is just 'password' # this is hardcoded because the password is slow to hash (so would slow down tests otherwise) "hashed_password": b"$argon2id$v=19$m=65536,t=2,p=1$4cjGg1bRaZ10k+7XbIDmFg$tZG7JaLrkfyfO7cS233ocq7P8rf3znXR7SAfUt34kJg", "name": username.capitalize(), "city": "Testing city", "verification": 0.5, "community_standing": 0.5, "birthdate": date(year=2000, month=1, day=1), "gender": "N/A", "languages": "Testing language 1|Testing language 2", "occupation": "Tester", "about_me": "I test things", "about_place": "My place has a lot of testing paraphenelia", "countries_visited": "Testing country", "countries_lived": "Wonderland", # you need to make sure to update this logic to make sure the user is jailed/not on request "accepted_tos": 1, } for key, value in kwargs.items(): user_opts[key] = value user = User(**user_opts) session.add(user) # this expires the user, so now it's "dirty" session.commit() token = auth._create_session("Dummy context", session, user) # refresh it, undoes the expiry session.refresh(user) # allows detaches the user from the session, allowing its use outside this session session.expunge(user) return user, token
def test_ChangePassword_normal_wrong_password(db, fast_passwords): # user has old password and is changing to new password, but used wrong old password old_password = random_hex() new_password = random_hex() user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: with pytest.raises(grpc.RpcError) as e: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue( value="wrong password"), new_password=wrappers_pb2.StringValue(value=new_password), )) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD with session_scope() as session: updated_user = session.execute( select(User).where(User.id == user.id)).scalar_one() assert updated_user.hashed_password == hash_password(old_password)
def test_invalid_token(db): user1, token1 = generate_user() user2, token2 = generate_user() wrong_token = random_hex(32) with real_api_session(wrong_token) as api, pytest.raises( grpc.RpcError) as e: res = api.GetUser(api_pb2.GetUserReq(user=user2.username)) assert e.value.code() == grpc.StatusCode.UNAUTHENTICATED assert e.value.details() == "Unauthorized"
def test_ChangePassword_normal_no_passwords(db, fast_passwords): # user has old password and called with empty body old_password = random_hex() user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: with pytest.raises(grpc.RpcError) as e: account.ChangePassword(account_pb2.ChangePasswordReq()) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.MISSING_BOTH_PASSWORDS with session_scope() as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(old_password)
def test_SetPassword(db, fast_passwords): # make them not have a password user1, token1 = generate_user(hashed_password=None) with real_jail_session(token1) as jail: res = jail.JailInfo(empty_pb2.Empty()) assert res.jailed assert res.has_not_set_password # make sure bad password are caught with pytest.raises(grpc.RpcError) as e: jail.SetPassword(jail_pb2.SetPasswordReq(new_password="******")) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INSECURE_PASSWORD res = jail.JailInfo(empty_pb2.Empty()) assert res.jailed assert res.has_not_set_password # make sure we can set a good password pwd = random_hex() res = jail.SetPassword(jail_pb2.SetPasswordReq(new_password=pwd)) assert not res.jailed assert not res.has_not_set_password # make sure we can't set a password again with pytest.raises(grpc.RpcError) as e: jail.SetPassword( jail_pb2.SetPasswordReq(new_password=random_hex())) assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION assert e.value.details() == errors.ALREADY_HAS_PASSWORD res = jail.JailInfo(empty_pb2.Empty()) assert not res.jailed assert not res.has_not_set_password
def test_GetAccountInfo(db, fast_passwords): # without password user1, token1 = generate_user(hashed_password=None) with account_session(token1) as account: res = account.GetAccountInfo(empty_pb2.Empty()) assert res.login_method == account_pb2.GetAccountInfoRes.LoginMethod.MAGIC_LINK assert not res.has_password # with password user1, token1 = generate_user(hashed_password=hash_password(random_hex())) with account_session(token1) as account: res = account.GetAccountInfo(empty_pb2.Empty()) assert res.login_method == account_pb2.GetAccountInfoRes.LoginMethod.PASSWORD assert res.has_password
def print_dev_email(sender_name, sender_email, recipient, subject, plain, html): message_id = random_hex() print("Dev email:") print(plain) return Email( id=message_id, sender_name=sender_name, sender_email=sender_email, recipient=recipient, subject=subject, plain=plain, html=html, )
def test_ChangeEmail_has_password(db, fast_passwords): password = random_hex() new_email = f"{random_hex()}@couchers.org.invalid" user, token = generate_user(hashed_password=hash_password(password)) with account_session(token) as account: account.ChangeEmail( account_pb2.ChangeEmailReq( password=wrappers_pb2.StringValue(value=password), new_email=new_email, )) with session_scope() as session: user_updated = session.execute( select(User).where(User.id == user.id)).scalar_one() assert user_updated.email == user.email assert user_updated.new_email == new_email assert user_updated.old_email_token is None assert not user_updated.old_email_token_created assert not user_updated.old_email_token_expiry assert not user_updated.need_to_confirm_via_old_email assert user_updated.new_email_token is not None assert user_updated.new_email_token_created <= now() assert user_updated.new_email_token_expiry >= now() assert user_updated.need_to_confirm_via_new_email token = user_updated.new_email_token with auth_api_session() as (auth_api, metadata_interceptor): res = auth_api.ConfirmChangeEmail( auth_pb2.ConfirmChangeEmailReq(change_email_token=token, )) assert res.state == auth_pb2.EMAIL_CONFIRMATION_STATE_SUCCESS with session_scope() as session: user = session.execute( select(User).where(User.id == user.id)).scalar_one() assert user.email == new_email assert user.new_email is None assert user.old_email_token is None assert user.old_email_token_created is None assert user.old_email_token_expiry is None assert not user.need_to_confirm_via_old_email assert user.new_email_token is None assert user.new_email_token_created is None assert user.new_email_token_expiry is None assert not user.need_to_confirm_via_new_email
def test_ChangePassword_remove(db, fast_passwords): old_password = random_hex() user, token = generate_user(hashed_password=hash_password(old_password)) with account_session(token) as account: with patch("couchers.servicers.account.send_password_changed_email" ) as mock: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue( value=old_password), )) mock.assert_called_once() with session_scope() as session: updated_user = session.execute( select(User).where(User.id == user.id)).scalar_one() assert not updated_user.has_password
def test_ChangePassword_add(db, fast_passwords): # user does not have an old password and is adding a new password new_password = random_hex() user, token = generate_user(db, hashed_password=None) with account_session(db, token) as account: with patch("couchers.servicers.account.send_password_changed_email" ) as mock: account.ChangePassword( account_pb2.ChangePasswordReq( new_password=wrappers_pb2.StringValue( value=new_password), )) mock.assert_called_once() with session_scope(db) as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(new_password)
def test_ChangePassword_remove_wrong_password(db, fast_passwords): old_password = random_hex() user, token = generate_user(db, hashed_password=hash_password(old_password)) with account_session(db, token) as account: with pytest.raises(grpc.RpcError) as e: account.ChangePassword( account_pb2.ChangePasswordReq( old_password=wrappers_pb2.StringValue( value="wrong password"), )) assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT assert e.value.details() == errors.INVALID_USERNAME_OR_PASSWORD with session_scope(db) as session: updated_user = session.query(User).filter(User.id == user.id).one() assert updated_user.hashed_password == hash_password(old_password)