forum: let non-members browse a public forum's topic list

ListForumTopics / GetForumTopicsByID / GeneralForumTopic gated on
membership while channel history uses the public-preview path, so a
public forum's topics (General included) were invisible until you joined.
Switch them to getChannelForViewer / channelForViewerLocked; private
forums and write paths keep the membership gate.
This commit is contained in:
Astra 2026-09-09 11:15:56 +01:00
parent 57b7829a9e
commit f0bf315bf3
5 changed files with 108 additions and 6 deletions

View file

@ -178,7 +178,7 @@ func (s *ChannelStore) GeneralForumTopic(_ context.Context, viewerUserID, channe
}
s.mu.RLock()
defer s.mu.RUnlock()
channel, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
channel, member, _, err := s.channelForViewerLocked(viewerUserID, channelID)
if err != nil {
return domain.ChannelForumTopic{}, err
}

View file

@ -420,7 +420,9 @@ func (s *ChannelStore) DeleteForumTopicHistory(_ context.Context, req domain.Del
func (s *ChannelStore) ListForumTopics(_ context.Context, viewerUserID int64, filter domain.ChannelForumTopicFilter) (domain.ChannelForumTopicList, error) {
s.mu.RLock()
defer s.mu.RUnlock()
channel, member, err := s.channelAndMemberLocked(viewerUserID, filter.ChannelID)
// channelForViewerLocked, not channelAndMemberLocked: a public forum's topic
// list is browsable before joining, exactly like its message history.
channel, member, _, err := s.channelForViewerLocked(viewerUserID, filter.ChannelID)
if err != nil {
return domain.ChannelForumTopicList{}, err
}
@ -463,7 +465,7 @@ func (s *ChannelStore) ListForumTopics(_ context.Context, viewerUserID int64, fi
func (s *ChannelStore) GetForumTopicsByID(_ context.Context, viewerUserID, channelID int64, ids []int) (domain.ChannelForumTopicList, error) {
s.mu.RLock()
defer s.mu.RUnlock()
channel, member, err := s.channelAndMemberLocked(viewerUserID, channelID)
channel, member, _, err := s.channelForViewerLocked(viewerUserID, channelID)
if err != nil {
return domain.ChannelForumTopicList{}, err
}

View file

@ -198,7 +198,7 @@ func (s *ChannelStore) GeneralForumTopic(ctx context.Context, viewerUserID, chan
if viewerUserID == 0 || channelID == 0 {
return domain.ChannelForumTopic{}, domain.ErrChannelInvalid
}
channel, member, err := s.getChannelForMember(ctx, s.db, viewerUserID, channelID)
channel, member, _, err := s.getChannelForViewer(ctx, s.db, viewerUserID, channelID)
if err != nil {
return domain.ChannelForumTopic{}, err
}

View file

@ -470,7 +470,9 @@ WHERE channel_id = $1 AND topic_id = $2`, req.ChannelID, req.TopicID); err != ni
}
func (s *ChannelStore) ListForumTopics(ctx context.Context, viewerUserID int64, filter domain.ChannelForumTopicFilter) (domain.ChannelForumTopicList, error) {
channel, member, err := s.getChannelForMember(ctx, s.db, viewerUserID, filter.ChannelID)
// getChannelForViewer, not getChannelForMember: a public forum's topic list is
// browsable before joining, exactly like its message history.
channel, member, _, err := s.getChannelForViewer(ctx, s.db, viewerUserID, filter.ChannelID)
if err != nil {
return domain.ChannelForumTopicList{}, err
}
@ -539,7 +541,7 @@ LIMIT $`+fmt.Sprint(len(args)), args...)
}
func (s *ChannelStore) GetForumTopicsByID(ctx context.Context, viewerUserID, channelID int64, ids []int) (domain.ChannelForumTopicList, error) {
channel, member, err := s.getChannelForMember(ctx, s.db, viewerUserID, channelID)
channel, member, _, err := s.getChannelForViewer(ctx, s.db, viewerUserID, channelID)
if err != nil {
return domain.ChannelForumTopicList{}, err
}