User-owned Forum Improvements
* Private forums: CanBeSeenBy moderators, approved followers, its owner and admin users. * Note: the endpoint to subscribe to the forum won't allow users to follow the private forum, so approved followers can not be created at this time, except by adding them as moderators. * Admins: when creating a forum they can choose "no category" to create it as an unofficial community forum. * Code cleanup * More feature flag checking
This commit is contained in:
parent
28d1e284ab
commit
8a321eb8d2
|
@ -37,7 +37,7 @@ func Forum() http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a private forum?
|
// Is it a private forum?
|
||||||
if forum.Private && !currentUser.IsAdmin {
|
if !forum.CanBeSeenBy(currentUser) {
|
||||||
templates.NotFoundPage(w, r)
|
templates.NotFoundPage(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ func Landing() http.HandlerFunc {
|
||||||
categorized := models.CategorizeForums(forums, config.ForumCategories)
|
categorized := models.CategorizeForums(forums, config.ForumCategories)
|
||||||
|
|
||||||
// Inject the "My List" Category if the user subscribes to forums.
|
// Inject the "My List" Category if the user subscribes to forums.
|
||||||
|
if config.UserForumsEnabled {
|
||||||
myList, err := models.PaginateForums(currentUser, nil, nil, true, pager)
|
myList, err := models.PaginateForums(currentUser, nil, nil, true, pager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.FlashError(w, r, "Couldn't get your followed forums: %s", err)
|
session.FlashError(w, r, "Couldn't get your followed forums: %s", err)
|
||||||
|
@ -63,6 +64,7 @@ func Landing() http.HandlerFunc {
|
||||||
},
|
},
|
||||||
}, categorized...)
|
}, categorized...)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Map statistics for these forums.
|
// Map statistics for these forums.
|
||||||
forumMap := models.MapForumStatistics(forums)
|
forumMap := models.MapForumStatistics(forums)
|
||||||
|
|
|
@ -52,17 +52,14 @@ func Thread() http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it a private forum?
|
// Is it a private forum?
|
||||||
if forum.Private && !currentUser.IsAdmin {
|
if !forum.CanBeSeenBy(currentUser) {
|
||||||
templates.NotFoundPage(w, r)
|
templates.NotFoundPage(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can we moderate this forum? (from a user-owned forum perspective,
|
// Can we moderate this forum? (from a user-owned forum perspective,
|
||||||
// e.g. can we delete threads and posts, not edit them)
|
// e.g. can we delete threads and posts, not edit them)
|
||||||
var canModerate bool
|
var canModerate = forum.CanBeModeratedBy(currentUser)
|
||||||
if currentUser.HasAdminScope(config.ScopeForumModerator) || forum.OwnerID == currentUser.ID {
|
|
||||||
canModerate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping the view count on this thread.
|
// Ping the view count on this thread.
|
||||||
if err := thread.View(currentUser.ID); err != nil {
|
if err := thread.View(currentUser.ID); err != nil {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.nonshy.com/nonshy/website/pkg/config"
|
||||||
"code.nonshy.com/nonshy/website/pkg/log"
|
"code.nonshy.com/nonshy/website/pkg/log"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
@ -79,6 +80,40 @@ func (f *Forum) AddModerator(user *User) (*ForumMembership, error) {
|
||||||
return fm, err
|
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.
|
// RemoveModerator will unset a user's moderator flag on this forum.
|
||||||
func (f *Forum) RemoveModerator(user *User) (*ForumMembership, error) {
|
func (f *Forum) RemoveModerator(user *User) (*ForumMembership, error) {
|
||||||
fm, err := GetForumMembership(user, f)
|
fm, err := GetForumMembership(user, f)
|
||||||
|
|
|
@ -93,11 +93,18 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="select is-fullwidth">
|
<div class="select is-fullwidth">
|
||||||
<select name="category" id="category">
|
<select name="category" id="category">
|
||||||
|
<optgroup label="Community Forum">
|
||||||
|
<option value=""{{if and $Root.EditForum (eq $Root.EditForum.Category "")}} selected{{end}}>
|
||||||
|
This will be a community forum (no category set)
|
||||||
|
</option>
|
||||||
|
</optgroup>
|
||||||
|
<optgroup label="Official Forums">
|
||||||
{{range .Categories}}
|
{{range .Categories}}
|
||||||
<option value="{{.}}"{{if and $Root.EditForum (eq $Root.EditForum.Category .)}} selected{{end}}>
|
<option value="{{.}}"{{if and $Root.EditForum (eq $Root.EditForum.Category .)}} selected{{end}}>
|
||||||
{{.}}
|
{{.}}
|
||||||
</option>
|
</option>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h1 class="title">{{.Title}}</h1>
|
<h1 class="title">{{.Title}}</h1>
|
||||||
<h2 class="subtitle">
|
<h2 class="subtitle">
|
||||||
/f/{{.Fragment}}
|
<a href="/f/{{.Fragment}}">/f/{{.Fragment}}</a>
|
||||||
{{if .Category}}<span class="ml-4">{{.Category}}</span>{{end}}
|
{{if .Category}}<span class="ml-4">{{.Category}}</span>{{end}}
|
||||||
<span class="ml-4">
|
<span class="ml-4">
|
||||||
by <strong><a href="/u/{{.Owner.Username}}">{{.Owner.Username}}</a></strong>
|
by <strong><a href="/u/{{.Owner.Username}}">{{.Owner.Username}}</a></strong>
|
||||||
|
|
|
@ -16,11 +16,13 @@ Variables that your template should set:
|
||||||
Categories
|
Categories
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{{if .FeatureUserForumsEnabled}}
|
||||||
<li {{if eq .CurrentForumTab "explore" }}class="is-active"{{end}}>
|
<li {{if eq .CurrentForumTab "explore" }}class="is-active"{{end}}>
|
||||||
<a href="/forum/explore">
|
<a href="/forum/explore">
|
||||||
Explore
|
Explore
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{{end}}
|
||||||
<li {{if eq .CurrentForumTab "newest" }}class="is-active"{{end}}>
|
<li {{if eq .CurrentForumTab "newest" }}class="is-active"{{end}}>
|
||||||
<a href="/forum/newest">
|
<a href="/forum/newest">
|
||||||
Newest
|
Newest
|
||||||
|
|
Loading…
Reference in New Issue
Block a user