fix: keep DM participant rows when a user leaves the chat group
The participant sync and the non-member prune now remove only ogólny's rows. A user taken out of studenci, even briefly, keeps their DMs (the live membership check denies access while they are out) and gets them back when re-added, instead of losing them for good.
This commit is contained in:
@@ -34,9 +34,12 @@ JOIN user_groups ON user_groups.id = users_groups.user_group_id
|
||||
JOIN users ON users.id = users_groups.user_id
|
||||
WHERE user_groups.code = ? AND users.deleted_at IS NULL`
|
||||
|
||||
// chatConversationsSQL selects the ids of the conversations of context
|
||||
// bm/1 (ogólny and every DM).
|
||||
const chatConversationsSQL = `SELECT id FROM golem15_chat_conversations WHERE context_type = ? AND context_id = ?`
|
||||
// chatGroupConversationsSQL selects the ids of the group conversations of
|
||||
// context bm/1 (ogólny). DMs are never listed: their participant rows are
|
||||
// kept when someone leaves the chat group, so the history comes back when
|
||||
// they are re-added. Access while they are out is denied by golem15.chat's
|
||||
// live membership check (ChatContext.RequireLiveMembership).
|
||||
const chatGroupConversationsSQL = `SELECT id FROM golem15_chat_conversations WHERE context_type = ? AND context_id = ? AND type = ?`
|
||||
|
||||
// EnsureChatGroups creates a user group for each code that has none and
|
||||
// returns how many it created. It never assigns a user to a group: members
|
||||
@@ -120,12 +123,12 @@ func FindGeneral(ctx context.Context, db *gorm.DB) (*chatmodels.Conversation, er
|
||||
return &conv, nil
|
||||
}
|
||||
|
||||
// SyncChatParticipants makes the chat's participants follow the chat
|
||||
// group, in one transaction: every member missing from ogólny (generalID)
|
||||
// joins it, and users no longer in the group lose their participant rows
|
||||
// in every conversation of context bm/1. Nothing is pruned while no group
|
||||
// with that code exists, so a mistyped code cannot wipe the DMs. It returns
|
||||
// how many rows it added and removed.
|
||||
// SyncChatParticipants makes ogólny's participants follow the chat group,
|
||||
// in one transaction: every member missing from ogólny (generalID) joins
|
||||
// it, and users no longer in the group leave it. DM participant rows are
|
||||
// kept (a re-added user gets their DMs back; until then golem15.chat's
|
||||
// live membership check denies access). Nothing is pruned while no group
|
||||
// with that code exists. It returns how many rows it added and removed.
|
||||
func SyncChatParticipants(ctx context.Context, db *gorm.DB, generalID uint, group string) (int64, int64, error) {
|
||||
if db == nil {
|
||||
return 0, 0, errors.New("jz.bm: chat sync needs a database")
|
||||
@@ -145,9 +148,9 @@ ON CONFLICT (conversation_id, user_id) DO NOTHING`, generalID, group)
|
||||
added = res.RowsAffected
|
||||
}
|
||||
res := tx.Exec(`DELETE FROM golem15_chat_participants
|
||||
WHERE conversation_id IN (`+chatConversationsSQL+`)
|
||||
WHERE conversation_id IN (`+chatGroupConversationsSQL+`)
|
||||
AND user_id NOT IN (`+chatMembersSQL+`)
|
||||
AND EXISTS (SELECT 1 FROM user_groups WHERE code = ?)`, ChatContextType, ChatContextID, group, group)
|
||||
AND EXISTS (SELECT 1 FROM user_groups WHERE code = ?)`, ChatContextType, ChatContextID, chatmodels.TypeGroup, group, group)
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
}
|
||||
@@ -157,14 +160,16 @@ WHERE conversation_id IN (`+chatConversationsSQL+`)
|
||||
return added, removed, err
|
||||
}
|
||||
|
||||
// PruneChatParticipant removes userID from every conversation of context
|
||||
// bm/1. It runs when someone outside the chat group asks for the chat.
|
||||
// PruneChatParticipant removes userID from ogólny (the group
|
||||
// conversations of context bm/1); their DM rows are kept, as in
|
||||
// SyncChatParticipants. It runs when someone outside the chat group asks
|
||||
// for the chat.
|
||||
func PruneChatParticipant(ctx context.Context, db *gorm.DB, userID uint) error {
|
||||
if db == nil {
|
||||
return errors.New("jz.bm: chat prune needs a database")
|
||||
}
|
||||
return db.WithContext(ctx).Exec(`DELETE FROM golem15_chat_participants
|
||||
WHERE user_id = ? AND conversation_id IN (`+chatConversationsSQL+`)`, userID, ChatContextType, ChatContextID).Error
|
||||
WHERE user_id = ? AND conversation_id IN (`+chatGroupConversationsSQL+`)`, userID, ChatContextType, ChatContextID, chatmodels.TypeGroup).Error
|
||||
}
|
||||
|
||||
// AssignMissingHandles gives every chat-group member without a handle one
|
||||
|
||||
Reference in New Issue
Block a user