diff --git a/pkg/controller/forum/forum.go b/pkg/controller/forum/forum.go index d939f92..d3be6cb 100644 --- a/pkg/controller/forum/forum.go +++ b/pkg/controller/forum/forum.go @@ -37,7 +37,7 @@ func Forum() http.HandlerFunc { } // Is it a private forum? - if forum.Private && !currentUser.IsAdmin { + if !forum.CanBeSeenBy(currentUser) { templates.NotFoundPage(w, r) return } diff --git a/pkg/controller/forum/forums.go b/pkg/controller/forum/forums.go index 9d80ec1..8972fc7 100644 --- a/pkg/controller/forum/forums.go +++ b/pkg/controller/forum/forums.go @@ -51,17 +51,19 @@ func Landing() http.HandlerFunc { categorized := models.CategorizeForums(forums, config.ForumCategories) // Inject the "My List" Category if the user subscribes to forums. - myList, err := models.PaginateForums(currentUser, nil, nil, true, pager) - if err != nil { - session.FlashError(w, r, "Couldn't get your followed forums: %s", err) - } else { - forums = append(forums, myList...) - categorized = append([]*models.CategorizedForum{ - { - Category: "My List", - Forums: myList, - }, - }, categorized...) + if config.UserForumsEnabled { + myList, err := models.PaginateForums(currentUser, nil, nil, true, pager) + if err != nil { + session.FlashError(w, r, "Couldn't get your followed forums: %s", err) + } else { + forums = append(forums, myList...) + categorized = append([]*models.CategorizedForum{ + { + Category: "My List", + Forums: myList, + }, + }, categorized...) + } } // Map statistics for these forums. diff --git a/pkg/controller/forum/thread.go b/pkg/controller/forum/thread.go index 74a24f1..3872c50 100644 --- a/pkg/controller/forum/thread.go +++ b/pkg/controller/forum/thread.go @@ -52,17 +52,14 @@ func Thread() http.HandlerFunc { } // Is it a private forum? - if forum.Private && !currentUser.IsAdmin { + if !forum.CanBeSeenBy(currentUser) { templates.NotFoundPage(w, r) return } // Can we moderate this forum? (from a user-owned forum perspective, // e.g. can we delete threads and posts, not edit them) - var canModerate bool - if currentUser.HasAdminScope(config.ScopeForumModerator) || forum.OwnerID == currentUser.ID { - canModerate = true - } + var canModerate = forum.CanBeModeratedBy(currentUser) // Ping the view count on this thread. if err := thread.View(currentUser.ID); err != nil { diff --git a/pkg/models/forum_membership.go b/pkg/models/forum_membership.go index 1eee49b..2201be1 100644 --- a/pkg/models/forum_membership.go +++ b/pkg/models/forum_membership.go @@ -5,6 +5,7 @@ import ( "strings" "time" + "code.nonshy.com/nonshy/website/pkg/config" "code.nonshy.com/nonshy/website/pkg/log" "gorm.io/gorm" ) @@ -79,6 +80,40 @@ func (f *Forum) AddModerator(user *User) (*ForumMembership, error) { return fm, err } +// CanBeSeenBy checks whether the user can see a private forum. +// +// Admins, owners, moderators and approved followers can see it. +// +// Note: this may invoke a DB query to check for moderator. +func (f *Forum) CanBeSeenBy(user *User) bool { + if !f.Private || user.IsAdmin || user.ID == f.OwnerID { + return true + } + + if fm, err := GetForumMembership(user, f); err == nil { + return fm.Approved || fm.IsModerator + } + + return false +} + +// CanBeModeratedBy checks whether the user can moderate this forum. +// +// Admins, owners and moderators can do so. +// +// Note: this may invoke a DB query to check for moderator. +func (f *Forum) CanBeModeratedBy(user *User) bool { + if user.HasAdminScope(config.ScopeForumModerator) || f.OwnerID == user.ID { + return true + } + + if fm, err := GetForumMembership(user, f); err == nil { + return fm.IsModerator + } + + return false +} + // RemoveModerator will unset a user's moderator flag on this forum. func (f *Forum) RemoveModerator(user *User) (*ForumMembership, error) { fm, err := GetForumMembership(user, f) diff --git a/web/templates/forum/add_edit.html b/web/templates/forum/add_edit.html index 35ec208..d222848 100644 --- a/web/templates/forum/add_edit.html +++ b/web/templates/forum/add_edit.html @@ -93,11 +93,18 @@