From 2b3f417b242c121627d001b6b7370c13b56a4e9f Mon Sep 17 00:00:00 2001 From: Astra Date: Tue, 15 Sep 2026 12:11:04 +0100 Subject: [PATCH] channels: clear stale banned rights when promoting a member to admin EditChannelAdmin reactivates a previously kicked/banned member to Active status but left BannedRights.ViewMessages set from the old ban, an Active+banned-from-viewing state nothing else in the codebase expects. TransferChannelOwnership's participant check trips on it and rejects the transfer with PARTICIPANT_MISSING, even though the target is now a visibly active admin. --- internal/store/memory/channel_members.go | 5 +++++ internal/store/postgres/channel_member_admin.go | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/internal/store/memory/channel_members.go b/internal/store/memory/channel_members.go index d003deff..6d6ba93f 100644 --- a/internal/store/memory/channel_members.go +++ b/internal/store/memory/channel_members.go @@ -347,6 +347,11 @@ func (s *ChannelStore) EditChannelAdmin(_ context.Context, req domain.EditChanne member.InviterUserID = req.UserID member.Status = domain.ChannelMemberActive member.LeftAt = 0 + // See the postgres EditChannelAdmin implementation for why this is + // needed: a kicked/banned member carries BannedRights.ViewMessages=true, + // and editAdmin unconditionally reactivates them to Active, so any + // lingering ban must be lifted too. + member.BannedRights = domain.ChannelBannedRights{} if previous.Status != domain.ChannelMemberActive { if minPts := channelInitialAvailableMinPts(channel); minPts > member.AvailableMinPts { member.AvailableMinPts = minPts diff --git a/internal/store/postgres/channel_member_admin.go b/internal/store/postgres/channel_member_admin.go index e82efaf6..f401afcc 100644 --- a/internal/store/postgres/channel_member_admin.go +++ b/internal/store/postgres/channel_member_admin.go @@ -100,6 +100,13 @@ func (s *ChannelStore) EditChannelAdmin(ctx context.Context, req domain.EditChan member.InviterUserID = req.UserID member.Status = domain.ChannelMemberActive member.LeftAt = 0 + // A kicked/banned member carries BannedRights.ViewMessages=true (see + // EditChannelBanned above); editAdmin unconditionally reactivates them + // to Active, so any lingering ban must be lifted too -- otherwise the + // contradictory Active+ViewMessages-banned state trips later checks + // (e.g. TransferChannelOwnership's participant check) that never + // expect an active member to be ban-restricted from viewing messages. + member.BannedRights = domain.ChannelBannedRights{} if req.HasRank() { member.Rank = req.Rank }