def remove_members_from_group_backend(request: HttpRequest, user_profile: UserProfile, user_group_id: int, members: List[int]) -> HttpResponse: if not members: return json_success() user_profiles = user_ids_to_users(members, user_profile.realm) user_group = access_user_group_by_id(user_group_id, user_profile.realm) remove_members_from_user_group(user_group, user_profiles) return json_success()
def remove_members_from_group_backend(request: HttpRequest, user_profile: UserProfile, user_group_id: int, members: List[int]) -> HttpResponse: if not members: return json_success() user_profiles = user_ids_to_users(members, user_profile.realm) user_group = access_user_group_by_id(user_group_id, user_profile) group_member_ids = get_user_group_members(user_group) for member in members: if (member not in group_member_ids): raise JsonableError(_("There is no member '%s' in this user group" % (member,))) remove_members_from_user_group(user_group, user_profiles) return json_success()
def add_members_to_group_backend(request: HttpRequest, user_profile: UserProfile, user_group_id: int, members: List[int]) -> HttpResponse: if not members: return json_success() user_group = access_user_group_by_id(user_group_id, user_profile) user_profiles = user_ids_to_users(members, user_profile.realm) existing_member_ids = set(get_memberships_of_users(user_group, user_profiles)) for user_profile in user_profiles: if user_profile.id in existing_member_ids: raise JsonableError(_("User %s is already a member of this group" % (user_profile.id,))) bulk_add_members_to_user_group(user_group, user_profiles) return json_success()
def edit_user_group(request: HttpRequest, user_profile: UserProfile, user_group_id: int=REQ(validator=check_int), name: str=REQ(default=""), description: str=REQ(default="") ) -> HttpResponse: if not (name or description): return json_error(_("No new data supplied")) user_group = access_user_group_by_id(user_group_id, user_profile) result = {} if name != user_group.name: do_update_user_group_name(user_group, name) result['name'] = _("Name successfully updated.") if description != user_group.description: do_update_user_group_description(user_group, description) result['description'] = _("Description successfully updated.") return json_success(result)
def add_members_to_group_backend(request: HttpRequest, user_profile: UserProfile, user_group_id: int, members: List[int]) -> HttpResponse: if not members: return json_success() user_group = access_user_group_by_id(user_group_id, user_profile) user_profiles = user_ids_to_users(members, user_profile.realm) existing_member_ids = set( get_memberships_of_users(user_group, user_profiles)) for user_profile in user_profiles: if user_profile.id in existing_member_ids: raise JsonableError( _("User {user_id} is already a member of this group").format( user_id=user_profile.id, )) bulk_add_members_to_user_group(user_group, user_profiles) return json_success()
def edit_user_group( request: HttpRequest, user_profile: UserProfile, user_group_id: int = REQ(validator=check_int, path_only=True), name: str = REQ(default=""), description: str = REQ(default=""), ) -> HttpResponse: if not (name or description): return json_error(_("No new data supplied")) user_group = access_user_group_by_id(user_group_id, user_profile) if name != user_group.name: do_update_user_group_name(user_group, name) if description != user_group.description: do_update_user_group_description(user_group, description) return json_success()
def get_is_user_group_member( request: HttpRequest, user_profile: UserProfile, user_group_id: int = REQ(json_validator=check_int, path_only=True), user_id: int = REQ(json_validator=check_int, path_only=True), direct_member_only: bool = REQ(json_validator=check_bool, default=False), ) -> HttpResponse: user_group = access_user_group_by_id(user_group_id, user_profile, for_read=True) target_user = access_user_by_id(user_profile, user_id, for_admin=False) return json_success( request, data={ "is_user_group_member": is_user_in_group(user_group, target_user, direct_member_only=direct_member_only) }, )
def edit_user_group( request: HttpRequest, user_profile: UserProfile, user_group_id: int = REQ(validator=check_int), name: str = REQ(default=""), description: str = REQ(default="") ) -> HttpResponse: if not (name or description): return json_error(_("No new data supplied")) user_group = access_user_group_by_id(user_group_id, user_profile) result = {} if name != user_group.name: do_update_user_group_name(user_group, name) result['name'] = _("Name successfully updated.") if description != user_group.description: do_update_user_group_description(user_group, description) result['description'] = _("Description successfully updated.") return json_success(result)
def get_mentioned_user_group_name(messages: List[Dict[str, Any]], user_profile: UserProfile) -> Optional[str]: """Returns the user group name to display in the email notification if user group(s) are mentioned. This implements the same algorithm as get_user_group_mentions_data in zerver/lib/notification_data.py, but we're passed a list of messages instead. """ for message in messages: if message["mentioned_user_group_id"] is None and message[ "trigger"] == "mentioned": # The user has also been personally mentioned, so that gets prioritized. return None # These IDs are those of the smallest user groups mentioned in each message. mentioned_user_group_ids = [ message["mentioned_user_group_id"] for message in messages if message["mentioned_user_group_id"] is not None ] # We now want to calculate the name of the smallest user group mentioned among # all these messages. smallest_user_group_size = math.inf smallest_user_group_name = None for user_group_id in mentioned_user_group_ids: current_user_group = access_user_group_by_id(user_group_id, user_profile, for_mention=True) current_user_group_size = len( get_user_group_members(current_user_group)) if current_user_group_size < smallest_user_group_size: # If multiple user groups are mentioned, we prefer the # user group with the least members. smallest_user_group_size = current_user_group_size smallest_user_group_name = current_user_group.name return smallest_user_group_name
def get_apns_alert_subtitle( user_profile: UserProfile, message: Message, mentioned_user_group_id: Optional[int] = None) -> str: """ On an iOS notification, this is the second bolded line. """ if message.trigger == "mentioned": if mentioned_user_group_id is not None: user_group = access_user_group_by_id(mentioned_user_group_id, user_profile) return _("{full_name} mentioned @{user_group_name}:").format( full_name=message.sender.full_name, user_group_name=user_group.name) else: return _("{full_name} mentioned you:").format( full_name=message.sender.full_name) elif message.trigger == "wildcard_mentioned": return _("{full_name} mentioned everyone:").format( full_name=message.sender.full_name) elif message.recipient.type == Recipient.PERSONAL: return "" # For group PMs, or regular messages to a stream, just use a colon to indicate this is the sender. return message.sender.full_name + ":"
def check_delete_user_group(user_group_id: int, user_profile: UserProfile) -> None: user_group = access_user_group_by_id(user_group_id, user_profile) user_group.delete() do_send_delete_user_group_event(user_profile.realm, user_group_id, user_profile.realm.id)
def handle_push_notification(user_profile_id: int, missed_message: Dict[str, Any]) -> None: """ missed_message is the event received by the zerver.worker.queue_processors.PushNotificationWorker.consume function. """ if not push_notifications_enabled(): return user_profile = get_user_profile_by_id(user_profile_id) if user_profile.is_bot: # BUG: Investigate why it's possible to get here. return # nocoverage if not (user_profile.enable_offline_push_notifications or user_profile.enable_online_push_notifications): # BUG: Investigate why it's possible to get here. return # nocoverage try: (message, user_message) = access_message(user_profile, missed_message["message_id"]) except JsonableError: if ArchivedMessage.objects.filter( id=missed_message["message_id"]).exists(): # If the cause is a race with the message being deleted, # that's normal and we have no need to log an error. return logging.info( "Unexpected message access failure handling push notifications: %s %s", user_profile.id, missed_message["message_id"], ) return if user_message is not None: # If the user has read the message already, don't push-notify. if user_message.flags.read or user_message.flags.active_mobile_push_notification: return # Otherwise, we mark the message as having an active mobile # push notification, so that we can send revocation messages # later. user_message.flags.active_mobile_push_notification = True user_message.save(update_fields=["flags"]) else: # Users should only be getting push notifications into this # queue for messages they haven't received if they're # long-term idle; anything else is likely a bug. if not user_profile.long_term_idle: logger.error( "Could not find UserMessage with message_id %s and user_id %s", missed_message["message_id"], user_profile_id, exc_info=True, ) return trigger = missed_message["trigger"] mentioned_user_group_name = None mentioned_user_group_id = missed_message.get("mentioned_user_group_id") if mentioned_user_group_id is not None: user_group = access_user_group_by_id(mentioned_user_group_id, user_profile, for_mention=True) mentioned_user_group_name = user_group.name apns_payload = get_message_payload_apns(user_profile, message, trigger, mentioned_user_group_id, mentioned_user_group_name) gcm_payload, gcm_options = get_message_payload_gcm( user_profile, message, trigger, mentioned_user_group_id, mentioned_user_group_name) logger.info("Sending push notifications to mobile clients for user %s", user_profile_id) if uses_notification_bouncer(): send_notifications_to_bouncer(user_profile_id, apns_payload, gcm_payload, gcm_options) return android_devices = list( PushDeviceToken.objects.filter(user=user_profile, kind=PushDeviceToken.GCM)) apple_devices = list( PushDeviceToken.objects.filter(user=user_profile, kind=PushDeviceToken.APNS)) send_apple_push_notification(user_profile.id, apple_devices, apns_payload) send_android_push_notification(android_devices, gcm_payload, gcm_options)