lib/ixtlan/guard/guard_ng.rb in ixtlan-guard-0.7.0 vs lib/ixtlan/guard/guard_ng.rb in ixtlan-guard-0.7.2

- old
+ new

@@ -2,10 +2,12 @@ module Ixtlan module Guard class GuardNG + attr_reader :superuser + def initialize(options = {}) options[:guards_dir] ||= File.expand_path(".") @superuser = [(options[:superuser] || "root").to_s] @config = Config.new(options) @logger = options[:logger] @@ -29,128 +31,127 @@ require 'logger' Logger.new(STDOUT) end end - def allowed_groups(resource, action, current_groups) - allowed = @config.allowed_groups(resource, action) - blocked_groups + @superuser + def allowed_groups(resource_name, action, current_group_names) + allowed = @config.allowed_groups(resource_name, action) - blocked_groups + @superuser if allowed.member?('*') - current_groups - (blocked_groups - @superuser) + # keep superuser in current_groups if in there + current_group_names - (blocked_groups - @superuser) else - intersect(allowed, current_groups) + allowed & current_group_names end end - def allowed?(resource, action, current_groups, flavor = nil, &block) - current_groups = current_groups.collect { |g| g.to_s } - allowed_groups = self.allowed_groups(resource, action, current_groups) - logger.debug { "guard #{resource}##{action}: #{allowed_groups.size > 0}" } - if allowed_groups.size > 0 - if block - g = allowed_groups.detect do |group| - block.call(group).member?(flavor) - end - logger.debug do - if g - "found group #{g} for #{flavor}" - else - "no group found for #{flavor}" - end - end - g != nil + def group_map(current_groups) + names = current_groups.collect do |g| + key = case g + when String + g + when Symbol + g.to_s + else + g.name.to_s + end + [key, g] + end + Hash[*(names.flatten)] + end + private :group_map + + def allowed?(resource_name, action, current_groups, association = nil, &block) + group_map = group_map(current_groups) + allowed_group_names = allowed_groups(resource_name, action, group_map.keys) + logger.debug { "guard #{resource_name}##{action}: #{allowed_group_names.size > 0}" } + if allowed_group_names.size > 0 + if block || association + group_allowed?(group_map, allowed_group_names, association, &block) else true end else - unless @config.has_guard?(resource) - raise ::Ixtlan::Guard::GuardException.new("no guard config for '#{resource}'") + unless @config.has_guard?(resource_name) + raise ::Ixtlan::Guard::GuardException.new("no guard config for '#{resource_name}'") else false end end end - def permissions(current_groups, flavors = {}) + def group_allowed?(group_map, allowed_group_names, association, &block) + g = allowed_group_names.detect do |group_name| + block.call(group_map[group_name], association) + end if association && block + logger.debug do + if g + "found group #{g} for #{association}" + else + "no group found for #{association}" + end + end + g != nil + end + + def permissions(current_groups, &block) + group_map = group_map(current_groups) perms = [] m = @config.map_of_all m.each do |resource, actions| nodes = [] perm = Node.new(:permission) perm[:resource] = resource perm[:actions] = nodes - defaults = actions.delete('defaults') || [] - defaults = intersect(current_groups, defaults + @superuser) unless defaults.member?('*') - # no actions - # deny = false: !defaults.member?('*') - # deny = true: defaults.member?('*') || current_groups.member?(@superuser[0]) + default_actions = actions.delete('defaults') || [] + default_actions = group_map.keys & (default_actions + @superuser) unless default_actions.member?('*') deny = if actions.size == 0 - defaults.member?('*') || current_groups.member?(@superuser[0]) + # no actions + # deny = false: !default_actions.member?('*') + # deny = true: default_actions.member?('*') || current_group_names.member?(@superuser[0]) + default_actions.member?('*') || group_map.keys.member?(@superuser[0]) || !group_map.keys.detect {|g| default_actions.member? g }.nil? else # actions - # deny = false : defaults == [] - # deny = true : defaults.member?('*') - defaults.size != 0 || defaults.member?('*') + # deny = false : default_actions == [] + # deny = true : default_actions.member?('*') + default_actions.size != 0 || default_actions.member?('*') end perm[:deny] = deny actions.each do |action, groups| + group_names = groups.collect { |g| g.is_a?(Hash) ? g.keys : g }.flatten if groups node = Node.new(:action) allowed_groups = - if groups && groups.member?('*') - current_groups + if groups && group_names.member?('*') + group_map.values else - intersect(current_groups, (groups || []) + @superuser) + names = group_map.keys & ((group_names || []) + @superuser) + names.collect { |name| group_map[name] } end if (deny && allowed_groups.size == 0) || (!deny && allowed_groups.size > 0) node[:name] = action -# f = {} -# flavors.each do |fl, block| -# f[fl] = block.call(allowed_groups) -# end -# node[:flavors] = f if f.size > 0 + if block + if allowed_groups.size > 0 + node.content.merge!(block.call(resource, action, allowed_groups) || {}) + else + perm.content.merge!(block.call(resource, action, group_map.values) || {}) + end + end nodes << node end end + # TODO is that right like this ? + # only default_actions, i.e. no actions !!! + if block && actions.size == 0 && deny + perm.content.merge!(block.call(resource, nil, group_map.values) || {}) + end perms << perm end perms end - - def permission_map(current_groups, flavors = {}) - # TODO fix it - think first !! - perms = {} - m = @config.map_of_all - m.each do |resource, actions| - nodes = {} - actions.each do |action, groups| - if action == 'defaults' - nodes[action] = {} - else - allowed_groups = intersect(current_groups, (groups || []) + @superuser) - if allowed_groups.size > 0 - f = {} - flavors.each do |fl, block| - flav = block.call(allowed_groups) - f[fl] = flav if flav.size > 0 - end - nodes[action] = f - else - nodes[action] = nil # indicates not default action - end - end - end - perms[resource] = nodes if nodes.size > 0 - end - perms - end - - private - - def intersect(set1, set2) - set1 - (set1 - set2) - end end class Node < Hash - + + attr_reader :content + def initialize(name) map = super @content = {} merge!({ name => @content }) end