fix: align group management APIs
This commit is contained in:
@@ -24,6 +24,7 @@ const (
|
||||
adminCommandGroupMemberUnmute = "group.member.unmute"
|
||||
adminCommandGroupMemberRemove = "group.member.remove"
|
||||
adminCommandGroupOwnerTransfer = "group.owner.transfer"
|
||||
adminCommandGroupDissolve = "group.dissolve"
|
||||
adminCommandUserBan = "user.ban"
|
||||
adminCommandUserUnban = "user.unban"
|
||||
adminCommandUserFreeze = "user.freeze"
|
||||
@@ -75,6 +76,8 @@ type groupGovernancePatch struct {
|
||||
MemberUploadFiles *bool `json:"member_upload_files"`
|
||||
MemberPrivateChat *bool `json:"member_private_chat"`
|
||||
MemberInvite *bool `json:"member_invite"`
|
||||
MaxMemberCount *int `json:"max_member_count"`
|
||||
MaxAdminCount *int `json:"max_admin_count"`
|
||||
}
|
||||
|
||||
type adminCommandResultPayload struct {
|
||||
@@ -221,7 +224,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.settings.updated",
|
||||
map[string]any{"topic": topic, "version": settings.Version})
|
||||
return map[string]any{"topic": topic, "version": settings.Version, "updated_at": settings.UpdatedAt}, nil
|
||||
|
||||
case adminCommandGroupGovernUpdate:
|
||||
@@ -231,12 +235,15 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
MemberUploadFiles: payload.Governance.MemberUploadFiles,
|
||||
MemberPrivateChat: payload.Governance.MemberPrivateChat,
|
||||
MemberInvite: payload.Governance.MemberInvite,
|
||||
MaxMemberCount: payload.Governance.MaxMemberCount,
|
||||
MaxAdminCount: payload.Governance.MaxAdminCount,
|
||||
Version: payload.Version,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.settings.updated",
|
||||
map[string]any{"topic": topic, "version": settings.Version})
|
||||
return map[string]any{"topic": topic, "version": settings.Version, "updated_at": settings.UpdatedAt}, nil
|
||||
|
||||
case adminCommandGroupAdminSet:
|
||||
@@ -259,7 +266,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
}
|
||||
succeeded = append(succeeded, map[string]any{"user_id": internalAdminUIDRaw(target), "role": types.GroupMemberRoleAdmin})
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.role.updated",
|
||||
map[string]any{"topic": topic, "succeeded": succeeded})
|
||||
return map[string]any{"topic": topic, "succeeded": succeeded}, nil
|
||||
|
||||
case adminCommandGroupAdminRemove:
|
||||
@@ -271,7 +279,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
types.GroupMemberRoleMember, types.ModeCPublic, now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.role.updated",
|
||||
map[string]any{"user_id": internalAdminUIDRaw(target), "role": types.GroupMemberRoleMember})
|
||||
return map[string]any{"topic": topic, "user_id": internalAdminUIDRaw(target), "role": types.GroupMemberRoleMember}, nil
|
||||
|
||||
case adminCommandGroupMemberMute:
|
||||
@@ -291,7 +300,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.mute.updated",
|
||||
map[string]any{"user_id": internalAdminUIDRaw(target), "muted": true, "version": mute.Version})
|
||||
return map[string]any{"topic": topic, "user_id": internalAdminUIDRaw(target), "muted": true, "version": mute.Version}, nil
|
||||
|
||||
case adminCommandGroupMemberUnmute:
|
||||
@@ -302,7 +312,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
if err := store.GroupBusiness.DeleteMute(tenantID, topic, target, actor, now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.mute.updated",
|
||||
map[string]any{"user_id": internalAdminUIDRaw(target), "muted": false})
|
||||
return map[string]any{"topic": topic, "user_id": internalAdminUIDRaw(target), "muted": false}, nil
|
||||
|
||||
case adminCommandGroupMemberRemove:
|
||||
@@ -313,7 +324,8 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
if err := store.GroupBusiness.Leave(tenantID, topic, target, now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.member.left",
|
||||
map[string]any{"user_id": internalAdminUIDRaw(target)})
|
||||
return map[string]any{"topic": topic, "user_id": internalAdminUIDRaw(target), "status": "left"}, nil
|
||||
|
||||
case adminCommandGroupOwnerTransfer:
|
||||
@@ -324,12 +336,32 @@ func executeKafkaAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, p
|
||||
if err := store.GroupBusiness.TransferOwner(tenantID, topic, actor, target, payload.Version, now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dispatchIMGroupEvents(tenantID)
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.owner.transferred",
|
||||
map[string]any{"owner": internalAdminUIDRaw(target), "previous_owner": internalAdminUIDRaw(actor)})
|
||||
return map[string]any{"topic": topic, "owner": internalAdminUIDRaw(target), "previous_owner": internalAdminUIDRaw(actor)}, nil
|
||||
|
||||
case adminCommandGroupDissolve:
|
||||
if err := dissolveGroupByAdminCommand(tenantID, topic, actor, strings.TrimSpace(payload.Reason), now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
publishIMGroupRealtimeEvent(tenantID, topic, actor, "group.dissolved",
|
||||
map[string]any{"topic": topic, "reason": strings.TrimSpace(payload.Reason)})
|
||||
return map[string]any{"topic": topic, "status": "dissolved"}, nil
|
||||
}
|
||||
return nil, errors.New("unsupported admin command: " + envelope.EventType)
|
||||
}
|
||||
|
||||
func dissolveGroupByAdminCommand(tenantID types.TenantID, topic string, actor types.Uid, reason string, now time.Time) error {
|
||||
if strings.TrimSpace(topic) == "" || actor.IsZero() {
|
||||
return types.ErrMalformed
|
||||
}
|
||||
if store.GroupBusiness == nil {
|
||||
return errors.New("group business store is not initialized")
|
||||
}
|
||||
_, err := store.GroupBusiness.Dissolve(tenantID, topic, actor, reason, now)
|
||||
return err
|
||||
}
|
||||
|
||||
func executeKafkaMessageAdminCommand(tenantID types.TenantID, envelope kafkaEnvelope, payload adminCommandPayload) (map[string]any, error) {
|
||||
conversationType := strings.TrimSpace(payload.ConversationType)
|
||||
topic := strings.TrimSpace(payload.Topic)
|
||||
@@ -386,7 +418,7 @@ func executeKafkaUserGovernanceCommand(tenantID types.TenantID, envelope kafkaEn
|
||||
if err := store.Users.UpdateState(tenantID, target, types.StateSuspended); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
evictUserSessions(target)
|
||||
evictUserSessions(tenantID, target)
|
||||
notifyUserStateChanged(tenantID, target, types.StateSuspended)
|
||||
result["state"] = types.StateSuspended.String()
|
||||
result["evicted"] = true
|
||||
@@ -407,6 +439,7 @@ func executeKafkaUserGovernanceCommand(tenantID types.TenantID, envelope kafkaEn
|
||||
if globals.sessionStore != nil {
|
||||
evicted = globals.sessionStore.EvictUserDevice(target, deviceID)
|
||||
}
|
||||
publishRealtimeEvictDevice(tenantID, target, deviceID, "admin_device_kick")
|
||||
if store.Devices != nil {
|
||||
if err := store.Devices.Delete(tenantID, target, deviceID); err != nil && !errors.Is(err, types.ErrNotFound) {
|
||||
return nil, err
|
||||
@@ -416,7 +449,7 @@ func executeKafkaUserGovernanceCommand(tenantID types.TenantID, envelope kafkaEn
|
||||
result["evicted_sessions"] = evicted
|
||||
return result, nil
|
||||
case adminCommandUserLogoutAll:
|
||||
evictUserSessions(target)
|
||||
evictUserSessions(tenantID, target)
|
||||
result["evicted"] = true
|
||||
return result, nil
|
||||
case adminCommandUserCancel, adminCommandUserDelete:
|
||||
@@ -456,7 +489,7 @@ func executeKafkaUserPasswordResetCommand(tenantID types.TenantID, payload admin
|
||||
}
|
||||
authVersion = version
|
||||
}
|
||||
evictUserSessions(target)
|
||||
evictUserSessions(tenantID, target)
|
||||
return map[string]any{
|
||||
"user_id": internalAdminUIDRaw(target),
|
||||
"action": adminCommandUserPasswordReset,
|
||||
@@ -465,10 +498,11 @@ func executeKafkaUserPasswordResetCommand(tenantID types.TenantID, payload admin
|
||||
}, nil
|
||||
}
|
||||
|
||||
func evictUserSessions(uid types.Uid) {
|
||||
func evictUserSessions(tenantID types.TenantID, uid types.Uid) {
|
||||
if globals.sessionStore != nil {
|
||||
globals.sessionStore.EvictUser(uid, "")
|
||||
}
|
||||
publishRealtimeEvictUser(tenantID, uid, "admin_user_evict", "")
|
||||
}
|
||||
|
||||
func notifyUserStateChanged(tenantID types.TenantID, uid types.Uid, state types.ObjState) {
|
||||
@@ -479,7 +513,7 @@ func notifyUserStateChanged(tenantID types.TenantID, uid types.Uid, state types.
|
||||
}
|
||||
|
||||
func deleteUserByAdminCommand(tenantID types.TenantID, uid types.Uid, hard bool, _ time.Time) error {
|
||||
evictUserSessions(uid)
|
||||
evictUserSessions(tenantID, uid)
|
||||
usersRemoveUser(tenantID, uid)
|
||||
if globals.hub != nil && globals.hub.unreg != nil {
|
||||
done := make(chan bool)
|
||||
|
||||
Reference in New Issue
Block a user