예제 #1
0
def test_tracing_interceptor_abort(db):
    def TestRpc(request, context):
        context.abort(grpc.StatusCode.FAILED_PRECONDITION, "now a grpc abort")

    with interceptor_dummy_api(
        TestRpc,
        interceptors=[TracingInterceptor()],
        request_type=auth_pb2.SignupAccount,
        response_type=auth_pb2.AuthReq,
    ) as call_rpc:
        with pytest.raises(Exception):
            call_rpc(auth_pb2.SignupAccount(password="******", username="******"))

    with session_scope() as session:
        trace = session.execute(select(APICall)).scalar_one()
        assert trace.method == "/testing.Test/TestRpc"
        assert trace.status_code == "FAILED_PRECONDITION"
        assert not trace.user_id
        assert "now a grpc abort" in trace.traceback
        req = auth_pb2.SignupAccount.FromString(trace.request)
        assert not req.password
        assert req.username == "not removed"
        assert not trace.response

    _check_histogram_labels("/testing.Test/TestRpc", "Exception", "FAILED_PRECONDITION", 1)
예제 #2
0
def test_tracing_interceptor_sensitive(db):
    def TestRpc(request, context):
        return auth_pb2.AuthReq(user="******", password="******")

    with interceptor_dummy_api(
        TestRpc,
        interceptors=[TracingInterceptor()],
        request_type=auth_pb2.SignupAccount,
        response_type=auth_pb2.AuthReq,
    ) as call_rpc:
        call_rpc(auth_pb2.SignupAccount(password="******", username="******"))

    with session_scope() as session:
        trace = session.execute(select(APICall)).scalar_one()
        assert trace.method == "/testing.Test/TestRpc"
        assert not trace.status_code
        assert not trace.user_id
        assert not trace.traceback
        req = auth_pb2.SignupAccount.FromString(trace.request)
        assert not req.password
        assert req.username == "not removed"
        res = auth_pb2.AuthReq.FromString(trace.response)
        assert res.user == "this is not secret"
        assert not res.password

    _check_histogram_labels("/testing.Test/TestRpc", "", "", 1)
예제 #3
0
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]
예제 #4
0
def test_signup_without_password(db):
    with auth_api_session() as (auth_api, metadata_interceptor):
        with pytest.raises(grpc.RpcError) as e:
            auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    basic=auth_pb2.SignupBasic(name="Räksmörgås",
                                               email="*****@*****.**"),
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        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,
                    ),
                    feedback=auth_pb2.ContributorForm(),
                ))
        assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
        assert e.value.details() == errors.PASSWORD_TOO_SHORT
예제 #5
0
def test_complete_signup(db):
    testing_email = f"{random_hex(12)}@couchers.org.invalid"
    with auth_api_session() as (auth_api, metadata_interceptor):
        reply = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic(
                name="Tester", email=testing_email)))

    flow_token = reply.flow_token

    with auth_api_session() as (auth_api, metadata_interceptor):
        # Invalid username
        with pytest.raises(grpc.RpcError) as e:
            reply = auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    flow_token=flow_token,
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        city="Minas Tirith",
                        birthdate="1980-12-31",
                        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_USERNAME

    with auth_api_session() as (auth_api, metadata_interceptor):
        # Invalid name
        with pytest.raises(grpc.RpcError) as e:
            reply = auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic(
                    name=" ", email=f"{random_hex(12)}@couchers.org.invalid")))
        assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
        assert e.value.details() == errors.INVALID_NAME

    with auth_api_session() as (auth_api, metadata_interceptor):
        # Hosting status required
        with pytest.raises(grpc.RpcError) as e:
            reply = auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    flow_token=flow_token,
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        city="Minas Tirith",
                        birthdate="1980-12-31",
                        gender="Robot",
                        hosting_status=None,
                        lat=1,
                        lng=1,
                        radius=100,
                        accept_tos=True,
                    ),
                ))
        assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
        assert e.value.details() == errors.HOSTING_STATUS_REQUIRED

    user, _ = generate_user()
    with auth_api_session() as (auth_api, metadata_interceptor):
        # Username unavailable
        with pytest.raises(grpc.RpcError) as e:
            reply = auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    flow_token=flow_token,
                    account=auth_pb2.SignupAccount(
                        username=user.username,
                        password="******",
                        city="Minas Tirith",
                        birthdate="1980-12-31",
                        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.FAILED_PRECONDITION
        assert e.value.details() == errors.USERNAME_NOT_AVAILABLE

    with auth_api_session() as (auth_api, metadata_interceptor):
        # Invalid coordinate
        with pytest.raises(grpc.RpcError) as e:
            reply = auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    flow_token=flow_token,
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        city="Minas Tirith",
                        birthdate="1980-12-31",
                        gender="Robot",
                        hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST,
                        lat=0,
                        lng=0,
                        radius=100,
                        accept_tos=True,
                    ),
                ))
        assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
        assert e.value.details() == errors.INVALID_COORDINATE
예제 #6
0
def test_signup_invalid_birthdate(db):
    with auth_api_session() as (auth_api, metadata_interceptor):
        with pytest.raises(grpc.RpcError) as e:
            auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    basic=auth_pb2.SignupBasic(name="Räksmörgås",
                                               email="*****@*****.**"),
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        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,
                    ),
                    feedback=auth_pb2.ContributorForm(),
                ))
        assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
        assert e.value.details() == errors.INVALID_BIRTHDATE

        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(
                basic=auth_pb2.SignupBasic(name="Christopher",
                                           email="*****@*****.**"),
                account=auth_pb2.SignupAccount(
                    username="******",
                    password="******",
                    city="New York City",
                    birthdate=
                    "2000-12-31",  # arbitrary birthdate older than 18 years
                    gender="Helicopter",
                    hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST,
                    lat=1,
                    lng=1,
                    radius=100,
                    accept_tos=True,
                ),
                feedback=auth_pb2.ContributorForm(),
            ))

        assert res.flow_token

        with pytest.raises(grpc.RpcError) as e:
            auth_api.SignupFlow(
                auth_pb2.SignupFlowReq(
                    basic=auth_pb2.SignupBasic(name="Franklin",
                                               email="*****@*****.**"),
                    account=auth_pb2.SignupAccount(
                        username="******",
                        password="******",
                        city="Los Santos",
                        birthdate="2010-04-09",  # arbitrary birthdate < 18 yrs
                        gender="Male",
                        hosting_status=api_pb2.HOSTING_STATUS_CAN_HOST,
                        lat=1,
                        lng=1,
                        radius=100,
                        accept_tos=True,
                    ),
                    feedback=auth_pb2.ContributorForm(),
                ))
        assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
        assert e.value.details() == errors.INVALID_BIRTHDATE

        with session_scope() as session:
            assert session.execute(
                select(func.count()).select_from(SignupFlow)).scalar_one() == 1
예제 #7
0
def test_signup_incremental(db):
    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(basic=auth_pb2.SignupBasic(
                name="testing", email="*****@*****.**"), ))

    flow_token = res.flow_token
    assert res.flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert res.need_account
    assert res.need_feedback
    assert res.need_verify_email
    assert res.need_accept_community_guidelines

    # read out the signup token directly from the database for now
    with session_scope() as session:
        flow = session.execute(
            select(SignupFlow).where(
                SignupFlow.flow_token == flow_token)).scalar_one()
        assert flow.email_sent
        assert not flow.email_verified
        email_token = flow.email_token

    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(flow_token=flow_token))

    assert res.flow_token == flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert res.need_account
    assert res.need_feedback
    assert res.need_verify_email
    assert res.need_accept_community_guidelines

    # Add feedback
    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(
                flow_token=flow_token,
                feedback=auth_pb2.ContributorForm(
                    ideas="I'm a robot, incapable of original ideation",
                    features="I love all your features",
                    experience="I haven't done couch surfing before",
                    contribute=auth_pb2.CONTRIBUTE_OPTION_YES,
                    contribute_ways=["serving", "backend"],
                    expertise=
                    "I'd love to be your server: I can compute very fast, but only simple opcodes",
                ),
            ))

    assert res.flow_token == flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert res.need_account
    assert not res.need_feedback
    assert res.need_verify_email
    assert res.need_accept_community_guidelines

    # Agree to community guidelines
    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(
                flow_token=flow_token,
                accept_community_guidelines=wrappers_pb2.BoolValue(value=True),
            ))

    assert res.flow_token == flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert res.need_account
    assert not res.need_feedback
    assert res.need_verify_email
    assert not res.need_accept_community_guidelines

    # Verify email
    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(
                flow_token=flow_token,
                email_token=email_token,
            ))

    assert res.flow_token == flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert res.need_account
    assert not res.need_feedback
    assert not res.need_verify_email
    assert not res.need_accept_community_guidelines

    # Finally finish off account info
    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(
                flow_token=flow_token,
                account=auth_pb2.SignupAccount(
                    username="******",
                    password="******",
                    birthdate="1970-01-01",
                    gender="Bot",
                    hosting_status=api_pb2.HOSTING_STATUS_MAYBE,
                    city="New York City",
                    lat=40.7331,
                    lng=-73.9778,
                    radius=500,
                    accept_tos=True,
                ),
            ))

    assert not res.flow_token
    assert res.HasField("auth_res")
    assert res.auth_res.user_id
    assert not res.auth_res.jailed
    assert not res.need_basic
    assert not res.need_account
    assert not res.need_feedback
    assert not res.need_verify_email
    assert not res.need_accept_community_guidelines

    user_id = res.auth_res.user_id

    sess_token = get_session_cookie_token(metadata_interceptor)

    with api_session(sess_token) as api:
        res = api.GetUser(api_pb2.GetUserReq(user=str(user_id)))

    assert res.username == "frodo"
    assert res.gender == "Bot"
    assert res.hosting_status == api_pb2.HOSTING_STATUS_MAYBE
    assert res.city == "New York City"
    assert res.lat == 40.7331
    assert res.lng == -73.9778
    assert res.radius == 500

    with session_scope() as session:
        form = session.execute(select(ContributorForm)).scalar_one()

        assert form.ideas == "I'm a robot, incapable of original ideation"
        assert form.features == "I love all your features"
        assert form.experience == "I haven't done couch surfing before"
        assert form.contribute == ContributeOption.yes
        assert form.contribute_ways == ["serving", "backend"]
        assert form.expertise == "I'd love to be your server: I can compute very fast, but only simple opcodes"
예제 #8
0
def _quick_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="New York City",
                    lat=40.7331,
                    lng=-73.9778,
                    radius=500,
                    accept_tos=True,
                ),
                feedback=auth_pb2.ContributorForm(),
                accept_community_guidelines=wrappers_pb2.BoolValue(value=True),
            ))

    flow_token = res.flow_token

    assert res.flow_token
    assert not res.HasField("auth_res")
    assert not res.need_basic
    assert not res.need_account
    assert not res.need_feedback
    assert res.need_verify_email

    # read out the signup token directly from the database for now
    with session_scope() as session:
        flow = session.execute(
            select(SignupFlow).where(
                SignupFlow.flow_token == flow_token)).scalar_one()
        assert flow.email_sent
        assert not flow.email_verified
        email_token = flow.email_token

    with auth_api_session() as (auth_api, metadata_interceptor):
        res = auth_api.SignupFlow(
            auth_pb2.SignupFlowReq(email_token=email_token))

    assert not res.flow_token
    assert res.HasField("auth_res")
    assert res.auth_res.user_id
    assert not res.auth_res.jailed
    assert not res.need_basic
    assert not res.need_account
    assert not res.need_feedback
    assert not res.need_verify_email

    user_id = res.auth_res.user_id

    # make sure we got the right token in a cookie
    with session_scope() as session:
        token = (session.execute(
            select(UserSession).join(
                User, UserSession.user_id == User.id).where(
                    User.username == "frodo")).scalar_one()).token
    assert get_session_cookie_token(metadata_interceptor) == token