mirror of https://github.com/zulip/zulip.git
actions: Move part into zerver.lib.streams.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
6168c0110a
commit
a29f1b39da
|
@ -379,7 +379,6 @@ python_rules = RuleList(
|
|||
# This one in check_message is kinda terrible, since it's
|
||||
# how most instances are written, but better to exclude something than nothing
|
||||
("zerver/lib/actions.py", "stream = get_stream(stream_name, realm)"),
|
||||
("zerver/lib/actions.py", 'return get_stream("signups", realm)'),
|
||||
},
|
||||
"description": "Please use access_stream_by_*() to fetch Stream objects",
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ import orjson
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError, connection, transaction
|
||||
from django.db.models import Exists, F, OuterRef, Q
|
||||
from django.db.models import F
|
||||
from django.db.models.query import QuerySet
|
||||
from django.utils.html import escape
|
||||
from django.utils.timezone import now as timezone_now
|
||||
|
@ -125,7 +125,6 @@ from zerver.lib.stream_subscription import (
|
|||
get_active_subscriptions_for_stream_id,
|
||||
get_bulk_stream_subscriber_info,
|
||||
get_stream_subscriptions_for_user,
|
||||
get_subscribed_stream_ids_for_user,
|
||||
get_subscriptions_for_send_message,
|
||||
get_used_colors_for_user_ids,
|
||||
num_subscribers_for_stream_id,
|
||||
|
@ -138,10 +137,11 @@ from zerver.lib.streams import (
|
|||
access_stream_for_send_message,
|
||||
can_access_stream_user_ids,
|
||||
check_stream_access_based_on_stream_post_policy,
|
||||
create_stream_if_needed,
|
||||
ensure_stream,
|
||||
get_default_value_for_history_public_to_subscribers,
|
||||
get_occupied_streams,
|
||||
get_signups_stream,
|
||||
get_stream_permission_policy_name,
|
||||
get_web_public_streams_queryset,
|
||||
render_stream_description,
|
||||
send_stream_creation_event,
|
||||
subscribed_to_stream,
|
||||
|
@ -279,11 +279,6 @@ def subscriber_info(user_id: int) -> Dict[str, Any]:
|
|||
return {"id": user_id, "flags": ["read"]}
|
||||
|
||||
|
||||
def get_signups_stream(realm: Realm) -> Stream:
|
||||
# This one-liner helps us work around a lint rule.
|
||||
return get_stream("signups", realm)
|
||||
|
||||
|
||||
def send_message_to_signup_notification_stream(
|
||||
sender: UserProfile, realm: Realm, message: str, topic_name: str = _("signups")
|
||||
) -> None:
|
||||
|
@ -2442,23 +2437,6 @@ def do_remove_reaction(
|
|||
notify_reaction_update(user_profile, message, reaction, "remove")
|
||||
|
||||
|
||||
def ensure_stream(
|
||||
realm: Realm,
|
||||
stream_name: str,
|
||||
invite_only: bool = False,
|
||||
stream_description: str = "",
|
||||
*,
|
||||
acting_user: Optional[UserProfile],
|
||||
) -> Stream:
|
||||
return create_stream_if_needed(
|
||||
realm,
|
||||
stream_name,
|
||||
invite_only=invite_only,
|
||||
stream_description=stream_description,
|
||||
acting_user=acting_user,
|
||||
)[0]
|
||||
|
||||
|
||||
def already_sent_mirrored_message_id(message: Message) -> Optional[int]:
|
||||
if message.recipient.type == Recipient.HUDDLE:
|
||||
# For huddle messages, we use a 10-second window because the
|
||||
|
@ -7015,107 +6993,6 @@ def do_remove_realm_domain(
|
|||
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id)))
|
||||
|
||||
|
||||
def get_occupied_streams(realm: Realm) -> QuerySet:
|
||||
# TODO: Make a generic stub for QuerySet
|
||||
"""Get streams with subscribers"""
|
||||
exists_expression = Exists(
|
||||
Subscription.objects.filter(
|
||||
active=True,
|
||||
is_user_active=True,
|
||||
user_profile__realm=realm,
|
||||
recipient_id=OuterRef("recipient_id"),
|
||||
),
|
||||
)
|
||||
occupied_streams = (
|
||||
Stream.objects.filter(realm=realm, deactivated=False)
|
||||
.annotate(occupied=exists_expression)
|
||||
.filter(occupied=True)
|
||||
)
|
||||
return occupied_streams
|
||||
|
||||
|
||||
def get_web_public_streams(realm: Realm) -> List[Dict[str, Any]]: # nocoverage
|
||||
query = get_web_public_streams_queryset(realm)
|
||||
streams = Stream.get_client_data(query)
|
||||
return streams
|
||||
|
||||
|
||||
def do_get_streams(
|
||||
user_profile: UserProfile,
|
||||
include_public: bool = True,
|
||||
include_web_public: bool = False,
|
||||
include_subscribed: bool = True,
|
||||
include_all_active: bool = False,
|
||||
include_default: bool = False,
|
||||
include_owner_subscribed: bool = False,
|
||||
) -> List[Dict[str, Any]]:
|
||||
# This function is only used by API clients now.
|
||||
|
||||
if include_all_active and not user_profile.is_realm_admin:
|
||||
raise JsonableError(_("User not authorized for this query"))
|
||||
|
||||
include_public = include_public and user_profile.can_access_public_streams()
|
||||
|
||||
# Start out with all active streams in the realm.
|
||||
query = Stream.objects.filter(realm=user_profile.realm, deactivated=False)
|
||||
|
||||
if include_all_active:
|
||||
streams = Stream.get_client_data(query)
|
||||
else:
|
||||
# We construct a query as the or (|) of the various sources
|
||||
# this user requested streams from.
|
||||
query_filter: Optional[Q] = None
|
||||
|
||||
def add_filter_option(option: Q) -> None:
|
||||
nonlocal query_filter
|
||||
if query_filter is None:
|
||||
query_filter = option
|
||||
else:
|
||||
query_filter |= option
|
||||
|
||||
if include_subscribed:
|
||||
subscribed_stream_ids = get_subscribed_stream_ids_for_user(user_profile)
|
||||
recipient_check = Q(id__in=set(subscribed_stream_ids))
|
||||
add_filter_option(recipient_check)
|
||||
if include_public:
|
||||
invite_only_check = Q(invite_only=False)
|
||||
add_filter_option(invite_only_check)
|
||||
if include_web_public:
|
||||
# This should match get_web_public_streams_queryset
|
||||
web_public_check = Q(
|
||||
is_web_public=True,
|
||||
invite_only=False,
|
||||
history_public_to_subscribers=True,
|
||||
deactivated=False,
|
||||
)
|
||||
add_filter_option(web_public_check)
|
||||
if include_owner_subscribed and user_profile.is_bot:
|
||||
bot_owner = user_profile.bot_owner
|
||||
assert bot_owner is not None
|
||||
owner_stream_ids = get_subscribed_stream_ids_for_user(bot_owner)
|
||||
owner_subscribed_check = Q(id__in=set(owner_stream_ids))
|
||||
add_filter_option(owner_subscribed_check)
|
||||
|
||||
if query_filter is not None:
|
||||
query = query.filter(query_filter)
|
||||
streams = Stream.get_client_data(query)
|
||||
else:
|
||||
# Don't bother going to the database with no valid sources
|
||||
streams = []
|
||||
|
||||
streams.sort(key=lambda elt: elt["name"])
|
||||
|
||||
if include_default:
|
||||
is_default = {}
|
||||
default_streams = get_default_streams_for_realm(user_profile.realm_id)
|
||||
for default_stream in default_streams:
|
||||
is_default[default_stream.id] = True
|
||||
for stream in streams:
|
||||
stream["is_default"] = is_default.get(stream["stream_id"], False)
|
||||
|
||||
return streams
|
||||
|
||||
|
||||
def notify_attachment_update(
|
||||
user_profile: UserProfile, op: str, attachment_dict: Dict[str, Any]
|
||||
) -> None:
|
||||
|
|
|
@ -13,12 +13,7 @@ from zerver.actions.default_streams import (
|
|||
get_default_streams_for_realm,
|
||||
streams_to_dicts_sorted,
|
||||
)
|
||||
from zerver.lib.actions import (
|
||||
do_get_streams,
|
||||
gather_subscriptions_helper,
|
||||
get_owned_bot_dicts,
|
||||
get_web_public_streams,
|
||||
)
|
||||
from zerver.lib.actions import gather_subscriptions_helper, get_owned_bot_dicts
|
||||
from zerver.lib.alert_words import user_alert_words
|
||||
from zerver.lib.avatar import avatar_url
|
||||
from zerver.lib.bot_config import load_bot_config_template
|
||||
|
@ -46,6 +41,7 @@ from zerver.lib.realm_logo import get_realm_logo_source, get_realm_logo_url
|
|||
from zerver.lib.soft_deactivation import reactivate_user_if_soft_deactivated
|
||||
from zerver.lib.sounds import get_available_notification_sounds
|
||||
from zerver.lib.stream_subscription import handle_stream_notifications_compatibility
|
||||
from zerver.lib.streams import do_get_streams, get_web_public_streams
|
||||
from zerver.lib.subscription_info import get_web_public_subs
|
||||
from zerver.lib.timestamp import datetime_to_timestamp
|
||||
from zerver.lib.timezone import canonicalize_timezone
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
from typing import Collection, List, Optional, Set, Tuple, Union
|
||||
from typing import Any, Collection, Dict, List, Optional, Set, Tuple, Union
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import Exists, OuterRef, Q
|
||||
from django.db.models.query import QuerySet
|
||||
from django.utils.timezone import now as timezone_now
|
||||
from django.utils.translation import gettext as _
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from zerver.actions.default_streams import get_default_streams_for_realm
|
||||
from zerver.lib.exceptions import (
|
||||
JsonableError,
|
||||
OrganizationOwnerRequired,
|
||||
StreamAdministratorRequired,
|
||||
)
|
||||
from zerver.lib.markdown import markdown_convert
|
||||
from zerver.lib.stream_subscription import get_active_subscriptions_for_stream_id
|
||||
from zerver.lib.stream_subscription import (
|
||||
get_active_subscriptions_for_stream_id,
|
||||
get_subscribed_stream_ids_for_user,
|
||||
)
|
||||
from zerver.lib.string_validation import check_stream_name
|
||||
from zerver.models import (
|
||||
DefaultStreamGroup,
|
||||
|
@ -738,3 +743,126 @@ def get_stream_by_narrow_operand_access_unchecked(operand: Union[str, int], real
|
|||
if isinstance(operand, str):
|
||||
return get_stream(operand, realm)
|
||||
return get_stream_by_id_in_realm(operand, realm)
|
||||
|
||||
|
||||
def get_signups_stream(realm: Realm) -> Stream:
|
||||
# This one-liner helps us work around a lint rule.
|
||||
return get_stream("signups", realm)
|
||||
|
||||
|
||||
def ensure_stream(
|
||||
realm: Realm,
|
||||
stream_name: str,
|
||||
invite_only: bool = False,
|
||||
stream_description: str = "",
|
||||
*,
|
||||
acting_user: Optional[UserProfile],
|
||||
) -> Stream:
|
||||
return create_stream_if_needed(
|
||||
realm,
|
||||
stream_name,
|
||||
invite_only=invite_only,
|
||||
stream_description=stream_description,
|
||||
acting_user=acting_user,
|
||||
)[0]
|
||||
|
||||
|
||||
def get_occupied_streams(realm: Realm) -> QuerySet:
|
||||
# TODO: Make a generic stub for QuerySet
|
||||
"""Get streams with subscribers"""
|
||||
exists_expression = Exists(
|
||||
Subscription.objects.filter(
|
||||
active=True,
|
||||
is_user_active=True,
|
||||
user_profile__realm=realm,
|
||||
recipient_id=OuterRef("recipient_id"),
|
||||
),
|
||||
)
|
||||
occupied_streams = (
|
||||
Stream.objects.filter(realm=realm, deactivated=False)
|
||||
.annotate(occupied=exists_expression)
|
||||
.filter(occupied=True)
|
||||
)
|
||||
return occupied_streams
|
||||
|
||||
|
||||
def get_web_public_streams(realm: Realm) -> List[Dict[str, Any]]: # nocoverage
|
||||
query = get_web_public_streams_queryset(realm)
|
||||
streams = Stream.get_client_data(query)
|
||||
return streams
|
||||
|
||||
|
||||
def do_get_streams(
|
||||
user_profile: UserProfile,
|
||||
include_public: bool = True,
|
||||
include_web_public: bool = False,
|
||||
include_subscribed: bool = True,
|
||||
include_all_active: bool = False,
|
||||
include_default: bool = False,
|
||||
include_owner_subscribed: bool = False,
|
||||
) -> List[Dict[str, Any]]:
|
||||
# This function is only used by API clients now.
|
||||
|
||||
if include_all_active and not user_profile.is_realm_admin:
|
||||
raise JsonableError(_("User not authorized for this query"))
|
||||
|
||||
include_public = include_public and user_profile.can_access_public_streams()
|
||||
|
||||
# Start out with all active streams in the realm.
|
||||
query = Stream.objects.filter(realm=user_profile.realm, deactivated=False)
|
||||
|
||||
if include_all_active:
|
||||
streams = Stream.get_client_data(query)
|
||||
else:
|
||||
# We construct a query as the or (|) of the various sources
|
||||
# this user requested streams from.
|
||||
query_filter: Optional[Q] = None
|
||||
|
||||
def add_filter_option(option: Q) -> None:
|
||||
nonlocal query_filter
|
||||
if query_filter is None:
|
||||
query_filter = option
|
||||
else:
|
||||
query_filter |= option
|
||||
|
||||
if include_subscribed:
|
||||
subscribed_stream_ids = get_subscribed_stream_ids_for_user(user_profile)
|
||||
recipient_check = Q(id__in=set(subscribed_stream_ids))
|
||||
add_filter_option(recipient_check)
|
||||
if include_public:
|
||||
invite_only_check = Q(invite_only=False)
|
||||
add_filter_option(invite_only_check)
|
||||
if include_web_public:
|
||||
# This should match get_web_public_streams_queryset
|
||||
web_public_check = Q(
|
||||
is_web_public=True,
|
||||
invite_only=False,
|
||||
history_public_to_subscribers=True,
|
||||
deactivated=False,
|
||||
)
|
||||
add_filter_option(web_public_check)
|
||||
if include_owner_subscribed and user_profile.is_bot:
|
||||
bot_owner = user_profile.bot_owner
|
||||
assert bot_owner is not None
|
||||
owner_stream_ids = get_subscribed_stream_ids_for_user(bot_owner)
|
||||
owner_subscribed_check = Q(id__in=set(owner_stream_ids))
|
||||
add_filter_option(owner_subscribed_check)
|
||||
|
||||
if query_filter is not None:
|
||||
query = query.filter(query_filter)
|
||||
streams = Stream.get_client_data(query)
|
||||
else:
|
||||
# Don't bother going to the database with no valid sources
|
||||
streams = []
|
||||
|
||||
streams.sort(key=lambda elt: elt["name"])
|
||||
|
||||
if include_default:
|
||||
is_default = {}
|
||||
default_streams = get_default_streams_for_realm(user_profile.realm_id)
|
||||
for default_stream in default_streams:
|
||||
is_default[default_stream.id] = True
|
||||
for stream in streams:
|
||||
stream["is_default"] = is_default.get(stream["stream_id"], False)
|
||||
|
||||
return streams
|
||||
|
|
|
@ -2,8 +2,9 @@ from typing import Any
|
|||
|
||||
from django.core.management.base import CommandParser
|
||||
|
||||
from zerver.lib.actions import bulk_add_subscriptions, ensure_stream
|
||||
from zerver.lib.actions import bulk_add_subscriptions
|
||||
from zerver.lib.management import ZulipBaseCommand
|
||||
from zerver.lib.streams import ensure_stream
|
||||
|
||||
|
||||
class Command(ZulipBaseCommand):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from argparse import ArgumentParser
|
||||
from typing import Any
|
||||
|
||||
from zerver.lib.actions import ensure_stream
|
||||
from zerver.lib.management import ZulipBaseCommand
|
||||
from zerver.lib.streams import ensure_stream
|
||||
from zerver.models import DefaultStreamGroup
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ from zerver.lib.actions import (
|
|||
do_reactivate_realm,
|
||||
do_reactivate_user,
|
||||
do_set_realm_property,
|
||||
ensure_stream,
|
||||
)
|
||||
from zerver.lib.avatar import avatar_url
|
||||
from zerver.lib.avatar_hash import user_avatar_path
|
||||
|
@ -66,6 +65,7 @@ from zerver.lib.initial_password import initial_password
|
|||
from zerver.lib.mobile_auth_otp import otp_decrypt_api_key
|
||||
from zerver.lib.rate_limiter import add_ratelimit_rule, remove_ratelimit_rule
|
||||
from zerver.lib.storage import static_path
|
||||
from zerver.lib.streams import ensure_stream
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import (
|
||||
create_s3_buckets,
|
||||
|
|
|
@ -11,12 +11,7 @@ import orjson
|
|||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
|
||||
from zerver.lib.actions import (
|
||||
do_change_stream_post_policy,
|
||||
do_deactivate_realm,
|
||||
do_deactivate_user,
|
||||
ensure_stream,
|
||||
)
|
||||
from zerver.lib.actions import do_change_stream_post_policy, do_deactivate_realm, do_deactivate_user
|
||||
from zerver.lib.email_mirror import (
|
||||
create_missed_message_address,
|
||||
filter_footer,
|
||||
|
@ -37,6 +32,7 @@ from zerver.lib.email_mirror_helpers import (
|
|||
)
|
||||
from zerver.lib.email_notifications import convert_html_to_markdown
|
||||
from zerver.lib.send_email import FromAddress
|
||||
from zerver.lib.streams import ensure_stream
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import mock_queue_publish, most_recent_message, most_recent_usermessage
|
||||
from zerver.models import (
|
||||
|
|
|
@ -34,9 +34,7 @@ from zerver.lib.actions import (
|
|||
do_create_realm,
|
||||
do_deactivate_stream,
|
||||
do_deactivate_user,
|
||||
do_get_streams,
|
||||
do_set_realm_property,
|
||||
ensure_stream,
|
||||
gather_subscriptions,
|
||||
gather_subscriptions_helper,
|
||||
get_topic_messages,
|
||||
|
@ -63,6 +61,8 @@ from zerver.lib.streams import (
|
|||
can_access_stream_user_ids,
|
||||
create_stream_if_needed,
|
||||
create_streams_if_needed,
|
||||
do_get_streams,
|
||||
ensure_stream,
|
||||
filter_stream_authorization,
|
||||
list_to_streams,
|
||||
)
|
||||
|
|
|
@ -6,7 +6,8 @@ import orjson
|
|||
from django.utils.timezone import now as timezone_now
|
||||
|
||||
from zerver.actions.user_groups import promote_new_full_members
|
||||
from zerver.lib.actions import do_set_realm_property, ensure_stream
|
||||
from zerver.lib.actions import do_set_realm_property
|
||||
from zerver.lib.streams import ensure_stream
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import most_recent_usermessage
|
||||
from zerver.lib.user_groups import (
|
||||
|
|
|
@ -38,7 +38,6 @@ from zerver.lib.actions import (
|
|||
do_change_subscription_property,
|
||||
do_deactivate_stream,
|
||||
do_delete_messages,
|
||||
do_get_streams,
|
||||
do_rename_stream,
|
||||
do_send_messages,
|
||||
gather_subscriptions,
|
||||
|
@ -64,6 +63,7 @@ from zerver.lib.streams import (
|
|||
access_stream_for_delete_or_update,
|
||||
access_web_public_stream,
|
||||
check_stream_name_available,
|
||||
do_get_streams,
|
||||
filter_stream_authorization,
|
||||
get_stream_permission_policy_name,
|
||||
list_to_streams,
|
||||
|
|
|
@ -8,10 +8,10 @@ from zerver.lib.actions import (
|
|||
do_change_avatar_fields,
|
||||
do_create_user,
|
||||
do_send_messages,
|
||||
ensure_stream,
|
||||
internal_prep_stream_message,
|
||||
)
|
||||
from zerver.lib.emoji import emoji_name_to_emoji_code
|
||||
from zerver.lib.streams import ensure_stream
|
||||
from zerver.lib.upload import upload_avatar_image
|
||||
from zerver.models import Message, UserProfile, get_realm
|
||||
|
||||
|
|
Loading…
Reference in New Issue