Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion declarative_authorization.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Gem::Specification.new do |s|
s.name = "declarative_authorization"
s.version = "0.5.6"
s.version = "0.5.7"

s.required_ruby_version = ">= 1.8.6"
s.authors = ["Steffen Bartsch"]
Expand Down
15 changes: 14 additions & 1 deletion lib/declarative_authorization/authorization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,19 @@ def roles_with_hierarchy_for(user)
flatten_roles(roles_for(user))
end

def self.force_reload
@@force_reload = true
end

def self.force_reload?
#if defined? @@force_reload
# temp = @@force_reload
# @@force_reload = false
#end
#temp
true
end

def self.development_reload?
if Rails.env.development?
mod_time = AUTH_DSL_FILES.map { |m| File.mtime(m) rescue Time.at(0) }.flatten.max
Expand All @@ -293,7 +306,7 @@ def self.development_reload?
# yet. If +dsl_file+ is given, it is passed on to Engine.new and
# a new instance is always created.
def self.instance (dsl_file = nil)
if dsl_file or development_reload?
if dsl_file or development_reload? or force_reload?
@@instance = new(dsl_file)
else
@@instance ||= new
Expand Down
67 changes: 47 additions & 20 deletions lib/declarative_authorization/reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class DSLFileNotFoundError < Exception; end
class DSLError < Exception; end
# Signals errors in the syntax of an authorization DSL.
class DSLSyntaxError < DSLError; end

# Top-level reader, parses the methods +privileges+ and +authorization+.
# +authorization+ takes a block with authorization rules as described in
# AuthorizationRulesReader. The block to +privileges+ defines privilege
Expand All @@ -70,10 +70,10 @@ def initialize_copy (from) # :nodoc:
# String or Array - it will treat it as if you have passed a path or an array of paths and attempt to load those.
def self.factory(obj)
case obj
when Reader::DSLReader
obj
when String, Array
load(obj)
when Reader::DSLReader
obj
when String, Array
load(obj)
end
end

Expand Down Expand Up @@ -189,7 +189,7 @@ def includes (*privileges)

class AuthorizationRulesReader
attr_reader :roles, :role_hierarchy, :auth_rules,
:role_descriptions, :role_titles, :omnipotent_roles # :nodoc:
:role_descriptions, :role_titles, :omnipotent_roles # :nodoc:

def initialize # :nodoc:
@current_role = nil
Expand All @@ -205,7 +205,7 @@ def initialize # :nodoc:

def initialize_copy (from) # :nodoc:
[:roles, :role_hierarchy, :auth_rules,
:role_descriptions, :role_titles, :omnipotent_roles].each do |attribute|
:role_descriptions, :role_titles, :omnipotent_roles].each do |attribute|
instance_variable_set(:"@#{attribute}", from.send(attribute).clone)
end
end
Expand Down Expand Up @@ -245,7 +245,13 @@ def includes (*roles)
@role_hierarchy[@current_role] ||= []
@role_hierarchy[@current_role] += roles.flatten
end


def class_from_string(str)
str.split('::').inject(Object) do |mod, class_name|
mod.const_get(class_name)
end
end

# Allows the definition of privileges to be allowed for the current role,
# either in a has_permission_on block or directly in one call.
# role :admin
Expand Down Expand Up @@ -277,17 +283,38 @@ def includes (*roles)
def has_permission_on (*args, &block)
options = args.extract_options!
context = args.flatten

raise DSLError, "has_permission_on only allowed in role blocks" if @current_role.nil?

# Adding the option to set permission on all actions in a controller.
# For example: has_permission_on :users, :to => :all
if options[:to].include? :all
begin
routes = Rails.application.routes.routes.routes
raw_name = context[0].to_s
results = routes.select { |route| route.defaults.blank? ? false : route.defaults[:controller].split(/[\/_]/).join('_') == raw_name }
controller_parts = results.first.defaults[:controller].split('/')
controller_parts.each { |part| part.capitalize! }
controller_name = controller_parts.push(controller_parts.pop.camelize).join("::")
controller = class_from_string(controller_name.camelize + "Controller")

actions = []
controller.action_methods.each { |m| actions << m.to_sym }
options[:to] = actions
rescue
end
end
##########################################################################

options = {:to => [], :join_by => :or}.merge(options)
privs = options[:to]

privs = options[:to]
privs = [privs] unless privs.is_a?(Array)
raise DSLError, "has_permission_on either needs a block or :to option" if !block_given? and privs.empty?

file, line = file_and_line_number_from_call_stack
rule = AuthorizationRule.new(@current_role, privs, context, options[:join_by],
:source_file => file, :source_line => line)
:source_file => file, :source_line => line)
@auth_rules << rule
if block_given?
@current_rule = rule
Expand Down Expand Up @@ -316,7 +343,7 @@ def description (text)
raise DSLError, "description only allowed in role blocks" if @current_role.nil?
role_descriptions[@current_role] = text
end

# Sets a human-readable title for the current role. E.g.
# role :admin
# title "Administrator"
Expand All @@ -326,7 +353,7 @@ def title (text)
raise DSLError, "title only allowed in role blocks" if @current_role.nil?
role_titles[@current_role] = text
end

# Used in a has_permission_on block, to may be used to specify privileges
# to be assigned to the current role under the conditions specified in
# the current block.
Expand Down Expand Up @@ -452,9 +479,9 @@ def if_permitted_to (privilege, attr_or_hash = nil, options = {})
# only :context option in attr_or_hash:
attr_or_hash = nil if attr_or_hash.is_a?(Hash) and attr_or_hash.empty?
@current_rule.append_attribute AttributeWithPermission.new(privilege,
attr_or_hash, options[:context])
attr_or_hash, options[:context])
end

# In an if_attribute statement, is says that the value has to be
# met exactly by the if_attribute attribute. For information on the block
# argument, see if_attribute.
Expand Down Expand Up @@ -487,7 +514,7 @@ def does_not_contain (&block)
def intersects_with (&block)
[:intersects_with, block]
end

# In an if_attribute statement, is_in says that the value has to
# contain the attribute value.
# For information on the block argument, see if_attribute.
Expand All @@ -499,7 +526,7 @@ def is_in (&block)
def is_not_in (&block)
[:is_not_in, block]
end

# Less than
def lt (&block)
[:lt, block]
Expand Down Expand Up @@ -534,11 +561,11 @@ def parse_attribute_conditions_hash! (hash)
end
hash.merge!(merge_hash)
end

def file_and_line_number_from_call_stack
caller_parts = caller(2).first.split(':')
[caller_parts[0] == "(eval)" ? nil : caller_parts[0],
caller_parts[1] && caller_parts[1].to_i]
caller_parts[1] && caller_parts[1].to_i]
end
end
end
Expand Down