app/controllers/user_controller.rb
class UserController < ApplicationController
layout "default"
before_action :blocked_only, :only => [:authenticate, :update, :edit, :modify_blacklist]
before_action :janitor_only, :only => [:invites]
before_action :mod_only, :only => [:block, :unblock, :show_blocked_users]
before_action :post_member_only, :only => [:set_avatar]
before_action :no_anonymous, :only => [:change_password, :change_email, :show]
helper :post, :tag_subscription
helper :avatar
protected
def save_cookies(user)
@current_user = user
session[:user_id] = user.id
end
public
def autocomplete_name
keyword = params[:term].to_s
@users = User.where(["name ILIKE ?", "*#{keyword}*".to_escaped_for_sql_like]).order('LENGTH(name)', :name).limit(20).pluck(:name) if keyword.length >= 2
respond_to do |format|
format.json { render :json => (@users || []) }
end
end
# FIXME: this method is crap and only function as temporary workaround
# until I convert the controllers to resourceful version which is
# planned for 3.2 branch (at least 3.2.1).
def remove_avatar
# When removing other user's avatar, ensure current user is mod or higher.
if @current_user.id != params[:id] && !@current_user.is_mod_or_higher?
access_denied
return
end
@user = User.find(params[:id])
@user.avatar_post_id = nil
if @user.save
flash[:notice] = "Avatar removed"
else
flash[:notice] = "Failed removing avatar"
end
redirect_to :action => :show, :id => params[:id]
end
def change_password
@title = "Change Password"
respond_to { |format| format.html { render :layout => "settings" } }
end
def change_email
@title = "Change Email"
@current_user.current_email = @current_user.email
respond_to { |format| format.html { render :layout => "settings" } }
end
def show
if params[:name]
@user = User.find_by_name(params[:name])
else
@user = User.find(params[:id])
end
if @user.nil?
redirect_to "/404"
end
if @current_user.is_mod_or_higher?
@user_ips = @user.user_logs.order("created_at DESC").pluck("ip_addr").uniq
end
respond_to do |format|
format.html
end
end
def invites
if request.post?
if params[:member]
begin
@current_user.invite!(params[:member][:name], params[:member][:level])
flash[:notice] = "User was invited"
rescue ActiveRecord::RecordNotFound
flash[:notice] = "Account not found"
rescue User::NoInvites
flash[:notice] = "You have no invites for use"
rescue User::HasNegativeRecord
flash[:notice] = "This use has a negative record and must be invited by an admin"
end
end
redirect_to :action => "invites"
else
@invited_users = User.where(:invited_by => @current_user.id).order('name_normalized')
end
end
def home
end
def index
@users = User.with_params(params).paginate(:per_page => 20, :page => page_number)
respond_to_list("users")
end
def authenticate
save_cookies(@current_user)
if params[:url].is_a?(String) && params[:url][0] == '/'
path = params[:url]
end
path ||= { :action => "home" }
respond_to_success("You are now logged in", path)
end
# TODO: merge with .authenticate
def check
user = User.find_by_name(params[:username])
ret = { :exists => false }
ret[:name] = params[:username]
unless user
respond_to_success("User does not exist", {}, :api => { :response => "unknown-user" }.merge(ret))
return
end
# Return some basic information about the user even if the password isn't given, for
# UI cosmetics.
ret[:exists] = true
ret[:id] = user.id
ret[:name] = user.name
ret[:no_email] = user.email.blank?
user = User.authenticate(params[:username], params[:password] || "")
unless user
respond_to_success("Wrong password", {}, :api => { :response => "wrong-password" }.merge(ret))
return
end
save_cookies(user)
ret[:pass_hash] = user.password_hash
ret[:user_info] = user.user_info_cookie
respond_to_success("Successful", {}, :api => { :response => "success" }.merge(ret))
end
def login
respond_to { |format| format.html }
end
def create
user = User.create(user_params_for_create)
if user.errors.empty?
save_cookies(user)
ret = { :exists => false }
ret[:name] = user.name
ret[:id] = user.id
ret[:pass_hash] = user.password_hash
ret[:user_info] = user.user_info_cookie
respond_to_success("New account created", { :action => "home" }, :api => { :response => "success" }.merge(ret))
else
error = user.errors.full_messages.join(", ")
respond_to_success("Error: " + error, { :action => "signup" }, :api => { :response => "error", :errors => user.errors.full_messages })
end
end
def signup
@user = User.new
end
def logout
reset_session
flash[:notice] = 'You are now logged out'
respond_to do |format|
format.js
end
end
def update
if params[:commit] == "Cancel"
redirect_to :action => "home"
return
end
if @current_user.update(user_params_for_update)
respond_to_success("Account settings saved", :action => "edit")
else
if params[:render] && params[:render][:view]
render get_view_name_for_edit(params[:render][:view])
else
respond_to_error(@current_user, :action => "edit")
end
end
end
def modify_blacklist
added_tags = params[:add] || []
removed_tags = params[:remove] || []
tags = @current_user.blacklisted_tags_array
added_tags.each do |tag|
tags << tag unless tags.include?(tag)
end
tags -= removed_tags
if @current_user.update(:blacklisted_tags => tags.join("\n"))
respond_to_success("Tag blacklist updated", { :action => "home" }, :api => { :result => @current_user.blacklisted_tags_array })
else
respond_to_error(@current_user, :action => "edit")
end
end
def remove_from_blacklist
end
def edit
@user = @current_user
render :layout => "settings"
end
def reset_password
if request.post?
@user = User.find_by_name(params[:user][:name])
if @user.nil?
respond_to_error("That account does not exist", { :action => "reset_password" }, :api => { :result => "unknown-user" })
return
end
if @user.email.blank?
respond_to_error("You never supplied an email address, therefore you cannot have your password automatically reset",
{ :action => "login" }, :api => { :result => "no-email" })
return
end
if @user.email != params[:user][:email]
respond_to_error("That is not the email address you supplied",
{ :action => "login" }, :api => { :result => "wrong-email" })
return
end
begin
User.transaction do
# If the email is invalid, abort the password reset
new_password = @user.reset_password
UserMailer.new_password(@user, new_password).deliver_now
respond_to_success("Password reset. Check your email in a few minutes.",
{ :action => "login" }, :api => { :result => "success" })
end
rescue Net::SMTPSyntaxError, Net::SMTPFatalError
respond_to_success("Your email address was invalid",
{ :action => "login" }, :api => { :result => "invalid-email" })
end
else
@user = User.new
redirect_to root_path if params[:format] && params[:format] != "html"
end
end
def block
@user = User.find(params[:id])
if request.post?
if @user.is_mod_or_higher?
flash[:notice] = "You can not ban other moderators or administrators"
redirect_to :action => "block"
return
end
Ban.create(ban_params.merge(:banned_by => @current_user.id, :user_id => params[:id]))
redirect_to :action => "show_blocked_users"
else
@ban = Ban.new(:user_id => @user.id, :duration => "1")
end
end
def unblock
params[:user].keys.each do |user_id|
Ban.where(:user_id => user_id).destroy_all
end
redirect_to :action => "show_blocked_users"
end
def show_blocked_users
@users = User.includes(:ban).joins(:ban).order("bans.expires_at ASC")
@ip_bans = IpBans.all
end
if CONFIG["enable_account_email_activation"]
def resend_confirmation
if request.post?
user = User.find_by_email(params[:email])
if user.nil?
flash[:notice] = "No account exists with that email"
redirect_to :action => "home"
return
end
if user.is_blocked_or_higher?
flash[:notice] = "Your account is already activated"
redirect_to :action => "home"
return
end
UserMailer.confirmation_email(user).deliver_now
flash[:notice] = "Confirmation email sent"
redirect_to :action => "home"
end
end
def activate_user
flash[:notice] = "Invalid confirmation code"
users = User.where(:level => CONFIG["user_levels"]["Unactivated"])
users.each do |user|
if User.confirmation_hash(user.name) == params["hash"]
user.update(:level => CONFIG["starting_level"])
flash[:notice] = "Account has been activated"
break
end
end
redirect_to :action => "home"
end
end
def set_avatar
@user = @current_user
if params[:user_id]
@user = User.find(params[:user_id])
respond_to_error("Not found", :action => "index", :status => 404) unless @user
end
if !@user.is_anonymous? && !@current_user.has_permission?(@user, :id)
access_denied
return
end
if request.post?
if @user.set_avatar(params)
redirect_to :action => "show", :id => @user.id
else
respond_to_error(@user, :action => "home")
end
end
if !@user.is_anonymous? && params[:id] == @user.avatar_post_id
@old = params
end
@params = params
@post = Post.find(params[:id])
end
def error
report = params[:report]
file = "#{Rails.root}/log/user_errors.log"
File.open(file, "a") do |f|
f.write(report.to_s + "\n\n\n-------------------------------------------\n\n\n")
end
render :json => { :success => true }
end
private
def get_view_name_for_edit(param)
case param
when "change_email"
:change_email
when "change_password"
:change_password
else
:edit
end
end
def ban_params
params.require(:ban).permit(:reason, :duration)
end
def user_params_for_create
params.require(:user).permit(:name, :email, :password, :password_confirmation, :blacklisted_tags, :always_resize_images, :receive_dmails, :show_samples, :use_browser, :show_advanced_editing, :pool_browse_mode)
end
def user_params_for_update
params.require(:user).permit(:email, :current_password, :password, :password_confirmation, :blacklisted_tags, :always_resize_images, :receive_dmails, :show_samples, :use_browser, :show_advanced_editing, :pool_browse_mode)
end
end