namespace :auth do

desc "Lists all privileges used in controllers, views, models"
task :used_privileges do
  # TODO note where privileges are used
  require File.join(Rails.root, 'config', 'boot.rb')
  require File.join(Rails.root, 'config', 'environment.rb')
  controllers = [ApplicationController]
  Dir.new("#{Rails.root}/app/controllers").entries.each do |controller_file|
    if controller_file =~ /_controller/ 
      controllers << controller_file.gsub(".rb","").camelize.constantize
    end
  end 
  perms = controllers.select {|c| c.send(:class_variable_defined?, :@@permissions)}.
                      inject([]) do |all, c|
    contr_context = c.name.sub("Controller", "").tableize.to_sym
    contr_perms = c.send(:class_variable_get, :@@permissions).collect do |cp|
      [cp.privilege, cp.context || contr_context, cp]
    end
    if contr_perms.any? {|cp| cp[0].nil?}
      contr_perms += c.send(:action_methods).collect {|am| am.to_sym}.
                       reject {|am| contr_perms.any? {|cp| cp[2].actions.include?(am)}}.
                       collect {|am| [am, contr_context]}
    end
    all += contr_perms.reject {|cp| cp[0].nil?}.collect {|cp| cp[0..1]}
  end

  model_all = `grep -l "Base\.using_access_control" #{Rails.root}/config/*.rb #{Rails.root}/config/initializers/*.rb`.split("\n")
  if model_all.count > 0
    model_files = Dir.glob( "#{Rails.root}/app/models/*.rb").reject do |item|
      item.match(/_observer\.rb/)
    end
  else
    model_files = `grep -l "^[[:space:]]*using_access_control" #{Rails.root}/app/models/*.rb`.split("\n")
  end
  models_with_ac = model_files.collect {|mf| mf.sub(/^.*\//, "").sub(".rb", "").tableize.to_sym}
  model_security_privs = [:create, :read, :update, :delete]
  models_with_ac.each {|m| perms += model_security_privs.collect{|msp| [msp, m]}}

  grep_file_pattern = "#{Rails.root}/app/models/*.rb #{Rails.root}/app/views/**/* #{Rails.root}/app/controllers/*.rb"
  `grep "permitted_to?" #{grep_file_pattern}`.split("\n").each do |ptu|
    file, grep_match = ptu.split(':', 2)
    context = privilege = nil
    if (match = grep_match.match(/permitted_to\?\(?\s*:(\w+),\s*(:?@?\w+)/))
      privilege = match[1].to_sym
      if match[2][0..0] == ':'
        context = match[2][1..-1].to_sym
      else
        c = (match[2][0..0] == '@' ? match[2][1..-1] : match[2]).pluralize.to_sym
        context = c if perms.any? {|p| p[1] == c}
      end
    end
    if privilege.nil? or context.nil?
      puts "Could not handle: #{ptu}"
    else
      perms << [privilege, context]
    end
  end

  `grep ".with_permissions_to" #{grep_file_pattern}`.split("\n").each do |wpt|
    file, grep_match = wpt.split(':', 2)
    context = privilege = nil
    if match = grep_match.match(/(\w+\.)?with_permissions_to(\(:\w+)?/)
      c = match[1][0..-2].tableize.to_sym if match[1]
      c ||= File.basename(file, '.rb').tableize.to_sym
      context = c if perms.any? {|p| p[1] == c}
      privilege = match[2] && match[2][(match[2][0..0]=='(' ? 2 : 1)..-1].to_sym
      privilege ||= :read
    end
    if privilege.nil? or context.nil?
      puts "Could not handle: #{wpt}"
    else
      perms << [privilege, context]
    end
  end

  perms.uniq!
  perm_hash = {}
  perms.each do |cp| 
    perm_hash[cp[1]] ||= []
    perm_hash[cp[1]] << cp[0]
  end

  puts "Privileges currently in use:"
  perm_hash.each do |context, privileges|
    puts "  #{context.inspect}:\t#{privileges.collect {|p| p.inspect}.sort * ', '}"
    #privileges.collect {|p| p.inspect}.sort.each {|p| puts "  #{p}"}
  end
end

end