Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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()
Exemple #5
0
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()
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
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,
    )
Exemple #10
0
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)
Exemple #11
0
    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),
        )
Exemple #12
0
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
Exemple #13
0
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
Exemple #14
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
Exemple #15
0
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())
Exemple #16
0
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)
Exemple #17
0
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)
Exemple #18
0
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)
Exemple #19
0
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)
Exemple #20
0
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
Exemple #21
0
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)
Exemple #22
0
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"
Exemple #23
0
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)
Exemple #24
0
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
Exemple #25
0
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
Exemple #26
0
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,
    )
Exemple #27
0
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
Exemple #28
0
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
Exemple #29
0
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)
Exemple #30
0
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)