diff options
author | http://jneen.net/ <jneen@jneen.net> | 2017-04-07 00:06:24 +0300 |
---|---|---|
committer | http://jneen.net/ <jneen@jneen.net> | 2017-06-27 22:41:54 +0300 |
commit | 80d6e5bbd4bb4b2a418e3e81b45b59c01ca00b0c (patch) | |
tree | 975d804b8a68b73c83edb187a20b862be7b0cf38 /lib/declarative_policy.rb | |
parent | 585e6aa5b20b31b1de01f7c5aa9aea67d7a377f4 (diff) |
add a new DeclarativePolicy framework
Diffstat (limited to 'lib/declarative_policy.rb')
-rw-r--r-- | lib/declarative_policy.rb | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/declarative_policy.rb b/lib/declarative_policy.rb new file mode 100644 index 00000000000..d9959bc1aff --- /dev/null +++ b/lib/declarative_policy.rb @@ -0,0 +1,58 @@ +require_dependency 'declarative_policy/cache' +require_dependency 'declarative_policy/condition' +require_dependency 'declarative_policy/dsl' +require_dependency 'declarative_policy/preferred_scope' +require_dependency 'declarative_policy/rule' +require_dependency 'declarative_policy/runner' +require_dependency 'declarative_policy/step' + +require_dependency 'declarative_policy/base' + +module DeclarativePolicy + class << self + def policy_for(user, subject, opts = {}) + cache = opts[:cache] || {} + key = Cache.policy_key(user, subject) + + cache[key] ||= class_for(subject).new(user, subject, opts) + end + + def class_for(subject) + return GlobalPolicy if subject == :global + return NilPolicy if subject.nil? + + subject = find_delegate(subject) + + subject.class.ancestors.each do |klass| + next unless klass.name + + begin + policy_class = "#{klass.name}Policy".constantize + + # NOTE: the < operator here tests whether policy_class + # inherits from Base. We can't use #is_a? because that + # tests for *instances*, not *subclasses*. + return policy_class if policy_class < Base + rescue NameError + nil + end + end + + raise "no policy for #{subject.class.name}" + end + + private + + def find_delegate(subject) + seen = Set.new + + while subject.respond_to?(:declarative_policy_delegate) + raise ArgumentError, "circular delegations" if seen.include?(subject.object_id) + seen << subject.object_id + subject = subject.declarative_policy_delegate + end + + subject + end + end +end |