Content jailing: hide all posts/comments on ban/suspend, restore on activate
This commit is contained in:
parent
d32da021fb
commit
d1b01aa5b2
|
|
@ -470,6 +470,9 @@ func (h *AdminHandler) UpdateUserStatus(c *gin.Context) {
|
|||
}
|
||||
// Revoke ALL refresh tokens immediately
|
||||
h.pool.Exec(ctx, `UPDATE refresh_tokens SET revoked = true WHERE user_id = $1::uuid`, targetUserID)
|
||||
// Jail all their content (hidden from feeds until restored)
|
||||
h.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1::uuid AND status = 'active' AND deleted_at IS NULL`, targetUserID)
|
||||
h.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1::uuid AND status = 'active' AND deleted_at IS NULL`, targetUserID)
|
||||
} else if req.Status == "suspended" {
|
||||
suspendUntil := time.Now().Add(7 * 24 * time.Hour) // Default 7 day suspension from admin
|
||||
_, err := h.pool.Exec(ctx, `UPDATE users SET status = 'suspended', suspended_until = $2 WHERE id = $1::uuid`, targetUserID, suspendUntil)
|
||||
|
|
@ -477,12 +480,20 @@ func (h *AdminHandler) UpdateUserStatus(c *gin.Context) {
|
|||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user status"})
|
||||
return
|
||||
}
|
||||
// Jail all their content during suspension
|
||||
h.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1::uuid AND status = 'active' AND deleted_at IS NULL`, targetUserID)
|
||||
h.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1::uuid AND status = 'active' AND deleted_at IS NULL`, targetUserID)
|
||||
} else {
|
||||
_, err := h.pool.Exec(ctx, `UPDATE users SET status = $1, suspended_until = NULL WHERE id = $2::uuid`, req.Status, targetUserID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user status"})
|
||||
return
|
||||
}
|
||||
// If reactivating, restore any jailed content
|
||||
if req.Status == "active" {
|
||||
h.pool.Exec(ctx, `UPDATE posts SET status = 'active' WHERE author_id = $1::uuid AND status = 'jailed'`, targetUserID)
|
||||
h.pool.Exec(ctx, `UPDATE comments SET status = 'active' WHERE author_id = $1::uuid AND status = 'jailed'`, targetUserID)
|
||||
}
|
||||
}
|
||||
|
||||
// Log status change
|
||||
|
|
|
|||
|
|
@ -86,9 +86,13 @@ func AuthMiddleware(jwtSecret string, pool ...*pgxpool.Pool) gin.HandlerFunc {
|
|||
}
|
||||
if status == "suspended" {
|
||||
if suspendedUntil != nil && time.Now().After(*suspendedUntil) {
|
||||
// Suspension expired — reactivate
|
||||
// Suspension expired — reactivate and restore jailed content
|
||||
dbPool.Exec(context.Background(),
|
||||
`UPDATE users SET status = 'active', suspended_until = NULL WHERE id = $1::uuid`, userID)
|
||||
dbPool.Exec(context.Background(),
|
||||
`UPDATE posts SET status = 'active' WHERE author_id = $1::uuid AND status = 'jailed'`, userID)
|
||||
dbPool.Exec(context.Background(),
|
||||
`UPDATE comments SET status = 'active' WHERE author_id = $1::uuid AND status = 'jailed'`, userID)
|
||||
} else {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "Your account is temporarily suspended.", "code": "suspended"})
|
||||
c.Abort()
|
||||
|
|
|
|||
|
|
@ -165,6 +165,9 @@ func (cf *ContentFilter) RecordStrikeWithIP(ctx context.Context, userID uuid.UUI
|
|||
cf.pool.Exec(ctx, `UPDATE users SET status = 'banned' WHERE id = $1`, userID)
|
||||
// Revoke ALL refresh tokens immediately so the user is logged out
|
||||
cf.pool.Exec(ctx, `UPDATE refresh_tokens SET revoked = true WHERE user_id = $1`, userID)
|
||||
// Jail all their content
|
||||
cf.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
cf.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
// Log IP for ban evasion prevention
|
||||
if clientIP != "" {
|
||||
cf.pool.Exec(ctx, `
|
||||
|
|
@ -177,11 +180,15 @@ func (cf *ContentFilter) RecordStrikeWithIP(ctx context.Context, userID uuid.UUI
|
|||
consequence = "suspend_7d"
|
||||
suspendUntil := time.Now().Add(7 * 24 * time.Hour)
|
||||
cf.pool.Exec(ctx, `UPDATE users SET status = 'suspended', suspended_until = $2 WHERE id = $1`, userID, suspendUntil)
|
||||
cf.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
cf.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
fmt.Printf("Content filter: user %s suspended 7 days (%d strikes)\n", userID, count)
|
||||
case count >= 3:
|
||||
consequence = "suspend_24h"
|
||||
suspendUntil := time.Now().Add(24 * time.Hour)
|
||||
cf.pool.Exec(ctx, `UPDATE users SET status = 'suspended', suspended_until = $2 WHERE id = $1`, userID, suspendUntil)
|
||||
cf.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
cf.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, userID)
|
||||
fmt.Printf("Content filter: user %s suspended 24h (%d strikes)\n", userID, count)
|
||||
default:
|
||||
fmt.Printf("Content filter: user %s warning (%d strikes)\n", userID, count)
|
||||
|
|
|
|||
Loading…
Reference in a new issue