diff --git a/go-backend/internal/handlers/admin_handler.go b/go-backend/internal/handlers/admin_handler.go index 2b11b34..b57188d 100644 --- a/go-backend/internal/handlers/admin_handler.go +++ b/go-backend/internal/handlers/admin_handler.go @@ -1223,15 +1223,41 @@ func (h *AdminHandler) ReviewModerationFlag(c *gin.Context) { var postID, commentID *uuid.UUID h.pool.QueryRow(ctx, `SELECT post_id, comment_id FROM moderation_flags WHERE id = $1`, flagUUID).Scan(&postID, &commentID) + // Remove the flagged content + if postID != nil { + h.pool.Exec(ctx, `UPDATE posts SET status = 'removed', deleted_at = NOW() WHERE id = $1`, postID) + } + if commentID != nil { + h.pool.Exec(ctx, `UPDATE comments SET status = 'removed', deleted_at = NOW() WHERE id = $1`, commentID) + } + var authorID *uuid.UUID if postID != nil { h.pool.QueryRow(ctx, `SELECT author_id FROM posts WHERE id = $1`, postID).Scan(&authorID) } - if commentID != nil { + if commentID != nil && authorID == nil { h.pool.QueryRow(ctx, `SELECT author_id FROM comments WHERE id = $1`, commentID).Scan(&authorID) } if authorID != nil { - h.moderationService.UpdateUserStatus(ctx, *authorID, "banned", adminUUID, req.Reason) + // Ban the user + h.pool.Exec(ctx, `UPDATE users SET status = 'banned' WHERE id = $1`, authorID) + // Revoke all refresh tokens + h.pool.Exec(ctx, `UPDATE refresh_tokens SET revoked = true WHERE user_id = $1`, authorID) + // Jail all their content + h.pool.Exec(ctx, `UPDATE posts SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, authorID) + h.pool.Exec(ctx, `UPDATE comments SET status = 'jailed' WHERE author_id = $1 AND status = 'active' AND deleted_at IS NULL`, authorID) + // Log status change + h.pool.Exec(ctx, `INSERT INTO user_status_history (user_id, old_status, new_status, reason, changed_by) VALUES ($1, 'active', 'banned', $2, $3)`, authorID, req.Reason, adminUUID) + // Send ban email + if h.emailService != nil { + var userEmail, displayName string + h.pool.QueryRow(ctx, `SELECT u.email, COALESCE(p.display_name, '') FROM users u LEFT JOIN profiles p ON p.id = u.id WHERE u.id = $1`, authorID).Scan(&userEmail, &displayName) + if userEmail != "" { + go func() { + h.emailService.SendBanNotificationEmail(userEmail, displayName, req.Reason) + }() + } + } } } diff --git a/go-backend/scripts/fix_moderation_flags_status.sql b/go-backend/scripts/fix_moderation_flags_status.sql new file mode 100644 index 0000000..0329523 --- /dev/null +++ b/go-backend/scripts/fix_moderation_flags_status.sql @@ -0,0 +1,4 @@ +-- Drop old restrictive CHECK and add one matching the actual statuses used +ALTER TABLE moderation_flags DROP CONSTRAINT IF EXISTS moderation_flags_status_check; +ALTER TABLE moderation_flags ADD CONSTRAINT moderation_flags_status_check + CHECK (status = ANY (ARRAY['pending', 'approved', 'rejected', 'escalated', 'dismissed', 'actioned']));