When checking DM permissions, instead of using list of
users, we now use set of users to check if any user is
in direct_message_permission_group because there can be
case when sender can also be one of the recipients.
This commit updates code to not pre-fetch DM permission
group settings using select_related and instead just
fetch the required data from DB when checking permission.
This will increase one query but will help in pre-fetching
the settings for all users and for all type of messages.
Fixes part of #33677.
This commit updates is_user_in_group and is_any_user_in_group
to accept group ID as parameter instead of UserGroup object.
This is a prep commit for updating code to not prefetch
direct message permissions group.
This function will be useful in finding out affected groups when
sending events for users gaining or losing metadata access when the
members of a user group change in any way.
On the event side, orjson does the work of converting
UserGroupMembersData to json. But when fetching intial state data,
UserGroupMembersData was being returned which is not
json-serializable. This was causing a mismatch in the `verify_action`
workflow of test_events related to stream group settings where
apply_events resulted in a state with `direct_members` and
`direct_subgroups` as part of an ordinary dict, while fetching initial
state data was giving us a UserGroupMembersData class.
This commit uses UserGroupMembersDict where appropriate. It will
still be good to keep around the dataclass class since it has the added
benefit of storing the relevant value when needed.
UserGroupMembersData is not serializable by orjson. We will be
introducing a TypedDict (which is serializable) in the next commit
called UserGroupMembersDict. This rename will help us distinguish
between the two.
We now return the members and subgroups ID list sorted for
settings that are set to anonymous groups. This is needed to
make sure we do not show save discard buttons when only pill
order is changed.
Passing the user group object in case of named user group is fine for
`do_change_stream_group_based_setting`. But for anonymous groups, if the
code path calling that function is not creating a new anonymous user
group, it has to modify the user group by itself before calling that
function. In that case, if `old_setting_api_value` is not provided,
`old_user_group` is calculated false, since the group id has not changed
for the stream, but the group membership has changed.
old_setting_api_value will be the same as new_setting_api_value in such
a case.
It is better to accept the new setting value as either an int or
UserGroupMembersDict, so that `do_change_stream_group_based_setting` can
decide what to do with that argument.
We do not fetch all the realm group settings using
select_related for register data now since it takes a
lot of time in planning phase. This commit updates
the code to fetch all the members and subgroups data
in user_groups_in_realm_serialized so that we do not
need to access each setting group individually.
user_groups_in_realm_serialized is updated to send the
required data accordingly.
Fixes#33656.
Following improvments are done in user_groups_in_realm_serialized-
- Members and subgroups are fetched using a single query using
union.
- Query to fetch groups now does not fetch setting fields since
we already have the members and subgroups of all the setting
groups and we can check if setting group was a named group
or not directly without checking named_user_group field of
UserGroup object as we have IDs of all named groups of the realm.
This commit updates code to optimize computing users who have
metadata access via permission groups so that we do not have
to do DB query for each stream to get recursive members for
the groups having permissions.
Previously, we needed to pass the group to the function, which sometimes
meant having 1 extra query to fetch the user group when we just needed
the group id for this function.
Fixes: #32934
context:
Fetching all users who are members (directly or via sub-groups)
of groups mentioned in one message.
Reduce O(n) queries, where n is the number
of mentioned groups, to a constant of 1 query.
Extend "get_recursive_subgroups_for_groups" functionality to
"get_root_id_annotated_recursive_subgroups_for_groups"
which is the same but keeps track of each group root_id and
annotates it to each group.
Then in init_user_group_data(), we only fetch
each group's root_id along with
active direct members.
As we now allow anonymous groups and settings can be set to any
set of users, there is no benefit in not allowing a setting to
be set to "Owners" group.
Right now, the number of queries has remained the same, but when we add
more settings in the future, we won't be increasing the number of
queries when iterating over stream permission group settings.
This commit adds support to add subgroups to a group while
creating it.
User can add the subgroups to group irrespective of permissions
like user can add members during creating it.
This commit updates code to allow users with permission
to add members to add subgroups as well. And only users
with permission to manage the group can remove subgroups.
Also updated tests to check permissions in separate tests
and removed them from the existing test.
Users with permission to manage the group have all the permissions
including joining/leaving the group, adding others group which also
have a separate setting to control them.
So, it makes sense to just check managing permissions first in
access_user_group_for_update and then check the specific permission.
There is no behavioral change in this commit, it only changes the
order of checking permissions.
The main change is redefining ALLOW_GROUP_VALUED_SETTINGS to not
control code, but instead to instead control the configuration for
whether settings that have not been converted to use our modern UI
patterns should require system groups.
Fundamentally, it's the same for the realm/stream group-valued
settings, which don't have the new UI patterns yet.
We remove the visual hiding of the "can manage group" setting, which
was hidden only due to transitions being incomplete.
Earlier we use to restrict admins, moderators or members of a group to
manage that group if they were part of the realm wide
`can_manage_all_groups`. We will not do that anymore and even
non-members of a group regardless of role can manage a group if they are
part of `can_manage_all_groups`.
See
https://chat.zulip.org/#narrow/stream/101-design/topic/Group.20add.20members.20dropdown/near/1952902
to check more about the migration plan for which this is the last step.
Removing members will be controlled by `can_manage_group` until we add
`can_remove_members_group` in the future.
Users with permission to manage a group can add members to that group by
default without being present in `can_add_members_group`.
This commit updates backend code to not allow adding deactivated
users to groups including when creating groups and also to not
allow removing deactivated users from groups.
This commit updates code to not include deactivated users in the
anonymous group settings data sent to clients, where the setting
value is sent as a dict containing members and subgroups of the
anonymous group.
This commit updates code to not include deactivated users in
members list in the user groups object sent in "/register"
and "GET /user_groups" response and also in the response
returned by endpoint like "GET /user_groups/{group_id}/members".
The events code is also update to handle this -
- We expect clients to update the members list on receiving
"realm_user/update" event on deactivation. But for guests
who cannot access the user, "user_group/remove_members"
event is sent to update the group members list on deactivation.
- "user_group/add_members" event is sent to all the users on
reactivating the user.
We create an unnamed user group with just the group creator as it's
member when trying to set the default. The pattern I've followed across
most of the acting_user additions is to just put the user declared
somewhere before the check_add_user_group and see if the test passes.
If it does not, then I'll look at what kind of user it needs to be set
to `acting_user`.
The error response when a user group cannot be deactivated due
to it being used as a subgroup or for a setting includes details
about the supergroups, streams, user groups as well the settings
for which it is used.
This commit adds access_user_group_to_read_membership function
so that we can avoid calling get_user_group_by_id_in_realm with
"for_read=True" from views functions, which is better for security
since that function does not do any access checks.
Previously, if the user_group_edit_policy was set to allow
members or full members to manage the group, the user had
to be the direct member of the group being managed.
This commit updates the code to allow members of the subgroups
as well to manage the group as technically members of the
subgroups are member of the group.
This also improves the code to not fetch all the group members
to check this, and instead directly call is_user_in_group
which uses "exists" to check it.
This commit renames has_user_group_access function to
has_user_group_access_for_subgroup, since the function
is only used to check access for using a group as subgroup.
This commit refactors the code to check permission for
accessing user group in such a way that we can avoid
duplicate code in future when we will have different
settings controlling the permissions for editing group
details and settings, joining the group, adding others
to group, etc.
This commit renames "allow_deactivated" parameter in
"GET /user_groups" endpoint to "include_deactivated_groups", so
that we can have consistent naming here and for client capability
used for deciding whether to send deactivated groups in register
response and how to handle the related events.
This commit adds code to handle guests separately for group
based settings, where guest will only have permission if
that particular setting can be set to "role:everyone" group
even if the guest user is part of the group which is used
for that setting. This is to make sure that guests do not
get permissions for actions that we generally do not want
guests to have.
Currently the guests do not have permission for most of them
except for "Who can delete any message", where guest could
delete a message if the setting was set to a user defined
group with guest being its member. But this commit still
update the code to use the new function for all the settings
as we want to have a consistent pattern of how to check whether
a user has permission for group-based settings.
This commit introduced 'creator' and 'date_created'
fields in user groups, allowing users to view who
created the groups and when.
Both fields can be null for groups without creator data.