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 +1 -1
- data/id_please.gemspec +5 -3
- data/lib/id_please/assignment_map.rb +40 -12
- data/lib/id_please/model_extensions/for_subject.rb +31 -20
- data/test/assignment_test.rb +38 -0
- data/test/debug.log +222903 -0
- data/test/roles_test.rb +19 -9
- metadata +4 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
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.
|
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-
|
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/
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
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
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
47
|
-
|
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
|
-
|
57
|
-
|
58
|
-
case options[:result]
|
59
|
-
when :list
|
70
|
+
|
60
71
|
all_groups.uniq
|
61
|
-
|
62
|
-
|
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
|