id_please 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
data/id_please.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{id_please}
8
- s.version = "0.7.0"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["James Stuart"]
12
- s.date = %q{2010-03-01}
12
+ s.date = %q{2010-03-16}
13
13
  s.description = %q{Access control gem}
14
14
  s.email = %q{tastyhat@jamesstuart.org}
15
15
  s.extra_rdoc_files = [
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
35
35
  "lib/id_please/model_extensions/for_role.rb",
36
36
  "lib/id_please/model_extensions/for_subject.rb",
37
37
  "lib/id_please/model_extensions/for_user.rb",
38
+ "test/assignment_test.rb",
38
39
  "test/database.yml",
39
40
  "test/debug.log",
40
41
  "test/id_please_test.rb",
@@ -49,7 +50,8 @@ Gem::Specification.new do |s|
49
50
  s.rubygems_version = %q{1.3.5}
50
51
  s.summary = %q{Access control gem for rails}
51
52
  s.test_files = [
52
- "test/id_please_test.rb",
53
+ "test/assignment_test.rb",
54
+ "test/id_please_test.rb",
53
55
  "test/roles_test.rb",
54
56
  "test/support/models.rb",
55
57
  "test/support/schema.rb",
@@ -25,31 +25,38 @@ module IdPlease
25
25
 
26
26
  def initialize(*args)
27
27
  options = args.extract_options!
28
- options = {:direction => :down, :nested => true}.merge(options)
28
+ options = {:direction => :down, :nested => true, :members_only => false}.merge(options)
29
29
  @subjects = options[:subjects] # || raise("You must provide a subject")
30
30
  @subjects = [@subjects] unless @subjects.kind_of?(Array)
31
31
  @direction = options[:direction]
32
32
  @assign_class = options[:assignment_class] # || raise("You must provide the assignment class through :assignment_class")
33
33
  @nested = options[:nested]
34
34
  @member_role = options[:member_role] || :member
35
+ @members_only = options[:members_only]
35
36
  @assignments = []
36
37
  @calculated = false
37
38
  add_all_assignments(@subjects)
38
39
  end
39
40
 
40
41
  def add_all_assignments(subjects)
41
-
42
42
  @calculated = false
43
- if @direction == :down
44
- assignments = @assign_class.role_authorizable_eq(*subjects).all(:include => [:subject, {:role => :authorizable}])
45
-
46
- @assignments += assignments
43
+
44
+ search_proc = lambda { @direction == :down ? @assign_class.role_authorizable_eq(*subjects) : @assign_class.subject_eq(*subjects) }
45
+
46
+ search_with_role = lambda { |a| @members_only ? a.role_name_eq(@member_role.to_s) : a}
47
+
48
+ assignments = search_with_role.call(search_proc.call).all(:include => [:subject, {:role => :authorizable}])
49
+
50
+ @assignments += assignments
51
+
47
52
 
48
- if @nested
49
- subjects_to_search = assignments.collect(&:subject).select { |s| s._auth_is_group }
50
-
51
- add_all_assignments(subjects_to_search) unless subjects_to_search.empty?
53
+ if @nested
54
+ subjects_to_search = if @direction == :down
55
+ assignments.select { |a| a.role.name.to_sym == @member_role}.collect(&:subject).select { |s| s._auth_is_group }
56
+ else
57
+ assignments.select { |a| a.role.name.to_sym == @member_role}.collect { |a| a.role.authorizable }.select { |s| s.respond_to?(:_auth_is_group) && s._auth_is_group }
52
58
  end
59
+ add_all_assignments(subjects_to_search) unless subjects_to_search.empty?
53
60
  end
54
61
  end
55
62
 
@@ -100,6 +107,25 @@ module IdPlease
100
107
  return result
101
108
  end
102
109
 
110
+ def targets
111
+ calculate! unless @calculated
112
+ @targets = @assignment_links.collect(&:target).uniq
113
+ end
114
+
115
+
116
+ def targets_with_assignments
117
+ calculate! unless @calculated
118
+ result = Hash.new { |h,k| h[k] = Hash.new() }
119
+ @assignment_links.each do |a|
120
+ result[a.role][a.target] ||= []
121
+ result[a.role][a.target] << (a.via || a.subject)
122
+ end
123
+
124
+ result.each_key { |name| result[name].each_pair { |target,v| result[name][target] = v.compact.uniq }}
125
+ return result
126
+ end
127
+
128
+
103
129
  def map
104
130
  return self
105
131
  end
@@ -113,14 +139,16 @@ module IdPlease
113
139
 
114
140
  @assignment_links = []
115
141
 
116
- @assignments.each do |a|
142
+ @assignments.select { |a| !@members_only || a.role.name.to_sym == @member_role }.each do |a|
117
143
  al = AssignmentLink.new(:assignment => a)
118
144
  @assignment_links << al
119
145
  end
120
146
 
121
147
  @assignment_links.select { |al| al.role != @member_role }.each do |al|
148
+
122
149
  all_members_of(al.subject).each do |member|
123
- @assignment_links << AssignmentLink.new(:role => al.role, :target => al.subject, :subject => member, :via => al.subject)
150
+
151
+ @assignment_links << AssignmentLink.new(:role => al.role, :target => al.target, :subject => member, :via => al.subject)
124
152
  end
125
153
  end
126
154
 
@@ -28,38 +28,49 @@ module IdPlease
28
28
  all_groups.each { |group| self.not_in_group!(group) }
29
29
  end
30
30
 
31
+
32
+ def groups_with_assignments(*args)
33
+ options = args.extract_options!.merge(:view => :targets_with_assignments)
34
+ groups(options)
35
+ end
36
+
31
37
  def groups(*args)
32
38
  raise "Groups must be enabled for this model" unless _auth_groups_enabled
39
+
40
+ options = {:view => :targets}.merge(args.extract_options!)
41
+ view = options[:view]
42
+ valid_views = [:targets, :targets_with_assignments, :map]
43
+
33
44
 
34
- options = {:result => :list}.merge(args.extract_options!)
35
- group_hash = {}
45
+ raise "Invalid view argument, must be one of #{valid_views}" unless valid_views.include?(view)
46
+
47
+ members_only = if options.has_key?(:members_only)
48
+ options[:members_only]
49
+ else
50
+ view == :targets ? true : false
51
+ end
52
+
36
53
 
37
- all_groups = direct_parent_groups(self)
38
- all_groups.each { |g| group_hash[g] = [self]}
54
+ map = IdPlease::AssignmentMap.new(:assignment_class => _auth_assign_class, :direction => :up, :subjects => self, :members_only => members_only, :nested => _auth_nested_groups && options[:nested] != false)
55
+
39
56
 
57
+ return map.send(view)
58
+
59
+ options = args.extract_options!
60
+ all_groups = direct_parent_groups(self)
40
61
 
41
62
  if _auth_nested_groups && options[:nested] != false
42
63
  infinite_loop_counter = 25
43
64
  to_find = all_groups.dup
44
65
 
45
66
  until to_find.empty? || (infinite_loop_counter -=1) <= 0
46
- all_child_groups = []
47
- to_find.each do |parent_group|
48
- child_groups = direct_parent_groups(parent_group)
49
- child_groups.each { |g| group_hash.has_key?(g) ? group_hash[g] << parent_group : group_hash[g] = [parent_group]}
50
- all_child_groups += child_groups
51
- end
52
- all_child_groups.uniq!
53
- all_groups += all_child_groups
54
- to_find = all_child_groups
67
+ to_find = direct_parent_groups(*to_find)
68
+ all_groups += to_find
55
69
  end
56
- end
57
-
58
- case options[:result]
59
- when :list
70
+
60
71
  all_groups.uniq
61
- when :hash
62
- group_hash
72
+ else
73
+ all_groups
63
74
  end
64
75
  end
65
76
 
@@ -133,7 +144,7 @@ module IdPlease
133
144
 
134
145
  def self_and_groups
135
146
  if _auth_groups_enabled
136
- groups << self
147
+ groups(:members_only => false) << self
137
148
  else
138
149
  [self]
139
150
  end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ class AssignmentTest < ActiveSupport::TestCase
4
+ context "given users and groups" do
5
+ setup do
6
+ @user_a = User.create!(:name => "Alice")
7
+ @user_b = User.create!(:name => "Bob")
8
+ @user_c = User.create!(:name => "Charles")
9
+ @group_execs = Group.create!(:name => "Executives")
10
+ @group_company = Group.create!(:name => "Company")
11
+ @group_division = Group.create!(:name => "Division")
12
+
13
+ @user_a.in_group!(@group_execs)
14
+ @group_execs.has_role!(:owner, @group_division)
15
+ @group_division.in_group!(@group_company)
16
+ @group_execs.in_group!(@group_company)
17
+
18
+ end
19
+
20
+ should "make an Assignment Map" do
21
+ map = IdPlease::AssignmentMap.new(:assignment_class => Assignment, :direction => :up, :subjects => @user_a)
22
+ assert_kind_of IdPlease::AssignmentMap, map
23
+
24
+
25
+
26
+ end
27
+
28
+ should "handle groups, even nested" do
29
+ assert_same_elements @user_a.groups, [@group_execs, @group_company]
30
+ assert_same_elements_in_hash @user_a.groups_with_assignments(:members_only => true)[:member], {@group_execs => [@user_a], @group_company => [@group_execs]}
31
+ assert_same_elements_in_hash @user_a.groups_with_assignments(:members_only => false)[:member], {@group_execs => [@user_a], @group_company => [@group_execs]}
32
+
33
+ assert_same_elements_in_hash @user_a.groups_with_assignments(:members_only => true)[:owner], {}
34
+ assert_same_elements_in_hash @user_a.groups_with_assignments(:members_only => false)[:owner], {@group_division => [@group_execs]}
35
+
36
+ end
37
+ end
38
+ end