Пример #1
0
def avatar(request: HttpRequest, email_or_id: str, medium: bool=False) -> HttpResponse:
    """Accepts an email address or user ID and returns the avatar"""
    is_email = False
    try:
        int(email_or_id)
    except ValueError:
        is_email = True

    try:
        if is_email:
            realm = request.user.realm
            user_profile = get_user_including_cross_realm(email_or_id, realm)
        else:
            user_profile = get_user_profile_by_id(email_or_id)
        # If there is a valid user account passed in, use its avatar
        url = avatar_url(user_profile, medium=medium)
    except UserProfile.DoesNotExist:
        # If there is no such user, treat it as a new gravatar
        email = email_or_id
        avatar_version = 1
        url = get_gravatar_url(email, avatar_version, medium)

    # We can rely on the url already having query parameters. Because
    # our templates depend on being able to use the ampersand to
    # add query parameters to our url, get_avatar_url does '?x=x'
    # hacks to prevent us from having to jump through decode/encode hoops.
    assert '?' in url
    url += '&' + request.META['QUERY_STRING']
    return redirect(url)
Пример #2
0
def archive(request: HttpRequest,
            stream_id: int,
            topic_name: str) -> HttpResponse:

    def get_response(rendered_message_list: List[str],
                     is_web_public: bool,
                     stream_name: str) -> HttpResponse:
        return render(
            request,
            'zerver/archive/index.html',
            context={
                'is_web_public': is_web_public,
                'message_list': rendered_message_list,
                'stream': stream_name,
                'topic': topic_name,
            }
        )

    try:
        stream = get_stream_by_id(stream_id)
    except JsonableError:
        return get_response([], False, '')

    if not stream.is_web_public:
        return get_response([], False, '')

    all_messages = list(Message.objects.select_related(
        'sender').filter(recipient__type_id=stream_id, subject=topic_name).order_by('pub_date'))
    if not all_messages:
        return get_response([], True, stream.name)

    rendered_message_list = []
    prev_sender = None
    for msg in all_messages:
        include_sender = False
        status_message = Message.is_status_message(msg.content, msg.rendered_content)
        if not prev_sender or prev_sender != msg.sender or status_message:
            if status_message:
                prev_sender = None
            else:
                prev_sender = msg.sender
            include_sender = True
        if status_message:
            status_message = msg.rendered_content[4+3: -4]
        context = {
            'sender_full_name': msg.sender.full_name,
            'timestampstr': datetime_to_timestamp(msg.last_edit_time
                                                  if msg.last_edit_time
                                                  else msg.pub_date),
            'message_content': msg.rendered_content,
            'avatar_url': get_gravatar_url(msg.sender.email, 1),
            'include_sender': include_sender,
            'status_message': status_message,
        }
        rendered_msg = loader.render_to_string('zerver/archive/single_message.html', context)
        rendered_message_list.append(rendered_msg)
    return get_response(rendered_message_list, True, stream.name)
Пример #3
0
def archive(request: HttpRequest, stream_id: int,
            topic_name: str) -> HttpResponse:
    def get_response(rendered_message_list: List[str], is_web_public: bool,
                     stream_name: str) -> HttpResponse:
        return render(
            request,
            "zerver/archive/index.html",
            context={
                "is_web_public": is_web_public,
                "message_list": rendered_message_list,
                "stream": stream_name,
                "topic": topic_name,
            },
        )

    try:
        realm = get_request_notes(request).realm
        assert realm is not None
        stream = access_web_public_stream(stream_id, realm)
    except JsonableError:
        return get_response([], False, "")

    all_messages = list(
        messages_for_topic(
            stream_recipient_id=stream.recipient_id,
            topic_name=topic_name,
        ).select_related("sender").order_by("date_sent"), )

    if not all_messages:
        return get_response([], True, stream.name)

    rendered_message_list = []
    prev_sender: Optional[UserProfile] = None
    for msg in all_messages:
        include_sender = False
        status_message = Message.is_status_message(msg.content,
                                                   msg.rendered_content)
        if not prev_sender or prev_sender != msg.sender or status_message:
            if status_message:
                prev_sender = None
            else:
                prev_sender = msg.sender
            include_sender = True
        if status_message:
            status_message = msg.rendered_content[4 + 3:-4]
        context = {
            "sender_full_name":
            msg.sender.full_name,
            "timestampstr":
            datetime_to_timestamp(
                msg.last_edit_time if msg.last_edit_time else msg.date_sent),
            "message_content":
            msg.rendered_content,
            "avatar_url":
            get_gravatar_url(msg.sender.delivery_email, 1),
            "include_sender":
            include_sender,
            "status_message":
            status_message,
        }
        rendered_msg = loader.render_to_string(
            "zerver/archive/single_message.html", context)
        rendered_message_list.append(rendered_msg)
    return get_response(rendered_message_list, True, stream.name)
Пример #4
0
def archive(request: HttpRequest, stream_id: int,
            topic_name: str) -> HttpResponse:
    def get_response(rendered_message_list: List[str], is_web_public: bool,
                     stream_name: str) -> HttpResponse:
        return render(request,
                      'zerver/archive/index.html',
                      context={
                          'is_web_public': is_web_public,
                          'message_list': rendered_message_list,
                          'stream': stream_name,
                          'topic': topic_name,
                      })

    try:
        stream = get_stream_by_id(stream_id)
    except JsonableError:
        return get_response([], False, '')

    if not stream.is_web_public:
        return get_response([], False, '')

    all_messages = list(
        messages_for_topic(
            stream_id=stream_id,
            topic_name=topic_name,
        ).select_related('sender').order_by('date_sent'))

    if not all_messages:
        return get_response([], True, stream.name)

    rendered_message_list = []
    prev_sender = None  # type: Optional[UserProfile]
    for msg in all_messages:
        include_sender = False
        status_message = Message.is_status_message(msg.content,
                                                   msg.rendered_content)
        if not prev_sender or prev_sender != msg.sender or status_message:
            if status_message:
                prev_sender = None
            else:
                prev_sender = msg.sender
            include_sender = True
        if status_message:
            status_message = msg.rendered_content[4 + 3:-4]
        context = {
            'sender_full_name':
            msg.sender.full_name,
            'timestampstr':
            datetime_to_timestamp(
                msg.last_edit_time if msg.last_edit_time else msg.date_sent),
            'message_content':
            msg.rendered_content,
            'avatar_url':
            get_gravatar_url(msg.sender.email, 1),
            'include_sender':
            include_sender,
            'status_message':
            status_message,
        }
        rendered_msg = loader.render_to_string(
            'zerver/archive/single_message.html', context)
        rendered_message_list.append(rendered_msg)
    return get_response(rendered_message_list, True, stream.name)
Пример #5
0
def avatar(
    request: HttpRequest,
    maybe_user_profile: Union[UserProfile, AnonymousUser],
    email_or_id: str,
    medium: bool = False,
) -> HttpResponse:
    """Accepts an email address or user ID and returns the avatar"""
    is_email = False
    try:
        int(email_or_id)
    except ValueError:
        is_email = True

    if not maybe_user_profile.is_authenticated:
        # Allow anonymous access to avatars only if spectators are
        # enabled in the organization.
        realm = get_valid_realm_from_request(request)
        if not realm.allow_web_public_streams_access():
            raise MissingAuthenticationError()

        # We only allow the ID format for accessing a user's avatar
        # for spectators. This is mainly for defense in depth, since
        # email_address_visibility should mean spectators only
        # interact with fake email addresses anyway.
        if is_email:
            raise MissingAuthenticationError()

        if settings.RATE_LIMITING:
            try:
                unique_avatar_key = f"{realm.id}/{email_or_id}/{medium}"
                rate_limit_spectator_attachment_access_by_file(
                    unique_avatar_key)
            except RateLimited:
                return json_response_from_error(
                    RateLimited(
                        _("Too many attempts, please try after some time.")))
    else:
        realm = maybe_user_profile.realm

    try:
        if is_email:
            avatar_user_profile = get_user_including_cross_realm(
                email_or_id, realm)
        else:
            avatar_user_profile = get_user_by_id_in_realm_including_cross_realm(
                int(email_or_id), realm)
        # If there is a valid user account passed in, use its avatar
        url = avatar_url(avatar_user_profile, medium=medium)
    except UserProfile.DoesNotExist:
        # If there is no such user, treat it as a new gravatar
        email = email_or_id
        avatar_version = 1
        url = get_gravatar_url(email, avatar_version, medium)

    # We can rely on the URL already having query parameters. Because
    # our templates depend on being able to use the ampersand to
    # add query parameters to our url, get_avatar_url does '?x=x'
    # hacks to prevent us from having to jump through decode/encode hoops.
    assert url is not None
    url = append_url_query_string(url, request.META["QUERY_STRING"])
    return redirect(url)
Пример #6
0
    def test_make_request(self) -> None:
        othello = self.example_user("othello")
        stream = get_stream("Denmark", othello.realm)
        message_id = self.send_stream_message(
            othello,
            stream.name,
            content="@**test**",
        )

        message = Message.objects.get(id=message_id)

        gravatar_url = get_gravatar_url(
            othello.delivery_email,
            othello.avatar_version,
        )

        expected_message_data = {
            "avatar_url": gravatar_url,
            "client": "test suite",
            "content": "@**test**",
            "content_type": "text/x-markdown",
            "display_recipient": "Denmark",
            "id": message.id,
            "is_me_message": False,
            "reactions": [],
            "recipient_id": message.recipient_id,
            "rendered_content": "<p>@<strong>test</strong></p>",
            "sender_email": othello.email,
            "sender_full_name": "Othello, the Moor of Venice",
            "sender_id": othello.id,
            "sender_realm_str": "zulip",
            "stream_id": stream.id,
            TOPIC_NAME: "test",
            "submessages": [],
            "timestamp": datetime_to_timestamp(message.date_sent),
            "topic_links": [],
            "type": "stream",
        }

        wide_message_dict = MessageDict.wide_dict(message)

        event = {
            "command": "@**test**",
            "message": wide_message_dict,
            "trigger": "mention",
        }

        test_url = "https://example.com/example"
        with mock.patch.object(self.handler, "session") as session:
            self.handler.make_request(
                test_url,
                event,
            )
            session.post.assert_called_once()
            self.assertEqual(session.post.call_args[0], (test_url,))
            request_data = session.post.call_args[1]["json"]

        validate_against_openapi_schema(request_data, "/zulip-outgoing-webhook", "post", "200")
        self.assertEqual(request_data["bot_full_name"], self.bot_user.full_name)
        self.assertEqual(request_data["data"], "@**test**")
        self.assertEqual(request_data["token"], "abcdef")
        self.assertEqual(request_data["message"], expected_message_data)

        # Make sure we didn't accidentally mutate wide_message_dict.
        self.assertEqual(wide_message_dict["sender_realm_id"], othello.realm_id)