id_please 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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