Skip to content

Conversation

blackheaven
Copy link
Contributor

@blackheaven blackheaven commented Sep 18, 2025

https://wearezeta.atlassian.net/browse/WPB-19712

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

WIP

  • Tests

@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Sep 18, 2025
@blackheaven blackheaven marked this pull request as ready for review September 19, 2025 16:49
@blackheaven blackheaven requested a review from a team as a code owner September 19, 2025 16:49
Copy link
Collaborator

@eyeinsky eyeinsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my comments, not all of them might be correct. Otherwise looks good and easy to read and understand.


type instance MapError 'UserGroupNotATeamAdmin = 'StaticError 403 "user-group-write-forbidden" "Only team admins can create, update, or delete user groups."

type instance MapError 'UserGroupChannelNotFound = 'StaticError 400 "user-group-channel-not-found" "Specified Channel does not exists or belongs to the team"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this could be a 404.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed, thanks.

lmap
(bimap toUUID (fmap toUUID))
$ [resultlessStatement|
delete from user_group_channel where user_group_id = ($1 :: uuid) and conv_id <> any($2 :: uuid[])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, testing on postgres console SELECT 1 <> ANY(ARRAY[1, 2, 3]); gives me true, so if an existing conversation is in the new set (part of the array) it would be deleted, but it's the other way around we want, don't we? (Unless I'm mistaken on what the logic should be.) Perhaps add this to the test to make sure.

Also, to my brain ... conv_id NOT IN (..new_conv_ids..) would be easier to read, rather than ... <> any(...) (but that may be just habit).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's also how my brain works... but not how hasql encoders work.

I guess it works because there is also an upsert operation following it.

I've tried something else.

);


ALTER TABLE public.user_group_member OWNER TO "wire-server";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this row need to be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped by mistake, thanks.

AddUser gid uid -> addUserImpl gid uid
UpdateUsers gid uids -> updateUsersImpl gid uids
RemoveUser gid uid -> removeUserImpl gid uid
UpdateUserGroupChannels _ gid convIds -> updateUserGroupChannelsImpl gid convIds
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove the TeamId field as it doesn't seem to be used (?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's used in the Mock interpreter (it's not a good idea though)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is not a good reason to have it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dropped, I was thinking of the subsystem.

AddUser gid uid -> addUserImpl gid uid
UpdateUsers gid uids -> updateUsersImpl gid uids
RemoveUser gid uid -> removeUserImpl gid uid
UpdateUserGroupChannels _ gid convIds -> updateUserGroupChannelsImpl gid convIds
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is not a good reason to have it here.

Comment on lines 423 to 427
session :: Session ()
session = do
statement (gid, convIds) deleteStatement
forM_ convIds $ \convId ->
statement (gid, convId) insertStatement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a transaction.
And maybe it is more efficient to add them with a single insert statement like in insertGroupMembersStatement? Not sure if it is better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aaaah, I have looked for it for so long, thanks, done.


type instance MapError 'UserGroupNotATeamAdmin = 'StaticError 403 "user-group-write-forbidden" "Only team admins can create, update, or delete user groups."

type instance MapError 'UserGroupChannelNotFound = 'StaticError 404 "user-group-channel-not-found" "Specified Channel does not exists or belongs to the team"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
type instance MapError 'UserGroupChannelNotFound = 'StaticError 404 "user-group-channel-not-found" "Specified Channel does not exists or belongs to the team"
type instance MapError 'UserGroupChannelNotFound = 'StaticError 404 "user-group-channel-not-found" "Specified Channel does not exists or does not belong to the team"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

applied (manually)

:<|> Named
"update-user-group-channels"
( Summary "[STUB] Update user group channels. Replaces the channels with the given list."
( Summary "Replaces the channels with the given list."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the possible errors here with CanThrow decorators.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines 377 to 394
testUserGroupUpdateChannels :: (HasCallStack) => App ()
testUserGroupUpdateChannels = do
(alice, tid, _) <- createTeam OwnDomain 1

ug <-
createUserGroup alice (object ["name" .= "none", "members" .= (mempty :: [String])])
>>= getJSON 200
gid <- ug %. "id" & asString

convId <-
postConversation alice (defProteus {team = Just tid})
>>= getJSON 201
>>= objConvId
updateUserGroupChannels alice gid [convId.id_] >>= assertSuccess

bindResponse (getUserGroup alice gid) $ \resp -> do
resp.status `shouldMatchInt` 200
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check that non-admins can't update
non existing user group return 404
check non existing (other team) conversations return error
check maybe also that an empty list removes all users
leave FUTUREWORK to check the actual assiciated channels, once the get feature is implemented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check maybe also that an empty list removes all users

I'm not sure how to do this: should we track why users have been added to a channel?

Done:

check that non-admins can't update
non existing user group return 404
check non existing (other team) conversations return error
leave FUTUREWORK to check the actual assiciated channels, once the get feature is implemented.

:<|> Named
"update-user-group-channels"
( Summary "[STUB] Update user group channels. Replaces the channels with the given list."
( Summary "Replaces the channels with the given list."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we double check that the payload contains a list of unqualified conv_ids is ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with someone specifically? because we changed back the RFC

updateChannels performer groupId channelIds = do
void $ getUserGroup performer groupId >>= note UserGroupNotFound
teamId <- getTeamAsAdmin performer >>= note UserGroupNotATeamAdmin
traverse_ (getTeamConv performer teamId >=> note UserGroupChannelNotFound) channelIds
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

@blackheaven blackheaven requested a review from battermann October 1, 2025 18:34
@blackheaven blackheaven force-pushed the gdifolco/WPB-19712_user-groups-update-endpoint branch from 4ed864c to 909912b Compare October 2, 2025 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants