diff --git a/classes/chat_sync.go b/classes/chat_sync.go index 8886aa2..6a3fd7d 100644 --- a/classes/chat_sync.go +++ b/classes/chat_sync.go @@ -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 diff --git a/console/chat_sync.go b/console/chat_sync.go index e9a946e..860fe87 100644 --- a/console/chat_sync.go +++ b/console/chat_sync.go @@ -49,7 +49,7 @@ func ChatSyncCommand(withDB func(ctx context.Context, fn func(*gorm.DB) error) e } else { out.Printf("ogólny participants added: %d\n", added) } - out.Printf("participant rows removed: %d\n", removed) + out.Printf("ogólny participants removed: %d\n", removed) out.Printf("handles assigned: %d\n", handles) out.Success(chatSyncName + ": chat group " + group + " synced") return nil