Exemplo n.º 1
0
def process_send_request_notifications(payload):
    """
    Sends out email notifications for unseen messages in host requests (as surfer or host)
    """
    logger.info(f"Sending out email notifications for unseen messages in host requests")

    with session_scope() as session:
        # requests where this user is surfing
        surfing_reqs = session.execute(
            select(User, HostRequest, func.max(Message.id))
            .where(User.is_visible)
            .join(HostRequest, HostRequest.surfer_user_id == User.id)
            .join(Message, Message.conversation_id == HostRequest.conversation_id)
            .where(Message.id > HostRequest.surfer_last_seen_message_id)
            .where(Message.id > User.last_notified_request_message_id)
            .where(Message.time < now() - timedelta(minutes=5))
            .where(Message.message_type == MessageType.text)
            .group_by(User, HostRequest)
        ).all()

        # where this user is hosting
        hosting_reqs = session.execute(
            select(User, HostRequest, func.max(Message.id))
            .where(User.is_visible)
            .join(HostRequest, HostRequest.host_user_id == User.id)
            .join(Message, Message.conversation_id == HostRequest.conversation_id)
            .where(Message.id > HostRequest.host_last_seen_message_id)
            .where(Message.id > User.last_notified_request_message_id)
            .where(Message.time < now() - timedelta(minutes=5))
            .where(Message.message_type == MessageType.text)
            .group_by(User, HostRequest)
        ).all()

        for user, host_request, max_message_id in surfing_reqs:
            user.last_notified_request_message_id = max(user.last_notified_request_message_id, max_message_id)
            session.commit()

            email.enqueue_email_from_template(
                user.email,
                "unseen_message_guest",
                template_args={
                    "user": user,
                    "host_request": host_request,
                    "host_request_link": urls.host_request_link_guest(),
                },
            )

        for user, host_request, max_message_id in hosting_reqs:
            user.last_notified_request_message_id = max(user.last_notified_request_message_id, max_message_id)
            session.commit()

            email.enqueue_email_from_template(
                user.email,
                "unseen_message_host",
                template_args={
                    "user": user,
                    "host_request": host_request,
                    "host_request_link": urls.host_request_link_host(),
                },
            )
Exemplo n.º 2
0
def test_list_host_requests_active_filter(db):
    user1, token1 = generate_user()
    user2, token2 = generate_user()
    today_plus_2 = (now() + timedelta(days=2)).strftime("%Y-%m-%d")
    today_plus_3 = (now() + timedelta(days=3)).strftime("%Y-%m-%d")

    with requests_session(token1) as api:
        request_id = api.CreateHostRequest(
            requests_pb2.CreateHostRequestReq(
                to_user_id=user2.id,
                from_date=today_plus_2,
                to_date=today_plus_3,
                text="Test request 1")).host_request_id
        api.RespondHostRequest(
            requests_pb2.RespondHostRequestReq(
                host_request_id=request_id,
                status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED))

    with requests_session(token2) as api:
        res = api.ListHostRequests(
            requests_pb2.ListHostRequestsReq(only_received=True))
        assert len(res.host_requests) == 1
        res = api.ListHostRequests(
            requests_pb2.ListHostRequestsReq(only_active=True))
        assert len(res.host_requests) == 0
Exemplo n.º 3
0
def test_get_host_request(db):
    user1, token1 = generate_user()
    user2, token2 = generate_user()
    user3, token3 = generate_user()
    today_plus_2 = (now() + timedelta(days=2)).strftime("%Y-%m-%d")
    today_plus_3 = (now() + timedelta(days=3)).strftime("%Y-%m-%d")
    with requests_session(token1) as api:
        host_request_id = api.CreateHostRequest(
            requests_pb2.CreateHostRequestReq(
                to_user_id=user2.id,
                from_date=today_plus_2,
                to_date=today_plus_3,
                text="Test request 1")).host_request_id

        with pytest.raises(grpc.RpcError) as e:
            api.GetHostRequest(
                requests_pb2.GetHostRequestReq(host_request_id=999))
        assert e.value.code() == grpc.StatusCode.NOT_FOUND

        api.SendHostRequestMessage(
            requests_pb2.SendHostRequestMessageReq(
                host_request_id=host_request_id, text="Test message 1"))

        res = api.GetHostRequest(
            requests_pb2.GetHostRequestReq(host_request_id=host_request_id))
        assert res.latest_message.text.text == "Test message 1"
Exemplo n.º 4
0
    def ConfirmChangeEmail(self, request, context):
        with session_scope() as session:
            user_with_valid_token_from_old_email = session.execute(
                select(User).where(
                    User.old_email_token == request.change_email_token).where(
                        User.old_email_token_created <= now()).where(
                            User.old_email_token_expiry >= now())
            ).scalar_one_or_none()
            user_with_valid_token_from_new_email = session.execute(
                select(User).where(
                    User.new_email_token == request.change_email_token).where(
                        User.new_email_token_created <= now()).where(
                            User.new_email_token_expiry >= now())
            ).scalar_one_or_none()

            if user_with_valid_token_from_old_email:
                user = user_with_valid_token_from_old_email
                user.old_email_token = None
                user.old_email_token_created = None
                user.old_email_token_expiry = None
                user.need_to_confirm_via_old_email = False
            elif user_with_valid_token_from_new_email:
                user = user_with_valid_token_from_new_email
                user.new_email_token = None
                user.new_email_token_created = None
                user.new_email_token_expiry = None
                user.need_to_confirm_via_new_email = False
            else:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.INVALID_TOKEN)

            # Using "___ is False" instead of "not ___" so that "None" doesn't pass
            if user.need_to_confirm_via_old_email is False and user.need_to_confirm_via_new_email is False:
                user.email = user.new_email
                user.new_email = None
                user.need_to_confirm_via_old_email = None
                user.need_to_confirm_via_new_email = None

                notify(
                    user_id=user.id,
                    topic="email_address",
                    key="",
                    action="change",
                    icon="wrench",
                    title=f"Your email was changed",
                    link=urls.account_settings_link(),
                )

                return auth_pb2.ConfirmChangeEmailRes(
                    state=auth_pb2.EMAIL_CONFIRMATION_STATE_SUCCESS)
            elif user.need_to_confirm_via_old_email:
                return auth_pb2.ConfirmChangeEmailRes(
                    state=auth_pb2.
                    EMAIL_CONFIRMATION_STATE_REQUIRES_CONFIRMATION_FROM_OLD_EMAIL
                )
            else:
                return auth_pb2.ConfirmChangeEmailRes(
                    state=auth_pb2.
                    EMAIL_CONFIRMATION_STATE_REQUIRES_CONFIRMATION_FROM_NEW_EMAIL
                )
Exemplo n.º 5
0
def _check_occurrence_time_validity(start_time, end_time, context):
    if start_time < now():
        context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.EVENT_IN_PAST)
    if end_time < start_time:
        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                      errors.EVENT_ENDS_BEFORE_STARTS)
    if end_time - start_time > timedelta(days=7):
        context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.EVENT_TOO_LONG)
    if start_time - now() > timedelta(days=365):
        context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                      errors.EVENT_TOO_FAR_IN_FUTURE)
Exemplo n.º 6
0
    def VerifyPhone(self, request, context):
        if not sms.looks_like_a_code(request.token):
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.WRONG_SMS_CODE)

        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == context.user_id)).scalar_one()
            if user.phone_verification_token is None:
                context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                              errors.NO_PENDING_VERIFICATION)

            if now() - user.phone_verification_sent > SMS_CODE_LIFETIME:
                context.abort(grpc.StatusCode.FAILED_PRECONDITION,
                              errors.NO_PENDING_VERIFICATION)

            if user.phone_verification_attempts > SMS_CODE_ATTEMPTS:
                context.abort(grpc.StatusCode.RESOURCE_EXHAUSTED,
                              errors.TOO_MANY_SMS_CODE_ATTEMPTS)

            if not verify_token(request.token, user.phone_verification_token):
                user.phone_verification_attempts += 1
                session.commit()
                context.abort(grpc.StatusCode.NOT_FOUND, errors.WRONG_SMS_CODE)

            # Delete verifications from everyone else that has this number
            session.execute(
                update(User).where(User.phone == user.phone).where(
                    User.id != context.user_id).values({
                        "phone_verification_verified":
                        None,
                        "phone_verification_attempts":
                        0,
                        "phone_verification_token":
                        None,
                        "phone":
                        None,
                    }).execution_options(synchronize_session=False))

            user.phone_verification_token = None
            user.phone_verification_verified = now()
            user.phone_verification_attempts = 0

            notify(
                user_id=user.id,
                topic="phone_number",
                key="",
                action="verify",
                icon="wrench",
                title=f"Your phone number was verified",
                link=urls.account_settings_link(),
            )

        return empty_pb2.Empty()
Exemplo n.º 7
0
def set_email_change_token(session, user, hours=2):
    """
    Make a new email change token that's valid for `hours` hours for this user

    Note: does not call session.commit()

    Returns token and expiry text
    """
    token = urlsafe_secure_token()
    user.new_email_token = token
    user.new_email_token_created = now()
    user.new_email_token_expiry = now() + datetime.timedelta(hours=hours)
    return token, f"{hours} hours"
Exemplo n.º 8
0
    def ChangePhone(self, request, context):
        phone = request.phone
        # early quick validation
        if phone and not is_e164_format(phone):
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_PHONE)

        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == context.user_id)).scalar_one()
            if not phone:
                user.phone = None
                user.phone_verification_verified = None
                user.phone_verification_token = None
                user.phone_verification_attempts = 0
                return empty_pb2.Empty()

            if not is_known_operator(phone):
                context.abort(grpc.StatusCode.UNIMPLEMENTED,
                              errors.UNRECOGNIZED_PHONE_NUMBER)

            if now(
            ) - user.phone_verification_sent < PHONE_REVERIFICATION_INTERVAL:
                context.abort(grpc.StatusCode.RESOURCE_EXHAUSTED,
                              errors.REVERIFICATION_TOO_EARLY)

            token = sms.generate_random_code()
            result = sms.send_sms(phone, sms.format_message(token))

            if result == "success":
                user.phone = phone
                user.phone_verification_verified = None
                user.phone_verification_token = token
                user.phone_verification_sent = now()
                user.phone_verification_attempts = 0

                notify(
                    user_id=user.id,
                    topic="phone_number",
                    key="",
                    action="change",
                    icon="wrench",
                    title=f"Your phone number was changed",
                    link=urls.account_settings_link(),
                )

                return empty_pb2.Empty()

        context.abort(grpc.StatusCode.UNIMPLEMENTED, result)
Exemplo n.º 9
0
def test_VerifyPhone():
    user, token = generate_user()
    user_id = user.id
    with account_session(token) as account, api_session(token) as api:

        with pytest.raises(grpc.RpcError) as e:
            account.VerifyPhone(account_pb2.VerifyPhoneReq(token="123455"))
        assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION

        res = api.GetUser(api_pb2.GetUserReq(user=str(user_id)))
        assert res.verification == 0.0

        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == user_id)).scalar_one()
            user.phone = "+46701740605"
            user.phone_verification_token = "111112"
            user.phone_verification_sent = now()

        account.VerifyPhone(account_pb2.VerifyPhoneReq(token="111112"))

        res = api.GetUser(api_pb2.GetUserReq(user=str(user_id)))
        assert res.verification == 1.0

        # Phone number should finally show up on in your profile settings
        res = account.GetAccountInfo(empty_pb2.Empty())
        assert res.phone == "+46701740605"
Exemplo n.º 10
0
    def ConfirmDeleteAccount(self, request, context):
        """
        Confirm account deletion using account delete token
        """
        with session_scope() as session:
            res = session.execute(
                select(User, AccountDeletionToken).join(
                    AccountDeletionToken,
                    AccountDeletionToken.user_id == User.id).where(
                        AccountDeletionToken.token == request.token).where(
                            AccountDeletionToken.is_valid)).one_or_none()

            if not res:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.INVALID_TOKEN)

            user, account_deletion_token = res

            session.execute(
                delete(AccountDeletionToken).where(
                    AccountDeletionToken.user_id == user.id))

            undelete_days = 7
            user.is_deleted = True
            user.undelete_until = now() + timedelta(days=undelete_days)
            user.undelete_token = urlsafe_secure_token()

            send_account_deletion_successful_email(user, undelete_days)

        return empty_pb2.Empty()
Exemplo n.º 11
0
def test_purge_password_reset_tokens(db):
    user, api_token = generate_user()

    with session_scope() as session:
        password_reset_token = PasswordResetToken(token=urlsafe_secure_token(),
                                                  user=user,
                                                  expiry=now())
        session.add(password_reset_token)
        assert session.execute(
            select(func.count()).select_from(
                PasswordResetToken)).scalar_one() == 1

    queue_job(BackgroundJobType.purge_password_reset_tokens, empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert session.execute(
            select(func.count()).select_from(
                PasswordResetToken)).scalar_one() == 0

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.completed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.completed)).
                scalar_one() == 0)
Exemplo n.º 12
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),
        )
Exemplo n.º 13
0
def send_signup_email(flow):
    logger.info(f"Sending signup email to {flow.email=}:")

    # whether we've sent an email at all yet
    email_sent_before = flow.email_sent
    if flow.email_verified:
        # we just send a link to continue, not a verification link
        signup_link = urls.signup_link(token=flow.flow_token)
    elif flow.email_token and flow.token_is_valid:
        # if the verification email was sent and still is not expired, just resend the verification email
        signup_link = urls.signup_link(token=flow.email_token)
    else:
        # otherwise send a fresh email with new token
        token = urlsafe_secure_token()
        flow.email_verified = False
        flow.email_token = token
        flow.email_token_expiry = now() + SIGNUP_EMAIL_TOKEN_VALIDITY
        signup_link = urls.signup_link(token=flow.email_token)

    flow.email_sent = True

    logger.info(f"Link is: {signup_link}")
    template = "signup_verify" if not email_sent_before else "signup_continue"
    email.enqueue_email_from_template(flow.email,
                                      template,
                                      template_args={
                                          "flow": flow,
                                          "signup_link": signup_link
                                      })
Exemplo n.º 14
0
def test_account_deletion_successful_email(db):
    user, api_token = generate_user()

    with session_scope() as session:
        user_ = session.execute(select(User)).scalar_one()
        user.undelete_token = "token"
        user.undelete_until = now()
        user.is_deleted = True

    with patch("couchers.email.queue_email") as mock:
        send_account_deletion_successful_email(user, 7)

        assert mock.call_count == 1
        (sender_name, sender_email, recipient, subject, plain, html), _ = mock.call_args
        assert recipient == user.email
        assert "account has been deleted" in subject.lower()
        unique_string = "You have successfully deleted your account from Couchers.org."
        assert unique_string in plain
        assert unique_string in html
        assert "7 days" in plain
        assert "7 days" in html
        url = f"{config['BASE_URL']}/recover-account?token={user.undelete_token}"
        assert url in plain
        assert url in html
        assert "*****@*****.**" in plain
        assert "*****@*****.**" in html
Exemplo n.º 15
0
    def ListAllEvents(self, request, context):
        with session_scope() as session:
            page_size = min(MAX_PAGINATION_LENGTH, request.page_size
                            or MAX_PAGINATION_LENGTH)
            # the page token is a unix timestamp of where we left off
            page_token = dt_from_millis(int(
                request.page_token)) if request.page_token else now()

            occurrences = select(EventOccurrence).join(
                Event, Event.id == EventOccurrence.event_id)

            if not request.past:
                occurrences = occurrences.where(
                    EventOccurrence.end_time > page_token -
                    timedelta(seconds=1)).order_by(
                        EventOccurrence.start_time.asc())
            else:
                occurrences = occurrences.where(
                    EventOccurrence.end_time < page_token +
                    timedelta(seconds=1)).order_by(
                        EventOccurrence.start_time.desc())

            occurrences = occurrences.limit(page_size + 1)
            occurrences = session.execute(occurrences).scalars().all()

            return events_pb2.ListAllEventsRes(
                events=[
                    event_to_pb(session, occurrence, context)
                    for occurrence in occurrences[:page_size]
                ],
                next_page_token=str(millis_from_dt(occurrences[-1].end_time))
                if len(occurrences) > page_size else None,
            )
Exemplo n.º 16
0
def test_purge_account_deletion_tokens(db):
    user, api_token = generate_user()
    user2, api_token2 = generate_user()
    user3, api_token3 = generate_user()

    with session_scope() as session:
        """
        3 cases:
        1) Token is valid
        2) Token expired but account retrievable
        3) Account is irretrievable (and expired)
        """
        account_deletion_tokens = [
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user,
                                 expiry=now() - timedelta(hours=2)),
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user2,
                                 expiry=now()),
            AccountDeletionToken(token=urlsafe_secure_token(),
                                 user=user3,
                                 expiry=now() + timedelta(hours=5)),
        ]
        for token in account_deletion_tokens:
            session.add(token)
        assert session.execute(
            select(func.count()).select_from(
                AccountDeletionToken)).scalar_one() == 3

    queue_job(BackgroundJobType.purge_account_deletion_tokens,
              empty_pb2.Empty())
    process_job()

    with session_scope() as session:
        assert session.execute(
            select(func.count()).select_from(
                AccountDeletionToken)).scalar_one() == 1

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state ==
                BackgroundJobState.completed)).scalar_one() == 1)
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.state != BackgroundJobState.completed)).
                scalar_one() == 0)
Exemplo n.º 17
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
Exemplo n.º 18
0
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
Exemplo n.º 19
0
def new_signup_token(session, email, hours=2):
    """
    Make a signup token that's valid for `hours` hours

    Returns token and expiry text
    """
    token = urlsafe_secure_token()
    signup_token = SignupToken(token=token, email=email, expiry=now() + timedelta(hours=hours))
    session.add(signup_token)
    session.commit()
    return signup_token, f"{hours} hours"
Exemplo n.º 20
0
def new_login_token(session, user, hours=2):
    """
    Make a login token that's valid for `hours` hours

    Returns token and expiry text
    """
    token = urlsafe_secure_token()
    login_token = LoginToken(token=token, user=user, expiry=now() + timedelta(hours=hours))
    session.add(login_token)
    session.commit()
    return login_token, f"{hours} hours"
Exemplo n.º 21
0
def new_password_reset_token(session, user, hours=2):
    """
    Make a password reset token that's valid for `hours` hours

    Returns token and expiry text
    """
    token = urlsafe_secure_token()
    password_reset_token = PasswordResetToken(token=token, user=user, expiry=now() + timedelta(hours=hours))
    session.add(password_reset_token)
    session.commit()
    return password_reset_token, f"{hours} hours"
Exemplo n.º 22
0
def test_get_page(db):
    user1, token1 = generate_user()
    user2, token2 = generate_user()
    with session_scope() as session:
        c_id = create_community(session, 0, 2, "Root node", [user1], [],
                                None).id

    with pages_session(token1) as api:
        time_before_create = now()
        page_id = api.CreatePlace(
            pages_pb2.CreatePlaceReq(
                title="dummy title",
                content="dummy content",
                address="dummy address",
                location=pages_pb2.Coordinate(
                    lat=1,
                    lng=1,
                ),
            )).page_id

    with pages_session(token2) as api:
        time_before_get = now()
        res = api.GetPage(pages_pb2.GetPageReq(page_id=page_id))
        assert res.title == "dummy title"
        assert res.content == "dummy content"
        assert res.address == "dummy address"
        assert res.location.lat == 1
        assert res.location.lng == 1
        assert res.slug == "dummy-title"
        assert time_before_create < to_aware_datetime(
            res.created) < time_before_get
        assert time_before_create < to_aware_datetime(
            res.last_edited) < time_before_get
        assert res.last_editor_user_id == user1.id
        assert res.creator_user_id == user1.id
        assert res.owner_user_id == user1.id
        assert not res.owner_community_id
        assert not res.owner_group_id
        assert res.editor_user_ids == [user1.id]
        assert not res.can_edit
        assert not res.can_moderate
Exemplo n.º 23
0
def create_friend_reference(session, from_user_id, to_user_id, reference_age):
    reference = Reference(
        time=now() - reference_age,
        from_user_id=from_user_id,
        to_user_id=to_user_id,
        reference_type=ReferenceType.friend,
        text="Test friend request",
        rating=0.4,
        was_appropriate=True,
    )
    session.add(reference)
    session.commit()
    return reference.id
Exemplo n.º 24
0
def create_event(token, community_id, group_id, title, content, start_td):
    with events_session(token) as api:
        res = api.CreateEvent(
            events_pb2.CreateEventReq(
                title=title,
                content=content,
                offline_information=events_pb2.OfflineEventInformation(
                    address="Near Null Island",
                    lat=0.1,
                    lng=0.2,
                ),
                start_time=Timestamp_from_datetime(now() + start_td),
                end_time=Timestamp_from_datetime(now() + start_td +
                                                 timedelta(hours=2)),
                timezone="UTC",
            ))
        api.TransferEvent(
            events_pb2.TransferEventReq(
                event_id=res.event_id,
                new_owner_community_id=community_id,
                new_owner_group_id=group_id,
            ))
Exemplo n.º 25
0
def test_process_send_onboarding_emails(db):
    # needs to get first onboarding email
    user1, token1 = generate_user(onboarding_emails_sent=0,
                                  last_onboarding_email_sent=None)

    process_send_onboarding_emails(empty_pb2.Empty())

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.job_type ==
                BackgroundJobType.send_email)).scalar_one() == 1)

    # needs to get second onboarding email, but not yet
    user2, token2 = generate_user(onboarding_emails_sent=1,
                                  last_onboarding_email_sent=now() -
                                  timedelta(days=6))

    process_send_onboarding_emails(empty_pb2.Empty())

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.job_type ==
                BackgroundJobType.send_email)).scalar_one() == 1)

    # needs to get second onboarding email
    user3, token3 = generate_user(onboarding_emails_sent=1,
                                  last_onboarding_email_sent=now() -
                                  timedelta(days=8))

    process_send_onboarding_emails(empty_pb2.Empty())

    with session_scope() as session:
        assert (session.execute(
            select(func.count()).select_from(BackgroundJob).where(
                BackgroundJob.job_type ==
                BackgroundJobType.send_email)).scalar_one() == 2)
Exemplo n.º 26
0
def process_send_onboarding_emails(payload):
    """
    Sends out onboarding emails
    """
    logger.info(f"Sending out onboarding emails")

    with session_scope() as session:
        # first onboarding email
        users = (
            session.execute(select(User).where(User.is_visible).where(User.onboarding_emails_sent == 0)).scalars().all()
        )

        for user in users:
            send_onboarding_email(user, email_number=1)
            user.onboarding_emails_sent = 1
            user.last_onboarding_email_sent = now()
            session.commit()

        # second onboarding email
        # sent after a week if the user has no profile or their "about me" section is less than 20 characters long
        users = (
            session.execute(
                select(User)
                .where(User.is_visible)
                .where(User.onboarding_emails_sent == 1)
                .where(now() - User.last_onboarding_email_sent > timedelta(days=7))
                .where(User.has_completed_profile == False)
            )
            .scalars()
            .all()
        )

        for user in users:
            send_onboarding_email(user, email_number=2)
            user.onboarding_emails_sent = 2
            user.last_onboarding_email_sent = now()
            session.commit()
Exemplo n.º 27
0
def test_create_page_place(db):
    user, token = generate_user()
    with session_scope() as session:
        c_id = create_community(session, 0, 2, "Root node", [user], [],
                                None).id

    with pages_session(token) as api:
        time_before = now()
        res = api.CreatePlace(
            pages_pb2.CreatePlaceReq(
                title="dummy !#¤%&/-*' title",
                content="dummy content",
                address="dummy address",
                location=pages_pb2.Coordinate(
                    lat=1,
                    lng=1,
                ),
            ))

        assert res.title == "dummy !#¤%&/-*' title"
        assert res.type == pages_pb2.PAGE_TYPE_PLACE
        assert res.content == "dummy content"
        assert res.address == "dummy address"
        assert res.location.lat == 1
        assert res.location.lng == 1
        assert res.slug == "dummy-title"
        assert time_before < to_aware_datetime(res.created) < now()
        assert time_before < to_aware_datetime(res.last_edited) < now()
        assert res.last_editor_user_id == user.id
        assert res.creator_user_id == user.id
        assert res.owner_user_id == user.id
        assert not res.owner_community_id
        assert not res.owner_group_id
        assert res.editor_user_ids == [user.id]
        assert res.can_edit
        assert res.can_moderate
Exemplo n.º 28
0
def create_host_reference(session,
                          from_user_id,
                          to_user_id,
                          reference_age,
                          *,
                          surfing=True,
                          host_request_id=None):
    if host_request_id:
        actual_host_request_id = host_request_id
    else:
        if surfing:
            actual_host_request_id = host_request_id or create_host_request(
                session, from_user_id, to_user_id,
                reference_age - timedelta(days=1))
        else:
            actual_host_request_id = host_request_id or create_host_request(
                session, to_user_id, from_user_id,
                reference_age - timedelta(days=1))

    host_request = session.query(HostRequest).filter(
        HostRequest.conversation_id == actual_host_request_id).one()

    other_reference = (session.query(Reference).filter(
        Reference.host_request_id == host_request.conversation_id).filter(
            Reference.to_user_id == from_user_id).one_or_none())

    reference = Reference(
        time=now() - reference_age,
        from_user_id=from_user_id,
        host_request_id=host_request.conversation_id,
        text="Dummy reference",
        rating=0.5,
        was_appropriate=True,
    )

    if host_request.from_user_id == from_user_id:
        reference.reference_type = ReferenceType.surfed
        reference.to_user_id = host_request.to_user_id
        assert from_user_id == host_request.from_user_id
    else:
        reference.reference_type = ReferenceType.hosted
        reference.to_user_id = host_request.from_user_id
        assert from_user_id == host_request.to_user_id

    session.add(reference)
    session.commit()
    return reference.id, actual_host_request_id
Exemplo n.º 29
0
    def Deauthenticate(self, request, context):
        """
        Removes an active cookie session.
        """
        token = parse_session_cookie(dict(context.invocation_metadata()))
        logger.info(f"Deauthenticate(token={token})")

        # if we had a token, try to remove the session
        if token:
            delete_session(token)

        # set the cookie to an empty string and expire immediately, should remove it from the browser
        context.send_initial_metadata([
            ("set-cookie", create_session_cookie("", now())),
        ])

        return empty_pb2.Empty()
Exemplo n.º 30
0
def test_VerifyPhone_antibrute():
    user, token = generate_user()
    user_id = user.id
    with account_session(token) as account, api_session(token) as api:

        with session_scope() as session:
            user = session.execute(
                select(User).where(User.id == user_id)).scalar_one()
            user.phone_verification_token = "111112"
            user.phone_verification_sent = now()
            user.phone = "+46701740605"

        for i in range(10):
            with pytest.raises(grpc.RpcError) as e:
                account.VerifyPhone(account_pb2.VerifyPhoneReq(token="123455"))
            if e.value.code() != grpc.StatusCode.NOT_FOUND:
                break
        assert e.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED