module Blubber
module ControllerSupport
@logger = Logger.new(STDERR)
@@minimum_roles = nil
# TODO: move to-be-inherited methods into an own module
protected
def current_user
@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
Thread.current[:user_id] = @current_user.id if @current_user
@current_user
end
def acl_check
user = current_user
self.prepare(user, params)
# stat = add_stats(@current_user, params[:controller], params[:action], topic_instance)
minimum_role = get_minimum_role(params[:action].to_sym)
# if access was anonymous check the parameter for an email
case minimum_role
when :anonymous
if params.include?(:email) && user.nil? then
user = @current_user = User.find_by_email(params[:email])
end
return @current_user
when :guest
if params.include?(:email) && user.nil? then
@current_user = User.find_by_email(params[:email])
user = @current_user
end
end
if user then
if user.guest? then
role = :guest
else
role = self.role_for(user)
end
else
role = :anonymous
end
if permissions_sufficient(role, minimum_role) then
current_user
else
access_denied
end
end
def permissions_sufficient(role, minimum_role)
case role
when :moderator
return true
when :friend
return true if minimum_role != :moderator
when :user
return true if [:anonymous, :guest, :user].include? minimum_role
when :guest
return true if [:anonymous, :guest].include? minimum_role
when :anonymous
return true if minimum_role == :anonymous
end
return false
end
def prepare_acl(acls, mode)
result = {}
acls.each do |action|
result[action] = mode
end
return result
end
public
def acl_map
acls = {}
acls.merge! prepare_acl(self.acl_friends, :friends)
acls.merge! prepare_acl(self.acl_user, :user)
acls.merge! prepare_acl(self.acl_guests, :guests)
acls.merge! prepare_acl(self.acl_anonymous, :anonymous)
acls
end
protected
def self.generate_minimum_role_hash
@logger.info "generated ACL table (not listed ACLs are :moderator)"
@@minimum_roles = {}
controllers = Dir.new("#{RAILS_ROOT}/app/controllers").entries
controllers.each do |controller|
if controller =~ /_controller/
c = controller.camelize.gsub(".rb", "").constantize.new
@@minimum_roles[c.controller_name.to_sym] = c.acl_map
@logger.warn "#{c.controller_name} -> #{c.acl_map.inspect}"
end
end
end
def get_minimum_role(action)
if RAILS_ENV == "production" && @@minimum_roles then
minimum = @@minimum_roles[self.controller_name.to_sym][action]
minimum ||= :moderator
else
minimum = :moderator
minimum = :friend if self.acl_friends and self.acl_friends.include?(action)
minimum = :user if self.acl_user and self.acl_user.include?(action)
minimum = :guest if self.acl_guests and self.acl_guests.include?(action)
minimum = :anonymous if self.acl_anonymous and self.acl_anonymous.include?(action)
end
return minimum
end
# Store the given user id in the session.
def current_user=(new_user)
Thread.current[:user_id] = session[:user_id] = new_user ? new_user.id : nil
end
# TODO add support for statistics..
def add_stats(user, controller, action, topic_instance=nil)
stat = StatsAccessLog.new
stat.controller = StatsController.find_or_create_by_name(controller)
stat.topic_instance = topic_instance
stat.action = action
stat.user_id = user.nil? ? 0 : user.id
stat.save!
stat
end
# Redirect as appropriate when an access request fails.
#
# The default action is to redirect to the login screen.
#
# Override this method in your controllers if you want to have special
# behavior in case the user is not authorized
# to access the requested action. For example, a popup window might
# simply close itself.
def access_denied
respond_to do |format|
format.html do
store_location
redirect_to new_session_path
end
format.any do
request_http_basic_authentication 'Web Password'
end
end
end
#TODO investigate what is needed..
def logged_in?
current_user
end
private
def store_location
session[:return_to] = request.request_uri
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
def login_from_session
self.current_user = User.find_by_id(session[:user_id]) if session[:user_id]
end
def login_from_basic_auth
authenticate_with_http_basic do |username, password|
self.current_user = User.authenticate(username, password)
end
end
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
user.remember_me
cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at }
self.current_user = user
end
end
protected
def role_for(user)
:user
end
def acl_friends
[]
end
def acl_user
[]
end
def acl_guests
[]
end
def acl_anonymous
[]
end
def prepare(user, params)
nil
end
end
module UserSupport
# callback authenticate
def current_user
user_id = Thread.current[:user_id]
raise "didn't set current user.." unless user_id
return user_id
end
def current_user_object
@current_user ||= User.find(current_user)
end
def current_user=(user)
if user.is_a? User then
Thread.current[:user_id] = user.id
else
Thread.current[:user_id] = user
end
end
end
end