Esempio n. 1
0
def notify_realm_custom_profile_fields(realm: Realm) -> None:
    fields = custom_profile_fields_for_realm(realm.id)
    event = dict(type="custom_profile_fields", fields=[f.as_dict() for f in fields])
    send_event(realm, event, active_user_ids(realm.id))
Esempio n. 2
0
def send_stream_creation_event(stream: Stream, user_ids: List[int]) -> None:
    event = dict(type="stream", op="create", streams=[stream.to_dict()])
    send_event(stream.realm, event, user_ids)
Esempio n. 3
0
def do_change_bot_owner(user_profile: UserProfile, bot_owner: UserProfile,
                        acting_user: UserProfile) -> None:
    previous_owner = user_profile.bot_owner
    user_profile.bot_owner = bot_owner
    user_profile.save(
    )  # Can't use update_fields because of how the foreign key works.
    event_time = timezone_now()
    RealmAuditLog.objects.create(
        realm=user_profile.realm,
        acting_user=acting_user,
        modified_user=user_profile,
        event_type=RealmAuditLog.USER_BOT_OWNER_CHANGED,
        event_time=event_time,
    )

    update_users = bot_owner_user_ids(user_profile)

    # For admins, update event is sent instead of delete/add
    # event. bot_data of admin contains all the
    # bots and none of them should be removed/(added again).

    # Delete the bot from previous owner's bot data.
    if previous_owner and not previous_owner.is_realm_admin:
        delete_event = dict(
            type="realm_bot",
            op="delete",
            bot=dict(user_id=user_profile.id, ),
        )
        transaction.on_commit(lambda: send_event(
            user_profile.realm,
            delete_event,
            {previous_owner.id},
        ))
        # Do not send update event for previous bot owner.
        update_users = update_users - {previous_owner.id}

    # Notify the new owner that the bot has been added.
    if not bot_owner.is_realm_admin:
        add_event = created_bot_event(user_profile)
        transaction.on_commit(
            lambda: send_event(user_profile.realm, add_event, {bot_owner.id}))
        # Do not send update event for bot_owner.
        update_users = update_users - {bot_owner.id}

    bot_event = dict(
        type="realm_bot",
        op="update",
        bot=dict(
            user_id=user_profile.id,
            owner_id=user_profile.bot_owner.id,
        ),
    )
    transaction.on_commit(lambda: send_event(
        user_profile.realm,
        bot_event,
        update_users,
    ))

    # Since `bot_owner_id` is included in the user profile dict we need
    # to update the users dict with the new bot owner id
    event = dict(
        type="realm_user",
        op="update",
        person=dict(
            user_id=user_profile.id,
            bot_owner_id=user_profile.bot_owner.id,
        ),
    )
    transaction.on_commit(lambda: send_event(
        user_profile.realm, event, active_user_ids(user_profile.realm_id)))
Esempio n. 4
0
def do_update_message_flags(user_profile: UserProfile, operation: str,
                            flag: str,
                            messages: List[int]) -> Tuple[int, List[int]]:
    valid_flags = [
        item for item in UserMessage.flags
        if item not in UserMessage.NON_API_FLAGS
    ]
    if flag not in valid_flags:
        raise JsonableError(_("Invalid flag: '{}'").format(flag))
    if flag in UserMessage.NON_EDITABLE_FLAGS:
        raise JsonableError(_("Flag not editable: '{}'").format(flag))
    if operation not in ("add", "remove"):
        raise JsonableError(
            _("Invalid message flag operation: '{}'").format(operation))
    flagattr = getattr(UserMessage.flags, flag)

    msgs = UserMessage.objects.filter(user_profile=user_profile,
                                      message_id__in=messages)
    um_message_ids = {um.message_id for um in msgs}
    historical_message_ids = list(set(messages) - um_message_ids)

    # Users can mutate flags for messages that don't have a UserMessage yet.
    # First, validate that the user is even allowed to access these message_ids.
    for message_id in historical_message_ids:
        access_message(user_profile, message_id)

    # And then create historical UserMessage records.  See the called function for more context.
    create_historical_user_messages(user_id=user_profile.id,
                                    message_ids=historical_message_ids)
    with transaction.atomic():
        if operation == "add":
            msgs = (msgs.select_for_update().order_by("message_id").extra(
                where=[UserMessage.where_flag_is_absent(flagattr)]))
            updated_message_ids = [um.message_id for um in msgs]
            msgs.filter(message_id__in=updated_message_ids).update(
                flags=F("flags").bitor(flagattr))
        elif operation == "remove":
            msgs = (msgs.select_for_update().order_by("message_id").extra(
                where=[UserMessage.where_flag_is_present(flagattr)]))
            updated_message_ids = [um.message_id for um in msgs]
            msgs.filter(message_id__in=updated_message_ids).update(
                flags=F("flags").bitand(~flagattr))

    count = len(updated_message_ids)
    event = {
        "type": "update_message_flags",
        "op": operation,
        "operation": operation,
        "flag": flag,
        "messages": updated_message_ids,
        "all": False,
    }

    if flag == "read" and operation == "remove":
        # When removing the read flag (i.e. marking messages as
        # unread), extend the event with an additional object with
        # details on the messages required to update the client's
        # `unread_msgs` data structure.
        raw_unread_data = get_raw_unread_data(user_profile,
                                              updated_message_ids)
        event["message_details"] = format_unread_message_details(
            user_profile.id, raw_unread_data)

    send_event(user_profile.realm, event, [user_profile.id])

    if flag == "read" and operation == "add":
        event_time = timezone_now()
        do_clear_mobile_push_notifications_for_ids([user_profile.id],
                                                   updated_message_ids)

        do_increment_logging_stat(user_profile,
                                  COUNT_STATS["messages_read::hour"],
                                  None,
                                  event_time,
                                  increment=count)
        do_increment_logging_stat(
            user_profile,
            COUNT_STATS["messages_read_interactions::hour"],
            None,
            event_time,
            increment=min(1, count),
        )

    return count, updated_message_ids
Esempio n. 5
0
def do_send_delete_user_group_event(realm: Realm, user_group_id: int,
                                    realm_id: int) -> None:
    event = dict(type="user_group", op="remove", group_id=user_group_id)
    send_event(realm, event, active_user_ids(realm_id))
Esempio n. 6
0
def do_deactivate_user(
    user_profile: UserProfile, _cascade: bool = True, *, acting_user: Optional[UserProfile]
) -> None:
    if not user_profile.is_active:
        return

    if _cascade:
        # We need to deactivate bots before the target user, to ensure
        # that a failure partway through this function cannot result
        # in only the user being deactivated.
        bot_profiles = get_active_bots_owned_by_user(user_profile)
        for profile in bot_profiles:
            do_deactivate_user(profile, _cascade=False, acting_user=acting_user)

    with transaction.atomic():
        if user_profile.realm.is_zephyr_mirror_realm:  # nocoverage
            # For zephyr mirror users, we need to make them a mirror dummy
            # again; otherwise, other users won't get the correct behavior
            # when trying to send messages to this person inside Zulip.
            #
            # Ideally, we need to also ensure their zephyr mirroring bot
            # isn't running, but that's a separate issue.
            user_profile.is_mirror_dummy = True
            user_profile.save(update_fields=["is_mirror_dummy"])

        change_user_is_active(user_profile, False)

        clear_scheduled_emails(user_profile.id)
        revoke_invites_generated_by_user(user_profile)

        event_time = timezone_now()
        RealmAuditLog.objects.create(
            realm=user_profile.realm,
            modified_user=user_profile,
            acting_user=acting_user,
            event_type=RealmAuditLog.USER_DEACTIVATED,
            event_time=event_time,
            extra_data=orjson.dumps(
                {
                    RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm),
                }
            ).decode(),
        )
        do_increment_logging_stat(
            user_profile.realm,
            COUNT_STATS["active_users_log:is_bot:day"],
            user_profile.is_bot,
            event_time,
            increment=-1,
        )
        if settings.BILLING_ENABLED:
            update_license_ledger_if_needed(user_profile.realm, event_time)

    delete_user_sessions(user_profile)
    event = dict(
        type="realm_user",
        op="remove",
        person=dict(user_id=user_profile.id, full_name=user_profile.full_name),
    )
    send_event(user_profile.realm, event, active_user_ids(user_profile.realm_id))

    if user_profile.is_bot:
        event = dict(
            type="realm_bot",
            op="remove",
            bot=dict(user_id=user_profile.id, full_name=user_profile.full_name),
        )
        send_event(user_profile.realm, event, bot_owner_user_ids(user_profile))
Esempio n. 7
0
def notify_alert_words(user_profile: UserProfile,
                       words: Sequence[str]) -> None:
    event = dict(type="alert_words", alert_words=words)
    send_event(user_profile.realm, event, [user_profile.id])