message_send: Optimize checking access to DM recipients.

We previously used get_accessible_user_ids to check whether the
sender can access all DM recipients, which was not efficient as
it queries the Message table. This commit updates the code to
make sure we use get_inaccessible_user_ids which is much more
efficient as it limits the queries to only DM recipients and
also queries the Message table only if needed.

This can still be optimized further as mentioned in #27835 but
this commit is a nice first step.
This commit is contained in:
Sahil Batra 2023-12-13 23:15:43 +05:30 committed by Tim Abbott
parent 8bce83709f
commit 92c1dfc248
1 changed files with 3 additions and 9 deletions

View File

@ -83,8 +83,7 @@ from zerver.lib.url_preview.types import UrlEmbedData
from zerver.lib.user_message import UserMessageLite, bulk_insert_ums from zerver.lib.user_message import UserMessageLite, bulk_insert_ums
from zerver.lib.users import ( from zerver.lib.users import (
check_can_access_user, check_can_access_user,
check_user_can_access_all_users, get_inaccessible_user_ids,
get_accessible_user_ids,
get_subscribers_of_target_user_subscriptions, get_subscribers_of_target_user_subscriptions,
get_user_ids_who_can_access_user, get_user_ids_who_can_access_user,
get_users_involved_in_dms_with_target_users, get_users_involved_in_dms_with_target_users,
@ -1556,14 +1555,9 @@ def check_private_message_policy(
def check_sender_can_access_recipients( def check_sender_can_access_recipients(
realm: Realm, sender: UserProfile, user_profiles: Sequence[UserProfile] realm: Realm, sender: UserProfile, user_profiles: Sequence[UserProfile]
) -> None: ) -> None:
if check_user_can_access_all_users(sender): recipient_user_ids = [user.id for user in user_profiles]
return inaccessible_recipients = get_inaccessible_user_ids(recipient_user_ids, sender)
users_accessible_to_sender = set(get_accessible_user_ids(realm, sender))
# Guest users can access all the bots (including cross-realm bots).
non_bot_recipient_user_ids = {user.id for user in user_profiles if not user.is_bot}
inaccessible_recipients = non_bot_recipient_user_ids - users_accessible_to_sender
if inaccessible_recipients: if inaccessible_recipients:
raise JsonableError(_("You do not have permission to access some of the recipients.")) raise JsonableError(_("You do not have permission to access some of the recipients."))