2
0
mirror of https://github.com/moebooru/moebooru synced 2025-08-22 01:47:48 +00:00
moebooru/app/controllers/application.rb
petopeto 30ff4fccd3 --HG--
branch : moe
extra : convert_revision : svn%3A2d28d66d-8d94-df11-8c86-00306ef368cb/trunk/moe%405
2010-04-20 23:05:11 +00:00

346 lines
9.5 KiB
Ruby

require 'digest/md5'
class ApplicationController < ActionController::Base
# This is a proxy class to make various nil checks unnecessary
class AnonymousUser
def id
nil
end
def level
0
end
def name
"Anonymous"
end
def pretty_name
"Anonymous"
end
def is_anonymous?
true
end
def has_permission?(obj, foreign_key = :user_id)
false
end
def can_change?(record, attribute)
method = "can_change_#{attribute.to_s}?"
if record.respond_to?(method)
record.__send__(method, self)
elsif record.respond_to?(:can_change?)
record.can_change?(self, attribute)
else
false
end
end
def show_samples?
true
end
def has_avatar?
false
end
CONFIG["user_levels"].each do |name, value|
normalized_name = name.downcase.gsub(/ /, "_")
define_method("is_#{normalized_name}?") do
false
end
define_method("is_#{normalized_name}_or_higher?") do
false
end
define_method("is_#{normalized_name}_or_lower?") do
true
end
end
end
module LoginSystem
protected
def access_denied
previous_url = params[:url] || request.request_uri
respond_to do |fmt|
fmt.html {flash[:notice] = "Access denied"; redirect_to(:controller => "user", :action => "login", :url => previous_url)}
fmt.xml {render :xml => {:success => false, :reason => "access denied"}.to_xml(:root => "response"), :status => 403}
fmt.json {render :json => {:success => false, :reason => "access denied"}.to_json, :status => 403}
end
end
def set_current_user
if RAILS_ENV == "test" && session[:user_id]
@current_user = User.find_by_id(session[:user_id])
end
if @current_user == nil && session[:user_id]
@current_user = User.find_by_id(session[:user_id])
end
if @current_user == nil && cookies[:login] && cookies[:pass_hash]
@current_user = User.authenticate_hash(cookies[:login], cookies[:pass_hash])
end
if @current_user == nil && params[:login] && params[:password_hash]
@current_user = User.authenticate_hash(params[:login], params[:password_hash])
end
if @current_user == nil && params[:user]
@current_user = User.authenticate(params[:user][:name], params[:user][:password])
end
if @current_user
if @current_user.is_blocked? && @current_user.ban && @current_user.ban.expires_at < Time.now
@current_user.update_attribute(:level, CONFIG["starting_level"])
Ban.destroy_all("user_id = #{@current_user.id}")
end
session[:user_id] = @current_user.id
else
@current_user = AnonymousUser.new
end
# For convenient access in activerecord models
Thread.current["danbooru-user"] = @current_user
Thread.current["danbooru-user_id"] = @current_user.id
Thread.current["danbooru-ip_addr"] = request.remote_ip
# Hash the user's IP to seed things like mirror selection.
Thread.current["danbooru-ip_addr_seed"] = Digest::MD5.hexdigest(request.remote_ip)[0..7].hex
ActiveRecord::Base.init_history
UserLog.access(@current_user, request)
end
CONFIG["user_levels"].each do |name, value|
normalized_name = name.downcase.gsub(/ /, "_")
define_method("#{normalized_name}_only") do
if @current_user.__send__("is_#{normalized_name}_or_higher?")
return true
else
access_denied()
end
end
# For many actions, GET invokes the HTML UI, and a POST actually invokes
# the action, so we often want to require higher access for POST (so the UI
# can invoke the login dialog).
define_method("post_#{normalized_name}_only") do
return true unless request.post?
if @current_user.__send__("is_#{normalized_name}_or_higher?")
return true
else
access_denied()
end
end
end
end
module RespondToHelpers
protected
def respond_to_success(notice, redirect_to_params, options = {})
extra_api_params = options[:api] || {}
respond_to do |fmt|
fmt.html {flash[:notice] = notice ; redirect_to(redirect_to_params)}
fmt.json {render :json => extra_api_params.merge(:success => true).to_json}
fmt.xml {render :xml => extra_api_params.merge(:success => true).to_xml(:root => "response")}
end
end
def respond_to_error(obj, redirect_to_params, options = {})
extra_api_params = options[:api] || {}
status = options[:status] || 500
if obj.is_a?(ActiveRecord::Base)
obj = obj.errors.full_messages.join(", ")
status = 420
end
case status
when 420
status = "420 Invalid Record"
when 421
status = "421 User Throttled"
when 422
status = "422 Locked"
when 423
status = "423 Already Exists"
when 424
status = "424 Invalid Parameters"
end
respond_to do |fmt|
fmt.html {flash[:notice] = "Error: #{obj}" ; redirect_to(redirect_to_params)}
fmt.json {render :json => extra_api_params.merge(:success => false, :reason => obj).to_json, :status => status}
fmt.xml {render :xml => extra_api_params.merge(:success => false, :reason => obj).to_xml(:root => "response"), :status => status}
end
end
def respond_to_list(inst_var_name)
inst_var = instance_variable_get("@#{inst_var_name}")
respond_to do |fmt|
fmt.html
fmt.json {render :json => inst_var.to_json}
fmt.xml {render :xml => inst_var.to_xml(:root => inst_var_name)}
end
end
def render_error(record)
@record = record
render :status => 500, :layout => "bare", :inline => "<%= error_messages_for('record') %>"
end
end
include LoginSystem
include RespondToHelpers
#include ExceptionNotifiable
include CacheHelper
#local_addresses.clear
before_filter :set_title
before_filter :set_current_user
before_filter :check_ip_ban
after_filter :init_cookies
protected :build_cache_key
protected :get_cache_key
def get_ip_ban()
ban = IpBans.find(:first, :conditions => ["? <<= ip_addr", request.remote_ip])
if not ban then return nil end
return ban
end
protected
def check_ip_ban
if request.parameters[:controller] == "banned" and request.parameters[:action] == "index" then
return
end
ban = get_ip_ban()
if not ban then
return
end
if ban.expires_at && ban.expires_at < Time.now then
IpBans.destroy_all("ip_addr = '#{request.remote_ip}'")
return
end
redirect_to :controller => "banned", :action => "index"
end
def check_load_average
current_load = Sys::CPU.load_avg[1]
if request.get? && request.env["HTTP_USER_AGENT"] !~ /Google/ && current_load > CONFIG["load_average_threshold"] && @current_user.is_member_or_lower?
render :file => "#{RAILS_ROOT}/public/503.html", :status => 503
return false
end
end
def set_title(title = CONFIG["app_name"])
@page_title = CGI.escapeHTML(title)
end
def save_tags_to_cookie
if params[:tags] || (params[:post] && params[:post][:tags])
tags = TagAlias.to_aliased((params[:tags] || params[:post][:tags]).downcase.scan(/\S+/))
tags += cookies["recent_tags"].to_s.scan(/\S+/)
cookies["recent_tags"] = tags.slice(0, 20).join(" ")
end
end
def set_cache_headers
response.headers["Cache-Control"] = "max-age=300"
end
def cache_action
if request.method == :get && request.env !~ /Googlebot/ && params[:format] != "xml" && params[:format] != "json"
key, expiry = get_cache_key(controller_name, action_name, params, :user => @current_user)
if key && key.size < 200
cached = Cache.get(key)
unless cached.blank?
render :text => cached, :layout => false
return
end
end
yield
if key && response.headers['Status'] =~ /^200/
Cache.put(key, response.body, expiry)
end
else
yield
end
end
def init_cookies
unless @current_user.is_anonymous?
if @current_user.has_mail?
cookies["has_mail"] = "1"
else
cookies["has_mail"] = "0"
end
if @current_user.is_privileged_or_higher? && ForumPost.updated?(@current_user)
cookies["forum_updated"] = "1"
else
cookies["forum_updated"] = "0"
end
if @current_user.is_privileged_or_higher? && Comment.updated?(@current_user)
cookies["comments_updated"] = "1"
else
cookies["comments_updated"] = "0"
end
if @current_user.is_blocked?
if @current_user.ban
cookies["block_reason"] = "You have been blocked. Reason: #{@current_user.ban.reason}. Expires: #{@current_user.ban.expires_at.strftime('%Y-%m-%d')}"
else
cookies["block_reason"] = "You have been blocked."
end
else
cookies["block_reason"] = ""
end
if @current_user.always_resize_images?
cookies["resize_image"] = "1"
else
cookies["resize_image"] = "0"
end
cookies["my_tags"] = @current_user.my_tags
cookies["blacklisted_tags"] = @current_user.blacklisted_tags_array
cookies["held_post_count"] = @current_user.held_post_count.to_s
else
cookies["blacklisted_tags"] = CONFIG["default_blacklists"]
end
if flash[:notice] then
cookies["notice"] = flash[:notice]
end
end
end