tilde.news/app/controllers/users_controller.rb

187 lines
5.3 KiB
Ruby

# typed: false
class UsersController < ApplicationController
before_action :load_showing_user, only: [:show, :standing]
before_action :require_logged_in_moderator,
only: [:enable_invitation, :disable_invitation, :ban, :unban]
before_action :flag_warning, only: [:show, :standing]
before_action :require_logged_in_user, only: [:standing]
before_action :only_user_or_moderator, only: [:standing]
before_action :show_title_h1, only: [:show]
def show
@title = @showing_user.username
if @showing_user.is_active?
@title_class = :inactive_user
elsif @showing_user.is_new?
@title_class = :new_user
end
if @user.try(:is_moderator?)
@mod_note = ModNote.new(user: @showing_user)
@mod_note.note = params[:note]
end
respond_to do |format|
format.html { render action: "show" }
format.json { render json: @showing_user }
end
end
def tree
@title = "Users"
newest_user = User.last.id
# pulling 10k+ users is significant enough memory pressure this is worthwhile
attrs = %w[banned_at created_at deleted_at id invited_by_user_id is_admin is_moderator karma
username]
if params[:by].to_s == "karma"
content = Rails.cache.fetch("users_by_karma_#{newest_user}", expires_in: (60 * 60 * 24)) {
@users = User.select(*attrs).order("karma DESC, id ASC").to_a
@user_count = @users.length
@title << " By Karma"
render_to_string action: "list", layout: nil
}
render html: content.html_safe, layout: "application"
elsif params[:moderators]
@users = User.select(*attrs).where("is_admin = ? OR is_moderator = ?", true, true)
.order("id ASC").to_a
@user_count = @users.length
@title = "Moderators and Administrators"
render action: "list"
else
content = Rails.cache.fetch("users_tree_#{newest_user}", expires_in: (60 * 60 * 24)) {
users = User.select(*attrs).order("id DESC").to_a
@user_count = users.length
@users_by_parent = users.group_by(&:invited_by_user_id)
@newest = User.select(*attrs).order("id DESC").limit(10)
render_to_string action: "tree", layout: nil
}
render html: content.html_safe, layout: "application"
end
end
def invite
@title = "Pass Along an Invitation"
end
def disable_invitation
target = User.where(username: params[:username]).first
if !target
flash[:error] = "Invalid user."
redirect_to "/"
else
target.disable_invite_by_user_for_reason!(@user, params[:reason])
flash[:success] = "User has had invite capability disabled."
redirect_to user_path(user: target.username)
end
end
def enable_invitation
target = User.where(username: params[:username]).first
if !target
flash[:error] = "Invalid user."
redirect_to "/"
else
target.enable_invite_by_user!(@user)
flash[:success] = "User has had invite capability enabled."
redirect_to user_path(user: target.username)
end
end
def ban
buser = User.where(username: params[:username]).first
if !buser
flash[:error] = "Invalid user."
return redirect_to "/"
end
if params[:reason].blank?
flash[:error] = "You must give a reason for the ban."
return redirect_to user_path(user: buser.username)
end
buser.ban_by_user_for_reason!(@user, params[:reason])
flash[:success] = "User has been banned."
redirect_to user_path(user: buser.username)
end
def unban
buser = User.where(username: params[:username]).first
if !buser
flash[:error] = "Invalid user."
return redirect_to "/"
end
buser.unban_by_user!(@user, params[:reason])
flash[:success] = "User has been unbanned."
redirect_to user_path(user: buser.username)
end
def standing
int = @flag_warning_int
fc = FlaggedCommenters.new(int[:param], 1.day)
@fc_flagged = fc.commenters.map { |_, c| c[:n_flags] }.sort
@flagged_user_stats = fc.check_list_for(@showing_user)
rows = ActiveRecord::Base.connection.exec_query("
select
n_flags, count(*) as n_users
from (
select
comments.user_id, sum(flags) as n_flags
from
comments
where
comments.created_at >= now() - interval #{int[:dur]} #{int[:intv]}
group by comments.user_id) count_by_user
group by 1
order by 1 asc;
").rows
users = Array.new(@fc_flagged.last.to_i + 1, 0)
rows.each { |r| users[r.first] = r.last }
@lookup = rows.to_h
@flagged_comments = @showing_user.comments
.where("
comments.flags > 0 and
comments.created_at >= now() - interval #{int[:dur]} #{int[:intv]}")
.order("id DESC")
.includes(:user, :hat, story: :user)
.joins(:story)
end
private
def load_showing_user
# case-insensitive search by username
@showing_user = User.find_by(username: params[:username])
if @showing_user.nil?
@title = "User not found"
render action: :not_found, status: 404
return false
end
# now a case-sensitive check
if params[:username] != @showing_user.username
redirect_to username: @showing_user.username
false
end
end
def only_user_or_moderator
if params[:username] == @user.username || @user.is_moderator?
true
else
redirect_to(user_path(params[:username]))
end
end
end