Notification when admin users are blocked
This commit is contained in:
parent
79ea384d40
commit
8d9588b039
|
@ -117,11 +117,17 @@ func UserActions() http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
// Get their block lists.
|
||||
insights, err := models.GetBlocklistInsights(user)
|
||||
if err != nil {
|
||||
session.FlashError(w, r, "Error getting blocklist insights: %s", err)
|
||||
}
|
||||
vars["BlocklistInsights"] = insights
|
||||
|
||||
// Also surface counts of admin blocks.
|
||||
count, total := models.CountBlockedAdminUsers(user)
|
||||
vars["AdminBlockCount"] = count
|
||||
vars["AdminBlockTotal"] = total
|
||||
case "essays":
|
||||
// Edit their profile essays easily.
|
||||
if !currentUser.HasAdminScope(config.ScopePhotoModerator) {
|
||||
|
|
|
@ -112,17 +112,35 @@ func BlockUser() http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
// Can't block admins who have the unblockable scope.
|
||||
if user.IsAdmin && user.HasAdminScope(config.ScopeUnblockable) {
|
||||
// If the target user is an admin, log this to the admin reports page.
|
||||
if user.IsAdmin {
|
||||
// Is the target admin user unblockable?
|
||||
var (
|
||||
unblockable = user.HasAdminScope(config.ScopeUnblockable)
|
||||
footer string // qualifier for the admin report body
|
||||
)
|
||||
|
||||
// Add a footer to the report to indicate whether the block goes through.
|
||||
if unblockable {
|
||||
footer = "**Unblockable:** this admin can not be blocked, so the block was not added and the user was shown an error message."
|
||||
} else {
|
||||
footer = "**Notice:** This admin is not unblockable, so the block has been added successfully."
|
||||
}
|
||||
|
||||
// Also, include this user's current count of blocked admin users.
|
||||
count, total := models.CountBlockedAdminUsers(currentUser)
|
||||
footer += fmt.Sprintf("\n\nThis user now blocks %d of %d admin user(s) on this site.", count+1, total)
|
||||
|
||||
// For curiosity's sake, log a report.
|
||||
fb := &models.Feedback{
|
||||
Intent: "report",
|
||||
Subject: "A user tried to block an admin",
|
||||
Message: fmt.Sprintf(
|
||||
"A user has tried to block an admin user account!\n\n"+
|
||||
"* Username: %s\n* Tried to block: %s",
|
||||
"* Username: %s\n* Tried to block: %s\n\n%s",
|
||||
currentUser.Username,
|
||||
user.Username,
|
||||
footer,
|
||||
),
|
||||
UserID: currentUser.ID,
|
||||
TableName: "users",
|
||||
|
@ -132,9 +150,12 @@ func BlockUser() http.HandlerFunc {
|
|||
log.Error("Could not log feedback for user %s trying to block admin %s: %s", currentUser.Username, user.Username, err)
|
||||
}
|
||||
|
||||
session.FlashError(w, r, "You can not block site administrators.")
|
||||
templates.Redirect(w, "/u/"+username)
|
||||
return
|
||||
// If the admin is unblockable, give the user an error message and return.
|
||||
if unblockable {
|
||||
session.FlashError(w, r, "You can not block site administrators.")
|
||||
templates.Redirect(w, "/u/"+username)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Block the target user.
|
||||
|
|
|
@ -199,6 +199,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
reverse = []*Block{} // Users who block the target
|
||||
userIDs = []uint64{user.ID}
|
||||
usernames = map[uint64]string{}
|
||||
admins = map[uint64]bool{}
|
||||
)
|
||||
|
||||
// Get the complete blocklist and bucket them into forward and reverse.
|
||||
|
@ -218,6 +219,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
type scanItem struct {
|
||||
ID uint64
|
||||
Username string
|
||||
IsAdmin bool
|
||||
}
|
||||
var scan = []scanItem{}
|
||||
if res := DB.Table(
|
||||
|
@ -225,6 +227,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
).Select(
|
||||
"id",
|
||||
"username",
|
||||
"is_admin",
|
||||
).Where(
|
||||
"id IN ?", userIDs,
|
||||
).Scan(&scan); res.Error != nil {
|
||||
|
@ -233,6 +236,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
|
||||
for _, row := range scan {
|
||||
usernames[row.ID] = row.Username
|
||||
admins[row.ID] = row.IsAdmin
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,6 +249,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
if username, ok := usernames[row.TargetUserID]; ok {
|
||||
result.Blocks = append(result.Blocks, BlocklistInsightUser{
|
||||
Username: username,
|
||||
IsAdmin: admins[row.TargetUserID],
|
||||
Date: row.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
@ -253,6 +258,7 @@ func GetBlocklistInsights(user *User) (*BlocklistInsight, error) {
|
|||
if username, ok := usernames[row.SourceUserID]; ok {
|
||||
result.BlockedBy = append(result.BlockedBy, BlocklistInsightUser{
|
||||
Username: username,
|
||||
IsAdmin: admins[row.SourceUserID],
|
||||
Date: row.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
@ -268,6 +274,7 @@ type BlocklistInsight struct {
|
|||
|
||||
type BlocklistInsightUser struct {
|
||||
Username string
|
||||
IsAdmin bool
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
|
|
|
@ -595,6 +595,33 @@ func MapAdminUsers(user *User) (UserMap, error) {
|
|||
return MapUsers(user, userIDs)
|
||||
}
|
||||
|
||||
// CountBlockedAdminUsers returns a count of how many admin users the current user has blocked, out of how many total.
|
||||
func CountBlockedAdminUsers(user *User) (count, total int64) {
|
||||
// Count the blocked admins.
|
||||
DB.Model(&User{}).Select(
|
||||
"count(users.id) AS cnt",
|
||||
).Joins(
|
||||
"JOIN blocks ON (blocks.target_user_id = users.id)",
|
||||
).Where(
|
||||
"blocks.source_user_id = ? AND users.is_admin IS TRUE",
|
||||
user.ID,
|
||||
).Count(&count)
|
||||
|
||||
// And the total number of available admins.
|
||||
total = CountAdminUsers()
|
||||
return
|
||||
}
|
||||
|
||||
// CountAdminUsers returns a count of how many admin users exist on the site.
|
||||
func CountAdminUsers() (count int64) {
|
||||
DB.Model(&User{}).Select(
|
||||
"count(id) AS cnt",
|
||||
).Where(
|
||||
"users.is_admin IS TRUE",
|
||||
).Count(&count)
|
||||
return
|
||||
}
|
||||
|
||||
// Has a user ID in the map?
|
||||
func (um UserMap) Has(id uint64) bool {
|
||||
_, ok := um[id]
|
||||
|
|
|
@ -100,11 +100,17 @@
|
|||
|
||||
<p>
|
||||
It is also against the <a href="/tos#child-exploitation">Terms of Service</a> of this website, and
|
||||
members who violate this rule will be banned. This website is actively monitored to keep on top of this stuff,
|
||||
members who violate this rule will be banned. <strong>This website is actively monitored</strong> to keep on top of this stuff,
|
||||
and we cooperate enthusiastically with
|
||||
<a href="https://www.missingkids.org/" title="National Center for Missing and Exploited Children">NCMEC</a>
|
||||
and relevant law enforcement agencies.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This incident has been reported to the website administrator. If you are surprised to see this message and
|
||||
it was on accident, don't worry -- but <strong>repeated attempts to bypass this search filter</strong> by trying
|
||||
other related keywords <strong>will be noticed</strong> and may attract extra admin attention to your account.
|
||||
</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
|
|
|
@ -99,6 +99,23 @@
|
|||
|
||||
<h3>Block Lists</h3>
|
||||
|
||||
<!-- Surface if admin users are blocked -->
|
||||
{{if .AdminBlockCount}}
|
||||
<h5 class="has-text-danger">
|
||||
<i class="fa fa-peace"></i>
|
||||
Blocked Admins <span class="tag is-danger">{{.AdminBlockCount}}</span>
|
||||
</h5>
|
||||
|
||||
<p>
|
||||
This user blocks <strong>{{.AdminBlockCount}}</strong> out of {{.AdminBlockTotal}} admin{{Pluralize64 .AdminBlockTotal}} of this website.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If this number is unusually high, it can indicate this user may be proactively blocking all the admins in order to be
|
||||
sneaky or evade moderation.
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h5 class="has-text-warning">Forward List <span class="tag is-warning">{{len .BlocklistInsights.Blocks}}</span></h5>
|
||||
|
@ -118,6 +135,9 @@
|
|||
{{range .BlocklistInsights.Blocks}}
|
||||
<li>
|
||||
<a href="/u/{{.Username}}">{{.Username}}</a>
|
||||
{{if .IsAdmin}}
|
||||
<sup class="has-text-warning fa fa-peace" title="Admin user"></sup>
|
||||
{{end}}
|
||||
<small class="has-text-grey" title="{{.Date}}">{{.Date.Format "2006-01-02"}}</small>
|
||||
</li>
|
||||
{{end}}
|
||||
|
@ -141,6 +161,9 @@
|
|||
{{range .BlocklistInsights.BlockedBy}}
|
||||
<li>
|
||||
<a href="/u/{{.Username}}">{{.Username}}</a>
|
||||
{{if .IsAdmin}}
|
||||
<sup class="has-text-warning fa fa-peace" title="Admin user"></sup>
|
||||
{{end}}
|
||||
<small class="has-text-grey" title="{{.Date}}">{{.Date.Format "2006-01-02"}}</small>
|
||||
</li>
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in New Issue
Block a user