Commit Graph

114 Commits

Author SHA1 Message Date
Sahil Batra b78ca79ccf user_groups: Define AnonymousSettingGroupDict in types.py.
AnonymousSettingGroupDict is now defined in types.py instead
of user_groups.py to avoid import cycles in future commits.
2024-11-15 16:36:37 -08:00
Prakhar Pratyush 0e67e4f1a1 compose_views: Add `savepoint=False` to avoid creating savepoints.
'compose_views' is used inside an outer db transaction created in
'update_user_group_backend'.

`transaction.atomic()` block in 'compose_views' resulted in
savepoint creation.

This commit adds `savepoint=False` to avoid that.
2024-11-05 17:58:47 -08:00
Prakhar Pratyush 0fb5657131 transaction: Add durable=True to outermost transaction.atomic decorator.
This commit adds 'durable=True' to the outermost transactions
of the following functions:
* do_create_multiuse_invite_link
* do_revoke_user_invite
* do_revoke_multi_use_invite
* sync_ldap_user_data
* do_reactivate_remote_server
* do_deactivate_remote_server
* bulk_handle_digest_email
* handle_customer_migration_from_server_to_realm
* add_reaction
* remove_reaction
* deactivate_user_group

It helps to avoid creating unintended savepoints in the future.

This is as a part of our plan to explicitly mark all the
transaction.atomic decorators with either 'savepoint=False' or
'durable=True' as required.

* 'savepoint=True' is used in special cases.
2024-11-01 16:41:15 -07:00
Aditya Kumar Kasaudhan 18a8125dac user_groups: Include group_id in success response on group creation.
Previously, the `group_id` was not returned in the success
response of the user group creation API.

This commit updates the API to return a success response
containing the unique ID of the user group with the key
`group_id`. This enhancement allows clients to easily reference
the newly created user group.

Fixes: #29686
2024-10-30 09:46:38 -07:00
Sahil Batra e5043b991a user_groups: Add API support to add subgroups during group creation.
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.
2024-10-17 14:27:21 -07:00
Sahil Batra 1e818c4708 user_groups: Allow updating subgroups and members using same endpoint.
`POST /user_groups/{user_group_id}/members` now allows updating
subgroups as well.
2024-10-17 14:27:21 -07:00
Sahil Batra 47a611f989 user_groups: Check permission when adding subgroups.
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.
2024-10-17 14:27:21 -07:00
Sahil Batra f24f1bfd14 user_groups: Refactor code to check permission for updating groups.
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.
2024-10-16 09:40:07 -07:00
Sahil Batra 3d65a8f78a user_groups: Fix permissions for joining the group.
We want to allow the user, who can add others to group, to
join the group as well irrespective of can_join_group setting.

Previously, the permission to add others (or say anyone) was
controlled by can_manage_group setting, but now it is controlled
by can_add_members_group setting. This commit fixes the code to
use can_add_members_group setting to check permission for joining
the group.

This commit also improves the tests for checking permission to
join the group such that different settings are tested in isolation.
2024-10-16 09:40:07 -07:00
Shubham Padia bf46747735 user_groups: Check can_leave_group when removing members. 2024-10-14 11:44:27 -07:00
Shubham Padia 060156fca4 user_groups: Add can_leave_group setting for user group.
This field will be used to control permission for who can
leave a user group.
2024-10-14 11:44:27 -07:00
Shubham Padia f134662312 user_groups: Check can_add_members_group before adding members.
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`.
2024-10-11 16:31:18 -07:00
Shubham Padia b305ca14dd user_groups: Add add_can_members_group to user group.
The default value for this field that we wanted to have was that group
itlself. But we are deferring that to later in order to reach the point
of switching over to the groups system sooner. Till then, we will use
`group_creator` as the default. See
https://chat.zulip.org/#narrow/stream/101-design/topic/Group.20add.20members.20dropdown/near/1952904
for more details.

For migration plan details, see
https://chat.zulip.org/#narrow/stream/101-design/topic/Group.20add.20members.20dropdown/near/1952902

The increase in query count from 7 to 9 in the query count test for
creating a user group is because of group_creator being the default for
the new field.
2024-10-11 16:31:18 -07:00
Sahil Batra 4784c71bf9 user_groups: Do not allow updating memberships of deactivated users.
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.
2024-10-10 11:37:44 -07:00
Sahil Batra 6d0d1a0700 user_groups: Check can_join_group setting when user tries to join.
Fixes part of #25938.
2024-10-08 12:18:13 -07:00
Sahil Batra e1d7f57da7 user_groups: Add can_join_group setting for user group.
This field will be used to control permission for who can
join a user group.

Fixes part of #25938.
2024-10-08 12:18:13 -07:00
Sahil Batra c1973d2263 user_groups: Add access_user_group_to_read_membership.
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.
2024-10-01 09:36:01 -07:00
Sahil Batra 0c89621fa6 user_groups: Refactor code to check permissions.
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.
2024-09-30 18:42:14 -07:00
Sahil Batra 5f3a8334be user_groups: Do not allow deleting user groups. 2024-09-18 13:41:13 -07:00
Sahil Batra 5c790aac72 user_groups: Rename allow_deactivated in 'GET /user_groups'.
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.
2024-09-18 13:41:13 -07:00
Tim Abbott 2585d209c0 user_groups: Rename misleadingly named view function. 2024-09-11 09:43:56 -07:00
Sahil Batra 688c5ad0af groups: Allow excluding deactivated groups in 'GET /user_groups' response. 2024-09-11 09:43:56 -07:00
Sahil Batra c1d6da0a5c user_groups: Update handling of deactivated groups.
We only allow updating name of a deactivated group, and not
allow updating description, members, subgroups and any setting
of a deactivated user group.

Deactivated user groups cannot be a a subgroup of any group
or used as a setting for a group.
2024-09-11 09:43:56 -07:00
Sahil Batra e1cfe61452 user_groups: Add API support for deactivating user groups. 2024-09-11 09:43:56 -07:00
Ujjawal Modi 5d613ce98d user_groups: Add support to update can_manage_group setting.
This commit adds API support to update can_manage_group setting
of a user group.
2024-08-20 09:28:05 -07:00
Ujjawal Modi b0b36e884c user_groups: Add support to set can_manage_group during creation.
This commit adds API support to set can_manage_group while
creating a user group.
2024-08-20 09:28:05 -07:00
Ujjawal Modi 423d5c42f6 user_groups: Update code to check whether user can edit a user group.
Earlier there was only a realm level setting for configuring
who can edit user groups. A new group level setting is also added
for configuring who can manage that particular group.
Now, a user group can be edited by a user if it is allowed from
realm level setting or group level setting.

This commit make changes to also use group level setting
in determining whether a group can be edited by user or not.

Also, updated tests to use api_post and api_delete helpers instead
of using client_post and client_delete helpers with different users
being logged in.
2024-08-20 09:28:05 -07:00
Ujjawal Modi bb0b6900df user_groups: Add a decorator to check group creation permission.
Earlier there was a single decorator function to check whether
user can create and edit user groups. This commit adds a new
decorator function to check whether user has permissions to
create user groups.

This was done because in future commits we will be adding a
realm level setting for configuring who can create user groups.
2024-08-20 09:28:05 -07:00
Prakhar Pratyush bae6188d92 user_groups: Add transaction.atomic decorator to add_user_group view.
The database operations in 'access_user_group_for_setting' and
'check_add_user_group' used in 'add_user_group' view should be
collectively atomic.

This commit adds transaction.atomic decorator for that purpose.
2024-08-12 12:16:14 -07:00
Prakhar Pratyush 66ff646e99 user_groups: Update edit_user_group codepath to send event on commit.
Earlier, we were using 'send_event' in 'edit_user_group' codepath
which can lead to a situation where we enqueue events but the
function fails at a later stage.

Events should not be sent until we know we're not rolling back.

Fixes part of #30489.
2024-08-12 12:16:14 -07:00
bedo 1ab4723d59 user_groups: Migrate to @typed_endpoint.
Migrate the following endpoints from @has_request_variables
to @typed_endpoint:

- get_user_group()
- delete_user_group()
- update_user_group_backend()
- update_subgroups_of_user_group()
- get_is_user_group_member()
- get_user_group_members()
- get_subgroups_of_user_group()

With tweaks from tabbott to avoid calling thunks unnecessarily.
2024-08-01 09:56:06 -07:00
Anders Kaseorg 0fa5e7f629 ruff: Fix UP035 Import from `collections.abc`, `typing` instead.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg 531b34cb4c ruff: Fix UP007 Use `X | Y` for type annotations.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Anders Kaseorg e08a24e47f ruff: Fix UP006 Use `list` instead of `List` for type annotation.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2024-07-13 22:28:22 -07:00
Vector73 6aa3a55796 openapi: Reorder group-setting-value oneOf clause. 2024-06-25 15:37:31 -07:00
Sahil Batra d3ea6520dc user_groups: Add server level setting disallow anonymous groups for settings.
This commit adds a server level setting which controls whether the setting
can be set to anonymous user groups. We only allow it in the tests for
now because the UI can only handle named user groups.
2024-06-03 09:45:26 -07:00
Sahil Batra 81765a1e83 user_groups: Fix audit log data when changing group settings.
This commit fixes the code store correct old value in audit
log data when changing can_mention_group setting from a
anonymous group to another anonymous group. The bug was
because the old value was being computed after updating
the UserGroup object with new members and subgroups and
is fixed by computing the old value for all the cases
and passing it to do_change_user_group_permission_setting.
2024-05-28 07:24:07 -07:00
Sahil Batra 7db7b3f94d groups: Move functions for updating settings to "lib.user_groups".
This commit moves validate_group_setting_value_change,
are_both_setting_values_equal and parse_group_setting_value
functions, which are used for updating the group settings, to
"zerver.lib.user_groups" as these functions will also be used for
group based realm and stream settings and "zerver.lib.user_groups"
file seems a better place to place such functions which are used
at multiple places.

For same reasons, we also move GroupSettingChangeRequest dataclass
to "zerver.lib.user_groups" file.
2024-05-16 12:58:20 -07:00
Sahil Batra 8bca565218 groups: Pass old setting value for can_mention_group.
This commit adds support to pass object containing both old and new
values of the can_mention_group setting, as well as detailed API
documentation for this part of the API system.

Co-authored-by: Tim Abbott <tabbott@zulip.com>
Co-authored-by: Greg PRice <greg@zulip.com>
2024-05-14 12:17:15 -07:00
Sahil Batra 0cc2244aac groups: Migrate group creation and edit endpoints to typed_endpoint. 2024-05-14 12:17:15 -07:00
Sahil Batra 3f80bc1b41 groups: Allow setting anonymous group to settings while editing.
This commit adds support to set can_mention_group setting to
anonymous group while editing groups.
2024-05-08 18:20:14 -07:00
Sahil Batra 23fdb73353 groups: Allow setting anonymous group to settings while creation.
This commit adds support to set can_mention_group setting to
anonymous group while group creation.
2024-05-08 18:20:14 -07:00
Sahil Batra 8e9c22afdc groups: Move constants inside NamedUserGroup. 2024-04-26 17:03:09 -07:00
Sahil Batra b60d5b6fc9 user_groups: Update code in actions module to use NamedUserGroup. 2024-04-26 17:03:09 -07:00
Anders Kaseorg 45bb8d2580 models: Extract zerver.models.users.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2023-12-16 22:08:44 -08:00
Sahil Batra 2c43c2a4db user_groups: Pass config object to access_user_group_for_setting.
We now pass the complete configuration object for a setting to
access_user_group_for_setting instead of passing the configuration
object's fields as different variables.
2023-11-01 10:42:56 -07:00
Tim Abbott ef5fee4778 user_groups: Improve bulk membership change logic.
Adds support for bulk-adjusting a single user's membership in multiple
user groups in a single transaction in the low-level actions
functions, for future use by work on #9957.
2023-09-29 15:08:02 +02:00
Tim Abbott 6c83bbcbdb settings: Disallow everyone group for new setting.
This is important because the "guests" value isn't one that we'd
expect anyone to pick intentionally, and in particular isn't an
available option for the similar/adjacent "email invitations" setting.
2023-09-07 14:21:01 -07:00
Ujjawal Modi 9eccb4336e types: Add id_field_name field to GroupPermissionSetting type.
This commit adds id_field_name field to GroupPermissionSetting
type which will be used to store the string formed by concatenation
of setting_name and `_id`.
2023-09-07 14:21:01 -07:00
Zixuan James Li a081428ad2 user_groups: Make locks required for updating user group memberships.
**Background**

User groups are expected to comply with the DAG constraint for the
many-to-many inter-group membership. The check for this constraint has
to be performed recursively so that we can find all direct and indirect
subgroups of the user group to be added.

This kind of check is vulnerable to phantom reads which is possible at
the default read committed isolation level because we cannot guarantee
that the check is still valid when we are adding the subgroups to the
user group.

**Solution**

To avoid having another transaction concurrently update one of the
to-be-subgroup after the recursive check is done, and before the subgroup
is added, we use SELECT FOR UPDATE to lock the user group rows.

The lock needs to be acquired before a group membership change is about
to occur before any check has been conducted.

Suppose that we are adding subgroup B to supergroup A, the locking protocol
is specified as follows:

1. Acquire a lock for B and all its direct and indirect subgroups.
2. Acquire a lock for A.

For the removal of user groups, we acquire a lock for the user group to
be removed with all its direct and indirect subgroups. This is the special
case A=B, which is still complaint with the protocol.

**Error handling**

We currently rely on Postgres' deadlock detection to abort transactions
and show an error for the users. In the future, we might need some
recovery mechanism or at least better error handling.

**Notes**

An important note is that we need to reuse the recursive CTE query that
finds the direct and indirect subgroups when applying the lock on the
rows. And the lock needs to be acquired the same way for the addition and
removal of direct subgroups.

User membership change (as opposed to user group membership) is not
affected. Read-only queries aren't either. The locks only protect
critical regions where the user group dependency graph might violate
the DAG constraint, where users are not participating.

**Testing**

We implement a transaction test case targeting some typical scenarios
when an internal server error is expected to happen (this means that the
user group view makes the correct decision to abort the transaction when
something goes wrong with locks).

To achieve this, we add a development view intended only for unit tests.
It has a global BARRIER that can be shared across threads, so that we
can synchronize them to consistently reproduce certain potential race
conditions prevented by the database locks.

The transaction test case lanuches pairs of threads initiating possibly
conflicting requests at the same time. The tests are set up such that exactly N
of them are expected to succeed with a certain error message (while we don't
know each one).

**Security notes**

get_recursive_subgroups_for_groups will no longer fetch user groups from
other realms. As a result, trying to add/remove a subgroup from another
realm results in a UserGroup not found error response.

We also implement subgroup-specific checks in has_user_group_access to
keep permission managing in a single place. Do note that the API
currently don't have a way to violate that check because we are only
checking the realm ID now.
2023-08-24 17:21:08 -07:00