Example #1
0
    def by_pm_with(self, query: Query, operand: Union[str, Iterable[int]],
                   maybe_negate: ConditionTransform) -> Query:

        try:
            if isinstance(operand, str):
                email_list = operand.split(",")
                user_profiles = get_user_profiles(
                    emails=email_list,
                    realm=self.user_realm,
                )
            else:
                """
                This is where we handle passing a list of user IDs for the narrow, which is the
                preferred/cleaner API.
                """
                user_profiles = get_user_profiles_by_ids(
                    user_ids=operand,
                    realm=self.user_realm,
                )

            recipient = recipient_for_user_profiles(user_profiles=user_profiles,
                                                    forwarded_mirror_message=False,
                                                    forwarder_user_profile=None,
                                                    sender=self.user_profile,
                                                    allow_deactivated=True)
        except (JsonableError, ValidationError):
            raise BadNarrowOperator('unknown user in ' + str(operand))

        # Group DM
        if recipient.type == Recipient.HUDDLE:
            cond = column("recipient_id") == recipient.id
            return query.where(maybe_negate(cond))

        # 1:1 PM
        other_participant = None

        # Find if another person is in PM
        for user in user_profiles:
            if user.id != self.user_profile.id:
                other_participant = user

        # PM with another person
        if other_participant:
            # We need bidirectional messages PM with another person.
            # But Recipient.PERSONAL objects only encode the person who
            # received the message, and not the other participant in
            # the thread (the sender), we need to do a somewhat
            # complex query to get messages between these two users
            # with either of them as the sender.
            self_recipient_id = self.user_profile.recipient_id
            cond = or_(and_(column("sender_id") == other_participant.id,
                            column("recipient_id") == self_recipient_id),
                       and_(column("sender_id") == self.user_profile.id,
                            column("recipient_id") == recipient.id))
            return query.where(maybe_negate(cond))

        # PM with self
        cond = and_(column("sender_id") == self.user_profile.id,
                    column("recipient_id") == recipient.id)
        return query.where(maybe_negate(cond))
Example #2
0
def further_validated_draft_dict(draft_dict: Dict[str, Any],
                                 user_profile: UserProfile) -> Dict[str, Any]:
    """ Take a draft_dict that was already validated by draft_dict_validator then
    further sanitize, validate, and transform it. Ultimately return this "further
    validated" draft dict. It will have a slightly different set of keys the values
    for which can be used to directly create a Draft object. """

    content = truncate_body(draft_dict["content"])
    if "\x00" in content:
        raise JsonableError(_("Content must not contain null bytes"))

    timestamp = draft_dict.get("timestamp", time.time())
    timestamp = round(timestamp, 6)
    if timestamp < 0:
        # While it's not exactly an invalid timestamp, it's not something
        # we want to allow either.
        raise JsonableError(_("Timestamp must not be negative."))
    last_edit_time = timestamp_to_datetime(timestamp)

    topic = ""
    recipient = None
    to = draft_dict["to"]
    if draft_dict["type"] == "stream":
        topic = truncate_topic(draft_dict["topic"])
        if "\x00" in topic:
            raise JsonableError(_("Topic must not contain null bytes"))
        if len(to) != 1:
            raise JsonableError(
                _("Must specify exactly 1 stream ID for stream messages"))
        stream, sub = access_stream_by_id(user_profile, to[0])
        recipient = stream.recipient
    elif draft_dict["type"] == "private" and len(to) != 0:
        to_users = get_user_profiles_by_ids(set(to), user_profile.realm)
        try:
            recipient = recipient_for_user_profiles(to_users, False, None,
                                                    user_profile)
        except ValidationError as e:  # nocoverage
            raise JsonableError(e.messages[0])

    return {
        "recipient": recipient,
        "topic": topic,
        "content": content,
        "last_edit_time": last_edit_time,
    }