Exemple #1
0
def create_stream_if_needed(
        realm: Realm,
        stream_name: str,
        *,
        invite_only: bool = False,
        is_web_public: bool = False,
        stream_post_policy: int = Stream.STREAM_POST_POLICY_EVERYONE,
        history_public_to_subscribers: Optional[bool] = None,
        stream_description: str = "",
        message_retention_days: Optional[int] = None,
        acting_user: Optional[UserProfile] = None) -> Tuple[Stream, bool]:
    history_public_to_subscribers = get_default_value_for_history_public_to_subscribers(
        realm, invite_only, history_public_to_subscribers)

    (stream, created) = Stream.objects.get_or_create(
        realm=realm,
        name__iexact=stream_name,
        defaults=dict(
            name=stream_name,
            description=stream_description,
            invite_only=invite_only,
            is_web_public=is_web_public,
            stream_post_policy=stream_post_policy,
            history_public_to_subscribers=history_public_to_subscribers,
            is_in_zephyr_realm=realm.is_zephyr_mirror_realm,
            message_retention_days=message_retention_days,
        ),
    )

    if created:
        recipient = Recipient.objects.create(type_id=stream.id,
                                             type=Recipient.STREAM)

        stream.recipient = recipient
        stream.rendered_description = render_stream_description(
            stream_description)
        stream.save(update_fields=["recipient", "rendered_description"])

        if stream.is_public():
            send_stream_creation_event(
                stream, active_non_guest_user_ids(stream.realm_id))
        else:
            realm_admin_ids = [
                user.id for user in stream.realm.get_admin_users_and_bots()
            ]
            send_stream_creation_event(stream, realm_admin_ids)

        event_time = timezone_now()
        RealmAuditLog.objects.create(realm=realm,
                                     acting_user=acting_user,
                                     modified_stream=stream,
                                     event_type=RealmAuditLog.STREAM_CREATED,
                                     event_time=event_time)
    return stream, created
Exemple #2
0
def bulk_get_subscriber_peer_info(
    realm: Realm,
    streams: List[Stream],
) -> SubscriberPeerInfo:
    """
    Glossary:

        subscribed_ids:
            This shows the users who are actually subscribed to the
            stream, which we generally send to the person subscribing
            to the stream.

        peer_ids:
            These are the folks that need to know about a new subscriber.
            It's usually a superset of the subscribers.
    """

    subscribed_ids = {}
    peer_ids = {}

    private_stream_ids = {stream.id for stream in streams if stream.invite_only}
    public_stream_ids = {stream.id for stream in streams if not stream.invite_only}

    stream_user_ids = get_user_ids_for_streams(private_stream_ids | public_stream_ids)

    if private_stream_ids:
        realm_admin_ids = {user.id for user in realm.get_admin_users_and_bots()}

        for stream_id in private_stream_ids:
            subscribed_user_ids = stream_user_ids.get(stream_id, set())
            subscribed_ids[stream_id] = subscribed_user_ids
            peer_ids[stream_id] = subscribed_user_ids | realm_admin_ids

    if public_stream_ids:
        non_guests = active_non_guest_user_ids(realm.id)
        for stream_id in public_stream_ids:
            subscribed_user_ids = stream_user_ids.get(stream_id, set())
            subscribed_ids[stream_id] = subscribed_user_ids
            peer_ids[stream_id] = set(non_guests)

    return SubscriberPeerInfo(
        subscribed_ids=subscribed_ids,
        peer_ids=peer_ids,
    )
Exemple #3
0
def create_stream_if_needed(
        realm: Realm,
        stream_name: str,
        *,
        invite_only: bool = False,
        stream_post_policy: int = Stream.STREAM_POST_POLICY_EVERYONE,
        history_public_to_subscribers: Optional[bool] = None,
        stream_description: str = "") -> Tuple[Stream, bool]:
    history_public_to_subscribers = get_default_value_for_history_public_to_subscribers(
        realm, invite_only, history_public_to_subscribers)

    (stream, created) = Stream.objects.get_or_create(
        realm=realm,
        name__iexact=stream_name,
        defaults=dict(
            name=stream_name,
            description=stream_description,
            invite_only=invite_only,
            stream_post_policy=stream_post_policy,
            history_public_to_subscribers=history_public_to_subscribers,
            is_in_zephyr_realm=realm.is_zephyr_mirror_realm,
        ),
    )

    if created:
        recipient = Recipient.objects.create(type_id=stream.id,
                                             type=Recipient.STREAM)

        stream.recipient = recipient
        stream.rendered_description = render_stream_description(
            stream_description)
        stream.save(update_fields=["recipient", "rendered_description"])

        if stream.is_public():
            send_stream_creation_event(
                stream, active_non_guest_user_ids(stream.realm_id))
        else:
            realm_admin_ids = [
                user.id for user in stream.realm.get_admin_users_and_bots()
            ]
            send_stream_creation_event(stream, realm_admin_ids)
    return stream, created
Exemple #4
0
def bulk_get_peers(
    realm: Realm,
    streams: List[Stream],
) -> Dict[int, Set[int]]:
    # This is almost a subset of bulk_get_subscriber_peer_info,
    # with the nuance that we don't have to query subscribers
    # for public streams.  (The other functions tries to save
    # a query hop.)

    peer_ids = {}

    private_stream_ids = {
        stream.id
        for stream in streams if stream.invite_only
    }
    public_stream_ids = {
        stream.id
        for stream in streams if not stream.invite_only
    }

    if private_stream_ids:
        realm_admin_ids = {
            user.id
            for user in realm.get_admin_users_and_bots()
        }
        stream_user_ids = get_user_ids_for_streams(private_stream_ids)

        for stream_id in private_stream_ids:
            subscribed_user_ids = stream_user_ids.get(stream_id, set())
            peer_ids[stream_id] = subscribed_user_ids | realm_admin_ids

    if public_stream_ids:
        non_guests = active_non_guest_user_ids(realm.id)
        for stream_id in public_stream_ids:
            peer_ids[stream_id] = set(non_guests)

    return peer_ids
Exemple #5
0
def send_peer_subscriber_events(
    op: str,
    realm: Realm,
    stream_dict: Dict[int, Stream],
    altered_user_dict: Dict[int, Set[int]],
    private_peer_dict: Dict[int, Set[int]],
) -> None:
    # Send peer_add/peer_remove events to other users who are tracking the
    # subscribers lists of streams in their browser; everyone for
    # public streams and only existing subscribers for private streams.

    assert op in ["peer_add", "peer_remove"]

    private_stream_ids = [
        stream_id for stream_id in altered_user_dict if stream_dict[stream_id].invite_only
    ]

    for stream_id in private_stream_ids:
        altered_user_ids = altered_user_dict[stream_id]
        peer_user_ids = private_peer_dict[stream_id] - altered_user_ids

        if peer_user_ids and altered_user_ids:
            event = dict(
                type="subscription",
                op=op,
                stream_ids=[stream_id],
                user_ids=sorted(list(altered_user_ids)),
            )
            send_event(realm, event, peer_user_ids)

    public_stream_ids = [
        stream_id
        for stream_id in altered_user_dict
        if not stream_dict[stream_id].invite_only and not stream_dict[stream_id].is_in_zephyr_realm
    ]

    if public_stream_ids:
        user_streams: Dict[int, Set[int]] = defaultdict(set)

        public_peer_ids = set(active_non_guest_user_ids(realm.id))

        for stream_id in public_stream_ids:
            altered_user_ids = altered_user_dict[stream_id]
            peer_user_ids = public_peer_ids - altered_user_ids

            if peer_user_ids and altered_user_ids:
                if len(altered_user_ids) == 1:
                    # If we only have one user, we will try to
                    # find other streams they have (un)subscribed to
                    # (where it's just them).  This optimization
                    # typically works when a single user is subscribed
                    # to multiple default public streams during
                    # new-user registration.
                    #
                    # This optimization depends on all public streams
                    # having the same peers for any single user, which
                    # isn't the case for private streams.
                    altered_user_id = list(altered_user_ids)[0]
                    user_streams[altered_user_id].add(stream_id)
                else:
                    event = dict(
                        type="subscription",
                        op=op,
                        stream_ids=[stream_id],
                        user_ids=sorted(list(altered_user_ids)),
                    )
                    send_event(realm, event, peer_user_ids)

        for user_id, stream_ids in user_streams.items():
            peer_user_ids = public_peer_ids - {user_id}
            event = dict(
                type="subscription",
                op=op,
                stream_ids=sorted(list(stream_ids)),
                user_ids=[user_id],
            )
            send_event(realm, event, peer_user_ids)
Exemple #6
0
def notify_default_streams(realm: Realm) -> None:
    event = dict(
        type="default_streams",
        default_streams=streams_to_dicts_sorted(get_default_streams_for_realm(realm.id)),
    )
    transaction.on_commit(lambda: send_event(realm, event, active_non_guest_user_ids(realm.id)))