Exemple #1
0
def add_message(db, text, author_id, conversation_id):
    with session_scope(db) as session:
        message = Message(conversation_id=conversation_id,
                          author_id=author_id,
                          text=text,
                          message_type=MessageType.text)

        session.add(message)
Exemple #2
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 #3
0
def create_host_request(session,
                        from_user_id,
                        to_user_id,
                        host_request_age=timedelta(days=15),
                        status=HostRequestStatus.confirmed):
    """
    Create a host request that's `host_request_age` old
    """
    from_date = today() - host_request_age - timedelta(days=2)
    to_date = today() - host_request_age
    fake_created = now() - host_request_age - timedelta(days=3)
    conversation = Conversation()
    session.add(conversation)
    session.flush()
    session.add(
        Message(
            time=fake_created + timedelta(seconds=1),
            conversation_id=conversation.id,
            author_id=from_user_id,
            message_type=MessageType.chat_created,
        ))
    message = Message(
        time=fake_created + timedelta(seconds=2),
        conversation_id=conversation.id,
        author_id=from_user_id,
        text="Hi, I'm requesting to be hosted.",
        message_type=MessageType.text,
    )
    session.add(message)
    session.flush()
    host_request = HostRequest(
        conversation_id=conversation.id,
        from_user_id=from_user_id,
        to_user_id=to_user_id,
        from_date=from_date,
        to_date=to_date,
        status=status,
        from_last_seen_message_id=message.id,
    )
    session.add(host_request)
    session.commit()
    # send_host_request_email(host_request)
    return host_request.conversation_id
Exemple #4
0
def _add_message_to_subscription(session, subscription, **kwargs):
    """
    Creates a new message for a subscription, from the user whose subscription that is. Updates last seen message id

    Specify the keyword args for Message
    """
    message = Message(conversation=subscription.group_chat.conversation,
                      author_id=subscription.user_id,
                      **kwargs)

    session.add(message)
    session.flush()

    subscription.last_seen_message_id = message.id

    return message
def _add_message_to_subscription(session, subscription, **kwargs):
    """
    Creates a new message for a subscription, from the user whose subscription that is. Updates last seen message id

    Specify the keyword args for Message
    """
    message = Message(conversation=subscription.group_chat.conversation, author_id=subscription.user_id, **kwargs)

    session.add(message)
    session.flush()

    subscription.last_seen_message_id = message.id

    # generate notifications in the background
    queue_job(
        job_type=BackgroundJobType.generate_message_notifications,
        payload=jobs_pb2.GenerateMessageNotificationsPayload(
            message_id=message.id,
        ),
    )

    return message
Exemple #6
0
    def SendHostRequestMessage(self, request, context):
        if request.text == "":
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_MESSAGE)
        with session_scope() as session:
            host_request = (session.query(HostRequest).filter(
                HostRequest.conversation_id ==
                request.host_request_id).one_or_none())

            if not host_request:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.from_user_id != context.user_id and host_request.to_user_id != context.user_id:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            # TODO: It is not very user-friendly to prevent messages for confirmed requests
            # but we also don't want people to use requests as normal messages...

            if (host_request.status == HostRequestStatus.rejected
                    or host_request.status == HostRequestStatus.confirmed
                    or host_request.status == HostRequestStatus.cancelled):
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.HOST_REQUEST_CLOSED)

            message = Message()
            message.conversation_id = host_request.conversation_id
            message.author_id = context.user_id
            message.message_type = MessageType.text
            message.text = request.text
            session.add(message)
            session.flush()

            if host_request.from_user_id == context.user_id:
                host_request.from_last_seen_message_id = message.id
            else:
                host_request.to_last_seen_message_id = message.id
            session.commit()

            return empty_pb2.Empty()
Exemple #7
0
    def SendHostRequestMessage(self, request, context):
        if request.text == "":
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_MESSAGE)
        with session_scope() as session:
            host_request = (session.query(HostRequest).filter(
                HostRequest.conversation_id ==
                request.host_request_id).one_or_none())

            if not host_request:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.from_user_id != context.user_id and host_request.to_user_id != context.user_id:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.status == HostRequestStatus.rejected or host_request.status == HostRequestStatus.cancelled:
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.HOST_REQUEST_CLOSED)

            if host_request.end_time < now():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.HOST_REQUEST_IN_PAST)

            message = Message()
            message.conversation_id = host_request.conversation_id
            message.author_id = context.user_id
            message.message_type = MessageType.text
            message.text = request.text
            session.add(message)
            session.flush()

            if host_request.from_user_id == context.user_id:
                host_request.from_last_seen_message_id = message.id
            else:
                host_request.to_last_seen_message_id = message.id
            session.commit()

            return empty_pb2.Empty()
Exemple #8
0
def add_dummy_users():
    try:
        logger.info(f"Adding dummy users")
        with session_scope() as session:
            with open("src/data/dummy_users.json", "r") as file:
                data = json.loads(file.read())

            for user in data["users"]:
                new_user = User(
                    username=user["username"],
                    email=user["email"],
                    hashed_password=hash_password(user["password"])
                    if user["password"] else None,
                    name=user["name"],
                    city=user["location"]["city"],
                    geom=create_coordinate(user["location"]["lat"],
                                           user["location"]["lng"]),
                    geom_radius=user["location"]["radius"],
                    verification=user["verification"],
                    community_standing=user["community_standing"],
                    birthdate=date(year=user["birthdate"]["year"],
                                   month=user["birthdate"]["month"],
                                   day=user["birthdate"]["day"]),
                    gender=user["gender"],
                    languages="|".join(user["languages"]),
                    occupation=user["occupation"],
                    about_me=user["about_me"],
                    about_place=user["about_place"],
                    countries_visited="|".join(user["countries_visited"]),
                    countries_lived="|".join(user["countries_lived"]),
                    hosting_status=hostingstatus2sql[HostingStatus.Value(
                        user["hosting_status"])]
                    if "hosting_status" in user else None,
                )
                session.add(new_user)

            session.commit()

            for username1, username2 in data["friendships"]:
                friend_relationship = FriendRelationship(
                    from_user_id=get_user_by_field(session, username1).id,
                    to_user_id=get_user_by_field(session, username2).id,
                    status=FriendStatus.accepted,
                )
                session.add(friend_relationship)

            session.commit()

            for reference in data["references"]:
                reference_type = (ReferenceType.HOSTED
                                  if reference["type"] == "hosted" else
                                  (ReferenceType.SURFED if reference["type"]
                                   == "surfed" else ReferenceType.FRIEND))
                new_reference = Reference(
                    from_user_id=get_user_by_field(session,
                                                   reference["from"]).id,
                    to_user_id=get_user_by_field(session, reference["to"]).id,
                    reference_type=reference_type,
                    text=reference["text"],
                    rating=reference["rating"],
                    was_safe=reference["was_safe"],
                )
                session.add(new_reference)

            session.commit()

            for group_chat in data["group_chats"]:
                # Create the chat
                creator = group_chat["creator"]

                conversation = Conversation()
                session.add(conversation)

                chat = GroupChat(
                    conversation=conversation,
                    title=group_chat["title"],
                    creator_id=get_user_by_field(session, creator).id,
                    is_dm=group_chat["is_dm"],
                )
                session.add(chat)

                for participant in group_chat["participants"]:
                    subscription = GroupChatSubscription(
                        user_id=get_user_by_field(session,
                                                  participant["username"]).id,
                        group_chat=chat,
                        role=GroupChatRole.admin if participant["username"]
                        == creator else GroupChatRole.participant,
                        joined=parser.isoparse(participant["joined"]),
                    )
                    session.add(subscription)

                for message in group_chat["messages"]:
                    session.add(
                        Message(
                            message_type=MessageType.text,
                            conversation=chat.conversation,
                            author_id=get_user_by_field(
                                session, message["author"]).id,
                            time=parser.isoparse(message["time"]),
                            text=message["message"],
                        ))

            session.commit()

    except IntegrityError:
        logger.error("Failed to insert dummy users, is it already inserted?")
Exemple #9
0
    def CreateHostRequest(self, request, context):
        with session_scope() as session:
            if request.to_user_id == context.user_id:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.CANT_REQUEST_SELF)
            # just to check the host exists
            host = session.query(User).filter(
                User.id == request.to_user_id).one_or_none()
            if not host:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.USER_NOT_FOUND)

            from_date = parse_date(request.from_date)
            to_date = parse_date(request.to_date)

            if not from_date or not to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_DATE)

            today = today_in_timezone(host.timezone)

            # request starts from the past
            if from_date < today:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_BEFORE_TODAY)

            # from_date is not >= to_date
            if from_date >= to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_TO)

            # No need to check today > to_date

            if from_date - today > timedelta(days=365):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_ONE_YEAR)

            if to_date - from_date > timedelta(days=365):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_TO_AFTER_ONE_YEAR)

            conversation = Conversation()
            session.add(conversation)
            session.flush()

            session.add(
                Message(
                    conversation_id=conversation.id,
                    author_id=context.user_id,
                    message_type=MessageType.chat_created,
                ))

            message = Message(
                conversation_id=conversation.id,
                author_id=context.user_id,
                text=request.text,
                message_type=MessageType.text,
            )
            session.add(message)
            session.flush()

            host_request = HostRequest(
                conversation_id=conversation.id,
                from_user_id=context.user_id,
                to_user_id=host.id,
                from_date=from_date,
                to_date=to_date,
                status=HostRequestStatus.pending,
                from_last_seen_message_id=message.id,
                # TODO: tz
                # timezone=host.timezone,
            )
            session.add(host_request)
            session.flush()

            send_host_request_email(host_request)

            return requests_pb2.CreateHostRequestRes(
                host_request_id=host_request.conversation_id)
Exemple #10
0
    def RespondHostRequest(self, request, context):
        with session_scope() as session:
            host_request = (session.query(HostRequest).filter(
                HostRequest.conversation_id ==
                request.host_request_id).one_or_none())

            if not host_request:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.from_user_id != context.user_id and host_request.to_user_id != context.user_id:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_PENDING:
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.INVALID_HOST_REQUEST_STATUS)

            if host_request.end_time < now():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.HOST_REQUEST_IN_PAST)

            control_message = Message()

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED:
                # only host can accept
                if context.user_id != host_request.to_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can't accept a cancelled or confirmed request (only reject), or already accepted
                if (host_request.status == HostRequestStatus.cancelled
                        or host_request.status == HostRequestStatus.confirmed
                        or host_request.status == HostRequestStatus.accepted):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.accepted
                host_request.status = HostRequestStatus.accepted

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED:
                # only host can reject
                if context.user_id != host_request.to_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can't reject a cancelled or already rejected request
                if (host_request.status == HostRequestStatus.cancelled
                        or host_request.status == HostRequestStatus.rejected):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.rejected
                host_request.status = HostRequestStatus.rejected

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED:
                # only hostee can confirm
                if context.user_id != host_request.from_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can only confirm an accepted request
                if host_request.status != HostRequestStatus.accepted:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.confirmed
                host_request.status = HostRequestStatus.confirmed

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED:
                # only hostee can cancel
                if context.user_id != host_request.from_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can't' cancel an already cancelled or rejected request
                if (host_request.status == HostRequestStatus.rejected
                        or host_request.status == HostRequestStatus.cancelled):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.cancelled
                host_request.status = HostRequestStatus.cancelled

            control_message.message_type = MessageType.host_request_status_changed
            control_message.conversation_id = host_request.conversation_id
            control_message.author_id = context.user_id
            session.add(control_message)

            if request.text:
                latest_message = Message()
                latest_message.conversation_id = host_request.conversation_id
                latest_message.text = request.text
                latest_message.author_id = context.user_id
                latest_message.message_type = MessageType.text
                session.add(latest_message)
            else:
                latest_message = control_message

            session.flush()

            if host_request.from_user_id == context.user_id:
                host_request.from_last_seen_message_id = latest_message.id
            else:
                host_request.to_last_seen_message_id = latest_message.id
            session.commit()

            return empty_pb2.Empty()
Exemple #11
0
def add_dummy_users():
    logger.info(f"Adding dummy users")
    with session_scope() as session:
        if session.execute(select(
                func.count()).select_from(User)).scalar_one() > 0:
            logger.info("Users not empty, not adding dummy users")
            return

        with open(SRC_DIR + "/data/dummy_users.json", "r") as f:
            data = json.loads(f.read())

        for user in data["users"]:
            new_user = User(
                username=user["username"],
                email=user["email"],
                hashed_password=hash_password(user["password"])
                if user["password"] else None,
                name=user["name"],
                city=user["location"]["city"],
                geom=create_coordinate(user["location"]["lat"],
                                       user["location"]["lng"]),
                geom_radius=user["location"]["radius"],
                community_standing=user["community_standing"],
                birthdate=date(year=user["birthdate"]["year"],
                               month=user["birthdate"]["month"],
                               day=user["birthdate"]["day"]),
                gender=user["gender"],
                occupation=user["occupation"],
                about_me=user["about_me"],
                about_place=user["about_place"],
                hosting_status=hostingstatus2sql[HostingStatus.Value(
                    user["hosting_status"] if "hosting_status" in
                    user else "HOSTING_STATUS_CANT_HOST")],
                new_notifications_enabled=True,
                accepted_tos=TOS_VERSION,
                accepted_community_guidelines=GUIDELINES_VERSION,
            )
            session.add(new_user)
            session.flush()

            for language in user["languages"]:
                session.add(
                    LanguageAbility(user_id=new_user.id,
                                    language_code=language[0],
                                    fluency=LanguageFluency[language[1]]))
            for region in user["regions_visited"]:
                session.add(
                    RegionVisited(user_id=new_user.id, region_code=region))
            for region in user["regions_lived"]:
                session.add(
                    RegionLived(user_id=new_user.id, region_code=region))

        session.commit()

        for username1, username2 in data["friendships"]:
            friend_relationship = FriendRelationship(
                from_user_id=session.execute(
                    select(User).where(
                        User.username == username1)).scalar_one().id,
                to_user_id=session.execute(
                    select(User).where(
                        User.username == username2)).scalar_one().id,
                status=FriendStatus.accepted,
            )
            session.add(friend_relationship)

        session.commit()

        for reference in data["references"]:
            reference_type = (ReferenceType.hosted
                              if reference["type"] == "hosted" else
                              (ReferenceType.surfed if reference["type"]
                               == "surfed" else ReferenceType.friend))
            new_reference = Reference(
                from_user_id=session.execute(
                    select(User).where(
                        User.username == reference["from"])).scalar_one().id,
                to_user_id=session.execute(
                    select(User).where(
                        User.username == reference["to"])).scalar_one().id,
                reference_type=reference_type,
                text=reference["text"],
                rating=reference["rating"],
                was_appropriate=reference["was_appropriate"],
            )
            session.add(new_reference)

        session.commit()

        for group_chat in data["group_chats"]:
            # Create the chat
            creator = group_chat["creator"]

            conversation = Conversation()
            session.add(conversation)

            chat = GroupChat(
                conversation=conversation,
                title=group_chat["title"],
                creator_id=session.execute(
                    select(User).where(
                        User.username == creator)).scalar_one().id,
                is_dm=group_chat["is_dm"],
            )
            session.add(chat)

            for participant in group_chat["participants"]:
                subscription = GroupChatSubscription(
                    user_id=session.execute(
                        select(User).where(
                            User.username ==
                            participant["username"])).scalar_one().id,
                    group_chat=chat,
                    role=GroupChatRole.admin if participant["username"]
                    == creator else GroupChatRole.participant,
                    joined=parser.isoparse(participant["joined"]),
                )
                session.add(subscription)

            for message in group_chat["messages"]:
                session.add(
                    Message(
                        message_type=MessageType.text,
                        conversation=chat.conversation,
                        author_id=session.execute(
                            select(User).where(
                                User.username ==
                                message["author"])).scalar_one().id,
                        time=parser.isoparse(message["time"]),
                        text=message["message"],
                    ))

        session.commit()
Exemple #12
0
    def CreateHostRequest(self, request, context):
        with session_scope() as session:
            if request.to_user_id == context.user_id:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.CANT_REQUEST_SELF)
            # just to check the host exists
            host = session.query(User).filter(
                User.id == request.to_user_id).one_or_none()
            if not host:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.USER_NOT_FOUND)

            if not is_valid_date(request.from_date) or not is_valid_date(
                    request.to_date):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_DATE)

            # today is not > from_date
            if least_current_date() > request.from_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_BEFORE_TODAY)

            # from_date is not >= to_date
            if request.from_date >= request.to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_TO)

            # No need to check today > to_date

            today = date.fromisoformat(largest_current_date())
            today_plus_one_year = today.replace(year=today.year +
                                                1).isoformat()
            if request.from_date > today_plus_one_year:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_ONE_YEAR)

            from_date = date.fromisoformat(request.from_date)
            from_date_plus_one_year = (from_date.replace(year=from_date.year +
                                                         1)).isoformat()
            if request.to_date > from_date_plus_one_year:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_TO_AFTER_ONE_YEAR)

            conversation = Conversation()
            session.add(conversation)
            session.flush()

            created_message = Message()
            created_message.conversation_id = conversation.id
            created_message.author_id = context.user_id
            created_message.message_type = MessageType.chat_created
            session.add(created_message)
            session.commit()

            message = Message()
            message.conversation_id = conversation.id
            message.author_id = context.user_id
            message.text = request.text
            message.message_type = MessageType.text
            session.add(message)
            session.flush()

            host_request = HostRequest()
            host_request.conversation_id = conversation.id
            host_request.from_user_id = context.user_id
            host_request.to_user_id = host.id
            host_request.from_date = request.from_date
            host_request.to_date = request.to_date
            host_request.status = HostRequestStatus.pending
            host_request.from_last_seen_message_id = message.id
            session.add(host_request)
            session.flush()

            send_host_request_email(host_request)

            return requests_pb2.CreateHostRequestRes(
                host_request_id=host_request.conversation_id)
Exemple #13
0
    def CreateHostRequest(self, request, context):
        with session_scope() as session:
            if request.host_user_id == context.user_id:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.CANT_REQUEST_SELF)

            # just to check host exists and is visible
            host = session.execute(
                select(User).where_users_visible(context).where(
                    User.id == request.host_user_id)).scalar_one_or_none()
            if not host:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.USER_NOT_FOUND)

            from_date = parse_date(request.from_date)
            to_date = parse_date(request.to_date)

            if not from_date or not to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.INVALID_DATE)

            today = today_in_timezone(host.timezone)

            # request starts from the past
            if from_date < today:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_BEFORE_TODAY)

            # from_date is not >= to_date
            if from_date >= to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_TO)

            # No need to check today > to_date

            if from_date - today > timedelta(days=365):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_FROM_AFTER_ONE_YEAR)

            if to_date - from_date > timedelta(days=365):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.DATE_TO_AFTER_ONE_YEAR)

            conversation = Conversation()
            session.add(conversation)
            session.flush()

            session.add(
                Message(
                    conversation_id=conversation.id,
                    author_id=context.user_id,
                    message_type=MessageType.chat_created,
                ))

            message = Message(
                conversation_id=conversation.id,
                author_id=context.user_id,
                text=request.text,
                message_type=MessageType.text,
            )
            session.add(message)
            session.flush()

            host_request = HostRequest(
                conversation_id=conversation.id,
                surfer_user_id=context.user_id,
                host_user_id=host.id,
                from_date=from_date,
                to_date=to_date,
                status=HostRequestStatus.pending,
                surfer_last_seen_message_id=message.id,
                # TODO: tz
                # timezone=host.timezone,
            )
            session.add(host_request)
            session.commit()

            send_new_host_request_email(host_request)

            notify(
                user_id=host_request.host_user_id,
                topic="host_request",
                action="create",
                key=str(host_request.surfer_user_id),
                avatar_key=host_request.surfer.avatar.thumbnail_url
                if host_request.surfer.avatar else None,
                title=
                f"**{host_request.surfer.name}** sent you a hosting request",
                content=request.text,
                link=urls.host_request_link_host(),
            )

            return requests_pb2.CreateHostRequestRes(
                host_request_id=host_request.conversation_id)
Exemple #14
0
    def SendHostRequestMessage(self, request, context):
        if request.text == "":
            context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                          errors.INVALID_MESSAGE)
        with session_scope() as session:
            host_request = session.execute(
                select(HostRequest).where(
                    HostRequest.conversation_id ==
                    request.host_request_id)).scalar_one_or_none()

            if not host_request:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.surfer_user_id != context.user_id and host_request.host_user_id != context.user_id:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.status == HostRequestStatus.rejected or host_request.status == HostRequestStatus.cancelled:
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.HOST_REQUEST_CLOSED)

            if host_request.end_time < now():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.HOST_REQUEST_IN_PAST)

            message = Message()
            message.conversation_id = host_request.conversation_id
            message.author_id = context.user_id
            message.message_type = MessageType.text
            message.text = request.text
            session.add(message)
            session.flush()

            if host_request.surfer_user_id == context.user_id:
                host_request.surfer_last_seen_message_id = message.id

                notify(
                    user_id=host_request.host_user_id,
                    topic="host_request",
                    action="message",
                    key=str(host_request.surfer_user_id),
                    avatar_key=host_request.surfer.avatar.thumbnail_url
                    if host_request.surfer.avatar else None,
                    title=
                    f"**{host_request.surfer.name}** sent a message in their host request",
                    link=urls.host_request_link_host(),
                )

            else:
                host_request.host_last_seen_message_id = message.id

                notify(
                    user_id=host_request.surfer_user_id,
                    topic="host_request",
                    action="message",
                    key=str(host_request.host_user_id),
                    avatar_key=host_request.host.avatar.thumbnail_url
                    if host_request.host.avatar else None,
                    title=
                    f"**{host_request.host.name}** sent a message in your host request",
                    link=urls.host_request_link_guest(),
                )

            session.commit()

            return empty_pb2.Empty()
Exemple #15
0
    def RespondHostRequest(self, request, context):
        with session_scope() as session:
            host_request = session.execute(
                select(HostRequest).where_users_column_visible(
                    context,
                    HostRequest.surfer_user_id).where_users_column_visible(
                        context, HostRequest.host_user_id).where(
                            HostRequest.conversation_id ==
                            request.host_request_id)).scalar_one_or_none()

            if not host_request:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if host_request.surfer_user_id != context.user_id and host_request.host_user_id != context.user_id:
                context.abort(grpc.StatusCode.NOT_FOUND,
                              errors.HOST_REQUEST_NOT_FOUND)

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_PENDING:
                context.abort(grpc.StatusCode.PERMISSION_DENIED,
                              errors.INVALID_HOST_REQUEST_STATUS)

            if host_request.end_time < now():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT,
                              errors.HOST_REQUEST_IN_PAST)

            control_message = Message()

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED:
                # only host can accept
                if context.user_id != host_request.host_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.NOT_THE_HOST)
                # can't accept a cancelled or confirmed request (only reject), or already accepted
                if (host_request.status == HostRequestStatus.cancelled
                        or host_request.status == HostRequestStatus.confirmed
                        or host_request.status == HostRequestStatus.accepted):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.accepted
                host_request.status = HostRequestStatus.accepted

                send_host_request_accepted_email_to_guest(host_request)

                notify(
                    user_id=host_request.surfer_user_id,
                    topic="host_request",
                    action="accept",
                    key=str(host_request.host_user_id),
                    avatar_key=host_request.host.avatar.thumbnail_url
                    if host_request.host.avatar else None,
                    title=
                    f"**{host_request.host.name}** accepted your host request",
                    link=urls.host_request_link_guest(),
                )

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED:
                # only host can reject
                if context.user_id != host_request.host_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can't reject a cancelled or already rejected request
                if (host_request.status == HostRequestStatus.cancelled
                        or host_request.status == HostRequestStatus.rejected):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.rejected
                host_request.status = HostRequestStatus.rejected

                send_host_request_rejected_email_to_guest(host_request)

                notify(
                    user_id=host_request.surfer_user_id,
                    topic="host_request",
                    action="reject",
                    key=str(host_request.host_user_id),
                    avatar_key=host_request.host.avatar.thumbnail_url
                    if host_request.host.avatar else None,
                    title=
                    f"**{host_request.host.name}** rejected your host request",
                    link=urls.host_request_link_guest(),
                )

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED:
                # only hostee can confirm
                if context.user_id != host_request.surfer_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can only confirm an accepted request
                if host_request.status != HostRequestStatus.accepted:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.confirmed
                host_request.status = HostRequestStatus.confirmed

                send_host_request_confirmed_email_to_host(host_request)

                notify(
                    user_id=host_request.host_user_id,
                    topic="host_request",
                    action="confirm",
                    key=str(host_request.surfer_user_id),
                    avatar_key=host_request.surfer.avatar.thumbnail_url
                    if host_request.surfer.avatar else None,
                    title=
                    f"**{host_request.surfer.name}** confirmed their host request",
                    link=urls.host_request_link_host(),
                )

            if request.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED:
                # only hostee can cancel
                if context.user_id != host_request.surfer_user_id:
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                # can't' cancel an already cancelled or rejected request
                if (host_request.status == HostRequestStatus.rejected
                        or host_request.status == HostRequestStatus.cancelled):
                    context.abort(grpc.StatusCode.PERMISSION_DENIED,
                                  errors.INVALID_HOST_REQUEST_STATUS)
                control_message.host_request_status_target = HostRequestStatus.cancelled
                host_request.status = HostRequestStatus.cancelled

                send_host_request_cancelled_email_to_host(host_request)

                notify(
                    user_id=host_request.host_user_id,
                    topic="host_request",
                    action="cancel",
                    key=str(host_request.surfer_user_id),
                    avatar_key=host_request.surfer.avatar.thumbnail_url
                    if host_request.surfer.avatar else None,
                    title=
                    f"**{host_request.surfer.name}** cancelled their host request",
                    link=urls.host_request_link_host(),
                )

            control_message.message_type = MessageType.host_request_status_changed
            control_message.conversation_id = host_request.conversation_id
            control_message.author_id = context.user_id
            session.add(control_message)

            if request.text:
                latest_message = Message()
                latest_message.conversation_id = host_request.conversation_id
                latest_message.text = request.text
                latest_message.author_id = context.user_id
                latest_message.message_type = MessageType.text
                session.add(latest_message)
            else:
                latest_message = control_message

            session.flush()

            if host_request.surfer_user_id == context.user_id:
                host_request.surfer_last_seen_message_id = latest_message.id
            else:
                host_request.host_last_seen_message_id = latest_message.id
            session.commit()

            return empty_pb2.Empty()
Exemple #16
0
    def CreateHostRequest(self, request, context):
        with session_scope(self._Session) as session:
            if request.to_user_id == context.user_id:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.CANT_REQUEST_SELF)
            # just to check the host exists
            host = session.query(User).filter(User.id == request.to_user_id).one_or_none()
            if not host:
                context.abort(grpc.StatusCode.NOT_FOUND, errors.USER_NOT_FOUND)

            if not is_valid_date(request.from_date) or not is_valid_date(request.to_date):
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.INVALID_DATE)

            if request.from_date >= request.to_date:
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.DATE_FROM_AFTER_TO)

            if request.to_date < least_current_date():
                context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.DATE_TO_BEFORE_TODAY)

            conversation = Conversation()
            session.add(conversation)
            session.flush()

            created_message = Message()
            created_message.conversation_id = conversation.id
            created_message.author_id = context.user_id
            created_message.message_type = MessageType.chat_created
            session.add(created_message)
            session.commit()

            message = Message()
            message.conversation_id = conversation.id
            message.author_id = context.user_id
            message.text = request.text
            message.message_type = MessageType.text
            session.add(message)
            session.flush()

            host_request = HostRequest()
            host_request.conversation_id = conversation.id
            host_request.from_user_id = context.user_id
            host_request.to_user_id = host.id
            host_request.from_date = request.from_date
            host_request.to_date = request.to_date
            host_request.status = HostRequestStatus.pending
            host_request.from_last_seen_message_id = message.id
            session.add(host_request)

            return requests_pb2.CreateHostRequestRes(host_request_id=host_request.conversation_id)