diff --git a/server/im_http.go b/server/im_http.go index 5a8f7b1..9a37297 100644 --- a/server/im_http.go +++ b/server/im_http.go @@ -55,6 +55,7 @@ const ( imReasonFileUnavailable = "FILE_UNAVAILABLE" imReasonRateLimited = "RATE_LIMITED" imReasonResourceNotFound = "RESOURCE_NOT_FOUND" + imReasonGroupDissolved = "GROUP_DISSOLVED" imReasonValidationFailed = "VALIDATION_FAILED" ) @@ -4774,7 +4775,11 @@ func serveIMGroupList(wrt http.ResponseWriter, req *http.Request) { continue } item := groupListItemPayload(sub) - if settings, err := store.GroupBusiness.GetSettings(principal.TenantID, sub.Topic); err == nil { + if settings, err := store.GroupBusiness.GetSettings(principal.TenantID, sub.Topic); err == nil && settings != nil { + if settings.GroupStatus == types.GroupStatusDissolved { + // Defensive check: hide dissolved groups even if their subscription cleanup lagged. + continue + } item = mergeGroupListSettingsPayload(item, settings) } if category != "" && groupCategory(groupMemberRole(sub.ModeGiven&sub.ModeWant)) != category { @@ -5083,6 +5088,10 @@ func serveIMGroupDetail(wrt http.ResponseWriter, req *http.Request, topic string } payload := groupDetailPayload(group, selfSub) if settings, err := store.GroupBusiness.GetSettings(principal.TenantID, topic); err == nil { + if settings != nil && settings.GroupStatus == types.GroupStatusDissolved { + writeIMError(wrt, req, http.StatusGone, 30004, imReasonGroupDissolved, "group dissolved", map[string]any{"topic": topic}) + return + } payload = mergeGroupSettingsPayload(payload, settings) } writeIMSuccess(wrt, req, payload) diff --git a/server/store/types/groups.go b/server/store/types/groups.go index 7cd174c..b51c0e6 100644 --- a/server/store/types/groups.go +++ b/server/store/types/groups.go @@ -3,7 +3,8 @@ package types import "time" const ( - GroupStatusActive = "active" + GroupStatusActive = "active" + GroupStatusDissolved = "dissolved" GroupMemberRoleOwner = "owner" GroupMemberRoleAdmin = "admin"