Exemple #1
0
def update_user_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: int,
    full_name: Optional[str] = REQ(default=None, validator=check_string),
    role: Optional[int] = REQ(default=None,
                              validator=check_int_in(
                                  UserProfile.ROLE_TYPES, )),
    profile_data: Optional[List[Dict[str, Optional[Union[
        int, str, List[int]]]]]] = REQ(
            default=None,
            validator=check_profile_data,
        ),
) -> HttpResponse:
    target = access_user_by_id(user_profile,
                               user_id,
                               allow_deactivated=True,
                               allow_bots=True,
                               for_admin=True)

    if role is not None and target.role != role:
        # Require that the current user has permissions to
        # grant/remove the role in question.  access_user_by_id has
        # already verified we're an administrator; here we enforce
        # that only owners can toggle the is_realm_owner flag.
        if UserProfile.ROLE_REALM_OWNER in [
                role, target.role
        ] and not user_profile.is_realm_owner:
            raise OrganizationOwnerRequired()

        if target.role == UserProfile.ROLE_REALM_OWNER and check_last_owner(
                user_profile):
            return json_error(
                _('The owner permission cannot be removed from the only organization owner.'
                  ))
        do_change_user_role(target, role, acting_user=user_profile)

    if (full_name is not None and target.full_name != full_name
            and full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    if profile_data is not None:
        clean_profile_data = []
        for entry in profile_data:
            assert isinstance(entry["id"], int)
            if entry["value"] is None or not entry["value"]:
                field_id = entry["id"]
                check_remove_custom_profile_field_value(target, field_id)
            else:
                clean_profile_data.append({
                    "id": entry["id"],
                    "value": entry["value"],
                })
        validate_user_custom_profile_data(target.realm.id, clean_profile_data)
        do_update_user_custom_profile_data_if_changed(target,
                                                      clean_profile_data)

    return json_success()
Exemple #2
0
def get_members_backend(request: HttpRequest, user_profile: UserProfile, user_id: Optional[int]=None,
                        include_custom_profile_fields: bool=REQ(validator=check_bool,
                                                                default=False),
                        client_gravatar: bool=REQ(validator=check_bool, default=False),
                        ) -> HttpResponse:
    '''
    The client_gravatar field here is set to True if clients can compute
    their own gravatars, which saves us bandwidth.  We want to eventually
    make this the default behavior, but we have old clients that expect
    the server to compute this for us.
    '''
    realm = user_profile.realm
    if realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE:
        # If email addresses are only available to administrators,
        # clients cannot compute gravatars, so we force-set it to false.
        client_gravatar = False
    target_user = None
    if user_id is not None:
        target_user = access_user_by_id(user_profile, user_id, allow_deactivated=True,
                                        allow_bots=True, read_only=True)

    members = get_raw_user_data(realm, user_profile, target_user=target_user,
                                client_gravatar=client_gravatar,
                                user_avatar_url_field_optional=False,
                                include_custom_profile_fields=include_custom_profile_fields)

    if target_user is not None:
        data: Dict[str, Any] = {"user": members[target_user.id]}
    else:
        data = {"members": [members[k] for k in members]}

    return json_success(data)
Exemple #3
0
def update_user_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: int,
    full_name: Optional[str] = REQ(default="", validator=check_string),
    is_admin: Optional[bool] = REQ(default=None, validator=check_bool)
) -> HttpResponse:
    target = access_user_by_id(user_profile,
                               user_id,
                               allow_deactivated=True,
                               allow_bots=True)

    if is_admin is not None:
        if not is_admin and check_last_admin(user_profile):
            return json_error(
                _('Cannot remove the only organization administrator'))
        do_change_is_admin(target, is_admin)

    if (full_name is not None and target.full_name != full_name
            and full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    return json_success()
Exemple #4
0
def update_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int,
                        full_name: Optional[str]=REQ(default=None, validator=check_string),
                        role: Optional[int]=REQ(default=None, validator=check_int_in(
                            UserProfile.ROLE_TYPES)),
                        profile_data: Optional[List[Dict[str, Union[int, str, List[int]]]]]=
                        REQ(default=None,
                            validator=check_list(check_dict([('id', check_int)])))) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)

    if role is not None and target.role != role:
        if target.role == UserProfile.ROLE_REALM_OWNER and check_last_owner(user_profile):
            return json_error(_('The owner permission cannot be removed from the only organization owner.'))
        if UserProfile.ROLE_REALM_OWNER in [role, target.role] and not user_profile.is_realm_owner:
            raise OrganizationOwnerRequired()
        do_change_user_role(target, role)

    if (full_name is not None and target.full_name != full_name and
            full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    if profile_data is not None:
        clean_profile_data = []
        for entry in profile_data:
            if not entry["value"]:
                field_id = entry["id"]
                check_remove_custom_profile_field_value(target, field_id)
            else:
                clean_profile_data.append(entry)
        validate_user_custom_profile_data(target.realm.id, clean_profile_data)
        do_update_user_custom_profile_data_if_changed(target, clean_profile_data)

    return json_success()
Exemple #5
0
def reactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile,
                               user_id,
                               allow_deactivated=True,
                               allow_bots=True)
    do_reactivate_user(target, acting_user=user_profile)
    return json_success()
Exemple #6
0
def reactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)
    if target.is_bot:
        assert target.bot_type is not None
        check_bot_creation_policy(user_profile, target.bot_type)
    do_reactivate_user(target, acting_user=user_profile)
    return json_success()
Exemple #7
0
def reactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)
    if target.is_bot:
        assert target.bot_type is not None
        check_bot_creation_policy(user_profile, target.bot_type)
    do_reactivate_user(target, acting_user=user_profile)
    return json_success()
Exemple #8
0
def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id)
    if target.is_realm_owner and not user_profile.is_realm_owner:
        return json_error(
            _('Only owners can deactivate other organization owners.'))
    if check_last_owner(target):
        return json_error(_('Cannot deactivate the only organization owner'))
    return _deactivate_user_profile_backend(request, user_profile, target)
Exemple #9
0
def get_subscription_backend(request: HttpRequest, user_profile: UserProfile,
                             user_id: int=REQ(validator=check_int, path_only=True),
                             stream_id: int=REQ(validator=check_int, path_only=True),
                             ) -> HttpResponse:
    target_user = access_user_by_id(user_profile, user_id, read_only=True)
    (stream, recipient, sub) = access_stream_by_id(user_profile, stream_id)

    subscription_status = {'is_subscribed': subscribed_to_stream(target_user, stream_id)}

    return json_success(subscription_status)
Exemple #10
0
def unmute_user(
    request: HttpRequest, user_profile: UserProfile, muted_user_id: int
) -> HttpResponse:
    muted_user = access_user_by_id(user_profile, muted_user_id, allow_bots=False, for_admin=False)

    if not user_is_muted(user_profile, muted_user):
        return json_error(_("User is not muted"))

    do_unmute_user(user_profile, muted_user)
    return json_success()
Exemple #11
0
def unmute_user(
    request: HttpRequest, user_profile: UserProfile, muted_user_id: int
) -> HttpResponse:
    muted_user = access_user_by_id(user_profile, muted_user_id, allow_bots=False, for_admin=False)
    mute_object = get_mute_object(user_profile, muted_user)

    if mute_object is None:
        raise JsonableError(_("User is not muted"))

    do_unmute_user(mute_object)
    return json_success()
Exemple #12
0
def mute_user(request: HttpRequest, user_profile: UserProfile, muted_user_id: int) -> HttpResponse:
    if user_profile.id == muted_user_id:
        return json_error(_("Cannot mute self"))

    muted_user = access_user_by_id(user_profile, muted_user_id, allow_bots=False, for_admin=False)
    date_muted = timezone_now()

    if user_is_muted(user_profile, muted_user):
        return json_error(_("User already muted"))

    do_mute_user(user_profile, muted_user, date_muted)
    return json_success()
Exemple #13
0
def update_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int,
                        full_name: Optional[str]=REQ(default="", validator=check_string),
                        is_admin: Optional[bool]=REQ(default=None, validator=check_bool),
                        is_guest: Optional[bool]=REQ(default=None, validator=check_bool),
                        profile_data: Optional[List[Dict[str, Union[int, str, List[int]]]]]=
                        REQ(default=None,
                            validator=check_list(check_dict([('id', check_int)])))) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)

    # Historically, UserProfile had two fields, is_guest and is_realm_admin.
    # This condition protected against situations where update_user_backend
    # could cause both is_guest and is_realm_admin to be set.
    # Once we update the frontend to just send a 'role' value, we can remove this check.
    if (((is_guest is None and target.is_guest) or is_guest) and
            ((is_admin is None and target.is_realm_admin) or is_admin)):
        return json_error(_("Guests cannot be organization administrators"))

    role = None
    if is_admin is not None and target.is_realm_admin != is_admin:
        if not is_admin and check_last_admin(user_profile):
            return json_error(_('Cannot remove the only organization administrator'))
        role = UserProfile.ROLE_MEMBER
        if is_admin:
            role = UserProfile.ROLE_REALM_ADMINISTRATOR

    if is_guest is not None and target.is_guest != is_guest:
        if is_guest:
            role = UserProfile.ROLE_GUEST
        if role is None:
            role = UserProfile.ROLE_MEMBER

    if role is not None and target.role != role:
        do_change_user_role(target, role)

    if (full_name is not None and target.full_name != full_name and
            full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    if profile_data is not None:
        clean_profile_data = []
        for entry in profile_data:
            if not entry["value"]:
                field_id = entry["id"]
                check_remove_custom_profile_field_value(target, field_id)
            else:
                clean_profile_data.append(entry)
        validate_user_custom_profile_data(target.realm.id, clean_profile_data)
        do_update_user_custom_profile_data_if_changed(target, clean_profile_data)

    return json_success()
Exemple #14
0
def update_user_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: int,
    full_name: Optional[str] = REQ(default="", validator=check_string),
    is_admin: Optional[bool] = REQ(default=None, validator=check_bool),
    is_guest: Optional[bool] = REQ(default=None, validator=check_bool),
    profile_data: List[Dict[str, Union[int, str, List[int]]]] = REQ(
        default=None, validator=check_list(check_dict([('id', check_int)])))
) -> HttpResponse:
    target = access_user_by_id(user_profile,
                               user_id,
                               allow_deactivated=True,
                               allow_bots=True)

    # This condition is a bit complicated, because the user could
    # already be a guest/admin, or the request could be to make the
    # user a guest/admin.  In any case, the point is that we outright
    # reject requests that would result in a user who is both an admin
    # and a guest.
    if (((is_guest is None and target.is_guest) or is_guest)
            and ((is_admin is None and target.is_realm_admin) or is_admin)):
        return json_error(_("Guests cannot be organization administrators"))

    if is_admin is not None and target.is_realm_admin != is_admin:
        if not is_admin and check_last_admin(user_profile):
            return json_error(
                _('Cannot remove the only organization administrator'))
        do_change_is_admin(target, is_admin)

    if is_guest is not None and target.is_guest != is_guest:
        do_change_is_guest(target, is_guest)

    if (full_name is not None and target.full_name != full_name
            and full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    if profile_data is not None:
        clean_profile_data = []
        for entry in profile_data:
            if not entry["value"]:
                field_id = entry["id"]
                check_remove_custom_profile_field_value(target, field_id)
            else:
                clean_profile_data.append(entry)
        validate_user_custom_profile_data(target.realm.id, clean_profile_data)
        do_update_user_custom_profile_data(target, clean_profile_data)

    return json_success()
Exemple #15
0
def get_subscription_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: int = REQ(json_validator=check_int, path_only=True),
    stream_id: int = REQ(json_validator=check_int, path_only=True),
) -> HttpResponse:
    target_user = access_user_by_id(user_profile, user_id, for_admin=False)
    (stream, sub) = access_stream_by_id(user_profile,
                                        stream_id,
                                        allow_realm_admin=True)

    subscription_status = {
        "is_subscribed": subscribed_to_stream(target_user, stream_id)
    }

    return json_success(request, data=subscription_status)
Exemple #16
0
def update_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int,
                        full_name: Optional[str]=REQ(default="", validator=check_string),
                        is_admin: Optional[bool]=REQ(default=None, validator=check_bool)) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)

    if is_admin is not None:
        if not is_admin and check_last_admin(user_profile):
            return json_error(_('Cannot remove the only organization administrator'))
        do_change_is_admin(target, is_admin)

    if (full_name is not None and target.full_name != full_name and
            full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    return json_success()
Exemple #17
0
def mute_user(request: HttpRequest, user_profile: UserProfile,
              muted_user_id: int) -> HttpResponse:
    if user_profile.id == muted_user_id:
        raise JsonableError(_("Cannot mute self"))

    muted_user = access_user_by_id(user_profile,
                                   muted_user_id,
                                   allow_bots=False,
                                   allow_deactivated=True,
                                   for_admin=False)
    date_muted = timezone_now()

    if get_mute_object(user_profile, muted_user) is not None:
        raise JsonableError(_("User already muted"))

    do_mute_user(user_profile, muted_user, date_muted)
    return json_success()
Exemple #18
0
def update_user_backend(request: HttpRequest, user_profile: UserProfile, user_id: int,
                        full_name: Optional[str]=REQ(default="", validator=check_string),
                        is_admin: Optional[bool]=REQ(default=None, validator=check_bool),
                        is_guest: Optional[bool]=REQ(default=None, validator=check_bool),
                        profile_data: List[Dict[str, Union[int, str, List[int]]]]=
                        REQ(default=None,
                            validator=check_list(check_dict([('id', check_int)])))) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)

    # This condition is a bit complicated, because the user could
    # already be a guest/admin, or the request could be to make the
    # user a guest/admin.  In any case, the point is that we outright
    # reject requests that would result in a user who is both an admin
    # and a guest.
    if (((is_guest is None and target.is_guest) or is_guest) and
            ((is_admin is None and target.is_realm_admin) or is_admin)):
        return json_error(_("Guests cannot be organization administrators"))

    if is_admin is not None and target.is_realm_admin != is_admin:
        if not is_admin and check_last_admin(user_profile):
            return json_error(_('Cannot remove the only organization administrator'))
        do_change_is_admin(target, is_admin)

    if is_guest is not None and target.is_guest != is_guest:
        do_change_is_guest(target, is_guest)

    if (full_name is not None and target.full_name != full_name and
            full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    if profile_data is not None:
        clean_profile_data = []
        for entry in profile_data:
            if not entry["value"]:
                field_id = entry["id"]
                check_remove_custom_profile_field_value(target, field_id)
            else:
                clean_profile_data.append(entry)
        validate_user_custom_profile_data(target.realm.id, clean_profile_data)
        do_update_user_custom_profile_data(target, clean_profile_data)

    return json_success()
Exemple #19
0
def get_members_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: Optional[int] = None,
    include_custom_profile_fields: bool = REQ(json_validator=check_bool,
                                              default=False),
    client_gravatar: bool = REQ(json_validator=check_bool, default=True),
) -> HttpResponse:
    """
    The client_gravatar field here is set to True by default assuming that clients
    can compute their own gravatars, which saves bandwidth. This is more important of
    an optimization than it might seem because gravatar URLs contain MD5 hashes that
    compress very poorly compared to other data.
    """
    realm = user_profile.realm
    if realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE:
        # If email addresses are only available to administrators,
        # clients cannot compute gravatars, so we force-set it to false.
        client_gravatar = False
    target_user = None
    if user_id is not None:
        target_user = access_user_by_id(user_profile,
                                        user_id,
                                        allow_deactivated=True,
                                        allow_bots=True,
                                        for_admin=False)

    members = get_raw_user_data(
        realm,
        user_profile,
        target_user=target_user,
        client_gravatar=client_gravatar,
        user_avatar_url_field_optional=False,
        include_custom_profile_fields=include_custom_profile_fields,
    )

    if target_user is not None:
        data: Dict[str, Any] = {"user": members[target_user.id]}
    else:
        data = {"members": [members[k] for k in members]}

    return json_success(data)
Exemple #20
0
def get_members_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: Optional[int] = None,
    include_custom_profile_fields: bool = REQ(json_validator=check_bool,
                                              default=False),
    client_gravatar: bool = REQ(json_validator=check_bool, default=True),
) -> HttpResponse:
    target_user = None
    if user_id is not None:
        target_user = access_user_by_id(user_profile,
                                        user_id,
                                        allow_deactivated=True,
                                        allow_bots=True,
                                        for_admin=False)

    data = get_user_data(user_profile, include_custom_profile_fields,
                         client_gravatar, target_user)

    return json_success(request, data)
Exemple #21
0
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)
        },
    )
Exemple #22
0
def update_user_backend(
    request: HttpRequest,
    user_profile: UserProfile,
    user_id: int,
    full_name: Optional[str] = REQ(default="", validator=check_string),
    is_admin: Optional[bool] = REQ(default=None, validator=check_bool),
    is_guest: Optional[bool] = REQ(default=None, validator=check_bool)
) -> HttpResponse:
    target = access_user_by_id(user_profile,
                               user_id,
                               allow_deactivated=True,
                               allow_bots=True)

    # This condition is a bit complicated, because the user could
    # already be a guest/admin, or the request could be to make the
    # user a guest/admin.  In any case, the point is that we outright
    # reject requests that would result in a user who is both an admin
    # and a guest.
    if (((is_guest is None and target.is_guest) or is_guest)
            and ((is_admin is None and target.is_realm_admin) or is_admin)):
        return json_error(_("Guests cannot be organization administrators"))

    if is_admin is not None and target.is_realm_admin != is_admin:
        if not is_admin and check_last_admin(user_profile):
            return json_error(
                _('Cannot remove the only organization administrator'))
        do_change_is_admin(target, is_admin)

    if is_guest is not None and target.is_guest != is_guest:
        do_change_is_guest(target, is_guest)

    if (full_name is not None and target.full_name != full_name
            and full_name.strip() != ""):
        # We don't respect `name_changes_disabled` here because the request
        # is on behalf of the administrator.
        check_change_full_name(target, full_name, user_profile)

    return json_success()
Exemple #23
0
    def test_access_user_by_id(self) -> None:
        iago = self.example_user("iago")

        # Must be a valid user ID in the realm
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, 1234)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, self.mit_user("sipbtest").id)

        # Can only access bot users if allow_deactivated is passed
        bot = self.example_user("welcome_bot")
        access_user_by_id(iago, bot.id, allow_bots=True)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, bot.id)

        # Can only access deactivated users if allow_deactivated is passed
        hamlet = self.example_user("hamlet")
        do_deactivate_user(hamlet)
        with self.assertRaises(JsonableError):
            access_user_by_id(iago, hamlet.id)
        access_user_by_id(iago, hamlet.id, allow_deactivated=True)

        # Non-admin user can't admin another user
        with self.assertRaises(JsonableError):
            access_user_by_id(self.example_user("cordelia"), self.example_user("aaron").id)
Exemple #24
0
def reactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id, allow_deactivated=True, allow_bots=True)
    do_reactivate_user(target, acting_user=user_profile)
    return json_success()
Exemple #25
0
def deactivate_user_backend(request: HttpRequest, user_profile: UserProfile,
                            user_id: int) -> HttpResponse:
    target = access_user_by_id(user_profile, user_id)
    if check_last_admin(target):
        return json_error(_('Cannot deactivate the only organization administrator'))
    return _deactivate_user_profile_backend(request, user_profile, target)