fix: group moderation and profile sync

This commit is contained in:
richjohnrambo
2026-10-17 10:12:20 +08:00
parent ea29fef40f
commit 9132207e21
9 changed files with 126 additions and 19 deletions
+26 -4
View File
@@ -2628,15 +2628,22 @@ func (groupBusinessMapper) TransferOwner(tenantID types.TenantID, topic string,
return nil
}
func (groupBusinessMapper) CanPost(tenantID types.TenantID, topic string, uid types.Uid, admin bool, now time.Time) (bool, error) {
func (groupBusinessMapper) CanPost(tenantID types.TenantID, topic string, uid types.Uid, _ bool, now time.Time) (bool, error) {
if strings.TrimSpace(topic) == "" || uid.IsZero() || now.IsZero() {
return false, types.ErrMalformed
}
if admin {
return true, nil
}
topic = strings.TrimSpace(topic)
mapper := groupBusinessMapper{}
member, err := mapper.GetMember(tenantID, topic, uid)
if errors.Is(err, types.ErrNotFound) {
return false, nil
}
if err != nil {
return false, err
}
if allowed, checkMute := groupMemberPostRole(member); !checkMute {
return allowed, nil
}
settings, err := mapper.GetSettings(tenantID, topic)
if err != nil && !errors.Is(err, types.ErrNotFound) {
return false, err
@@ -2655,6 +2662,21 @@ func (groupBusinessMapper) CanPost(tenantID types.TenantID, topic string, uid ty
(mute.ExpiresAt != nil && !mute.ExpiresAt.After(now)), nil
}
func groupMemberPostRole(member *types.GroupMember) (allowed, checkMute bool) {
if member == nil || member.MemberStatus != types.GroupMemberStatusActive {
return false, false
}
// The loaded Topic access snapshot can lag behind a role change.
switch member.Role {
case types.GroupMemberRoleOwner, types.GroupMemberRoleAdmin:
return true, false
case types.GroupMemberRoleMember:
return false, true
default:
return false, false
}
}
type groupMuteCacheValue struct {
Found bool `json:"found"`
Mute *types.GroupMute `json:"mute,omitempty"`
+24
View File
@@ -15,6 +15,30 @@ func TestForTenantRejectsZero(t *testing.T) {
}
}
func TestGroupMemberPostRoleUsesCurrentBusinessRole(t *testing.T) {
tests := []struct {
name string
member *types.GroupMember
allowed bool
checkMute bool
}{
{name: "missing member"},
{name: "ordinary member", member: &types.GroupMember{Role: types.GroupMemberRoleMember, MemberStatus: types.GroupMemberStatusActive}, checkMute: true},
{name: "administrator", member: &types.GroupMember{Role: types.GroupMemberRoleAdmin, MemberStatus: types.GroupMemberStatusActive}, allowed: true},
{name: "owner", member: &types.GroupMember{Role: types.GroupMemberRoleOwner, MemberStatus: types.GroupMemberStatusActive}, allowed: true},
{name: "departed administrator", member: &types.GroupMember{Role: types.GroupMemberRoleAdmin, MemberStatus: types.GroupMemberStatusLeft}},
{name: "unknown role", member: &types.GroupMember{Role: "unknown", MemberStatus: types.GroupMemberStatusActive}},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
allowed, checkMute := groupMemberPostRole(test.member)
if allowed != test.allowed || checkMute != test.checkMute {
t.Fatalf("got allowed=%t checkMute=%t, want allowed=%t checkMute=%t", allowed, checkMute, test.allowed, test.checkMute)
}
})
}
}
func TestValidateMessageHeadersProductContract(t *testing.T) {
valid := []types.KVMap{
{"x-im-schema": float64(1), "x-im-type": "text"},