ixtlan-user-management 0.2.0 → 0.3.1

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.
@@ -58,13 +58,13 @@ module Ixtlan
58
58
  end
59
59
 
60
60
  def group_for( model, login )
61
- model.new('name' => login.sub( /\[.*/, '' ) )
61
+ model.new('name' => login.sub( /\[.*/, '' ), 'associations'=> split( login ) )
62
62
  end
63
63
 
64
64
  def split( login )
65
- login.sub( /.*\[/ , '' ).sub( /\].*/, '' ).split( /,/ )
65
+ login.sub( /.*\[/ , '' ).sub( /\].*/, '' ).split( /,/ ) if login.match /.+\[/
66
66
  end
67
67
 
68
68
  end
69
69
  end
70
- end
70
+ end
@@ -25,7 +25,7 @@ module Ixtlan
25
25
  include Virtus
26
26
 
27
27
  attribute :name, String
28
- attribute :associations, Array[Object]
28
+ attribute :associations, Array[Object], :default => nil
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -29,32 +29,58 @@ module Ixtlan
29
29
  :delete => 'delete'
30
30
  }
31
31
 
32
- def allow?( resource ,method, association = nil )
33
- perm = permissions( resource )
34
- (perm.associations.empty? ||
35
- perm.associations.include?( association.to_s ) ) &&
36
- perm.allow?( METHODS[ method ] ) #TODO, associations )
32
+ def allow?( resource, method, association = nil )
33
+ perms = permissions[ resource ] || []
34
+ perms.one? do |perm|
35
+ ( perm.associations.nil? ||
36
+ perm.associations.include?( association.to_s ) ) &&
37
+ perm.allow?( METHODS[ method ], association )
38
+ end
37
39
  end
38
40
 
39
- def associations( resource, method )
40
- perm = permissions( resource )
41
- unless perm.associations.empty?
42
- perm.associations
41
+ def associations( resource, method = nil )
42
+ perms = permissions[ resource ] || []
43
+ asso = perms.select { |perm| perm.associations }
44
+ if asso.empty?
45
+ nil
46
+ else
47
+ asso.collect{ |perm| perm.associations }.flatten
43
48
  end
44
49
  # TODO method
45
50
  end
46
51
 
52
+ def check_parent( resource, parent_resource )
53
+ perms = permissions[ resource ]
54
+ if perms
55
+ perms.each do |perm|
56
+ if perm.parent && perm.parent.resource != parent_resource
57
+ raise 'parent resource is not guarded'
58
+ end
59
+ end
60
+ end
61
+ end
62
+
47
63
  def all_permissions
48
- @permissions.values
64
+ permissions.values.flatten.select { |pp| pp.parent.nil? }
49
65
  end
50
66
 
51
- def permissions( resource )
67
+ def permissions
52
68
  @permissions ||= {}
53
- @permissions[ resource ] ||= Permission.new( :resource => resource )
69
+ end
70
+
71
+ def permissions_new( resource )
72
+ pp = Permission.new( :resource => resource )
73
+ ( permissions[ resource ] ||= [] ) << pp
74
+ pp
54
75
  end
55
76
 
56
- def permission( resource, *associations, &block )
57
- current = permissions( resource )
77
+ def permission_for( resource, *associations, &block )
78
+ current = permissions_new( resource )
79
+ associations.flatten!
80
+ if associations.first.is_a? Permission
81
+ current.parent = associations.first
82
+ associations = associations[ 1..-1 ]
83
+ end
58
84
  current.associations = associations unless associations.empty?
59
85
  block.call current if block
60
86
  current
@@ -26,7 +26,7 @@ module Ixtlan
26
26
 
27
27
  attribute :verb, String
28
28
  attribute :name, String
29
- # attribute :associations, Array[String]
29
+ attribute :associations, Array[String], :default => nil
30
30
  end
31
31
  class Permission
32
32
  include Virtus
@@ -36,40 +36,77 @@ module Ixtlan
36
36
  :allow_update,
37
37
  :allow_delete ]
38
38
 
39
+ attribute :parent, Permission
40
+ attribute :children, Array[Permission]
39
41
  attribute :resource, String
40
42
  attribute :actions, Array[Action], :default => []
41
43
  attribute :allow, Boolean, :default => true
42
- attribute :associations, Array[String]
43
-
44
- def allow?( method )#TODO, association = nil )
44
+ attribute :associations, Array[String], :default => nil
45
+
46
+ def parent=( pt )
47
+ super
48
+ if pt
49
+ pt.children << self
50
+ elsif parent
51
+ parent.children.delete self
52
+ end
53
+ end
54
+
55
+ def allow?( method, association = nil )
45
56
  action = self.actions.detect { |a| a.name == method }
46
57
  if self.allow
47
- ! action.nil? #TODO && ( associations.nil || action.associations.include?( association ) )
58
+ action != nil && ( action.associations.nil? || action.associations.include?( association ) )
48
59
  else
49
60
  action.nil? #TODO associations
50
61
  end
51
62
  end
52
63
 
53
- def allow_all
64
+ def allow_all( *associations )
54
65
  self.allow = false
55
66
  self.actions.clear
67
+ set_asso( self, *associations )
68
+ self
56
69
  end
57
70
 
71
+ def set_asso( obj, *associations )
72
+ case associations.first
73
+ when NilClass
74
+ # leave default
75
+ when Array
76
+ # assume empty
77
+ obj.associations = associations.flatten
78
+ else
79
+ obj.associations = associations
80
+ end
81
+ end
82
+
58
83
  def deny_all
59
84
  self.allow = true
60
85
  self.actions.clear
86
+ self
61
87
  end
62
88
 
63
89
  def allow_mutate( *associations )
64
90
  allow_retrieve( *associations )
65
91
  allow_create( *associations )
66
92
  allow_update( *associations )
93
+ self
67
94
  end
68
95
 
69
96
  def method_missing( method, *args )
70
97
  if METHODS.include?( method )
71
- actions << Action.new( :name => method.to_s.sub( /allow_/, '' ),
72
- :associations => args )
98
+ a = Action.new( :name => method.to_s.sub( /allow_/, '' ) )
99
+ set_asso( a, *args )
100
+ self.actions << a
101
+ self
102
+ elsif METHODS.include?( method.to_s.sub( /_verb$/, '' ).to_sym )
103
+ verb = args.first
104
+ args = args[ 1..-1 ]
105
+ a = Action.new( :name => method.to_s.gsub( /allow_|_verb/, '' ),
106
+ :verb => verb )
107
+ set_asso( a, *args )
108
+ self.actions << a
109
+ self
73
110
  else
74
111
  super
75
112
  end
@@ -25,19 +25,22 @@ module Ixtlan
25
25
 
26
26
  root 'session'
27
27
 
28
- add_context( :single,
29
- :only => [],
30
- :methods => [:idle_session_timeout ],
31
- :include => {
32
- :user => {
33
- :only => [],
34
- :methods => [ :id, :login, :name ]
35
- },
36
- :permissions => {
37
- :include => [ :actions, :associations ]
38
- }
39
- } )
40
-
28
+ PERM = [ :resource,
29
+ :allow,
30
+ :associations ]
31
+ ACTION = only( :name,
32
+ :verb,
33
+ :associations )
34
+
35
+ add_context( :single ) do
36
+ only( :idle_session_timeout,
37
+ :user => only( :id, :login, :name ),
38
+ :permissions => only( PERM,
39
+ :actions => ACTION,
40
+ :children => only( PERM,
41
+ :actions => ACTION ) ) )
42
+
43
+ end
41
44
  end
42
45
  end
43
46
  end
@@ -23,15 +23,12 @@ module Ixtlan
23
23
  module UserManagement
24
24
  class UserSerializer < Ixtlan::Babel::Serializer
25
25
 
26
- add_context(:session,
27
- :only => [],
28
- :methods => [:login, :name],
29
- :include=> {
30
- :groups => {
31
- :only => [],
32
- :methods => [:name]
33
- }
34
- })
26
+ add_context( :session ) do
27
+ only( :login,
28
+ :name,
29
+ :groups => only( :name,
30
+ :associations ) )
31
+ end
35
32
  end
36
33
  end
37
34
  end
@@ -22,7 +22,7 @@ describe Ixtlan::UserManagement::Guard do
22
22
 
23
23
  before do
24
24
  %w( audits errors configuration ).each do |resource|
25
- subject.permission( resource ).deny_all
25
+ subject.permission_for( resource ).deny_all
26
26
  end
27
27
  end
28
28
 
@@ -79,7 +79,7 @@ describe Ixtlan::UserManagement::Guard do
79
79
  %w( audits errors configuration ).each do |resource|
80
80
  [ 'domain', nil ].each do |asso|
81
81
  expected = Ixtlan::UserManagement::Guard::METHODS[ m ]
82
- subject.allow?( resource, m, asso ).must_equal (expected == meth)
82
+ subject.allow?( resource, m, asso ).must_equal(expected == meth)
83
83
  end
84
84
  end
85
85
  end
@@ -90,8 +90,27 @@ describe Ixtlan::UserManagement::Guard do
90
90
  p.send method
91
91
  p.associations = [ 'domain', 'nodomain' ]
92
92
  end
93
-
93
+
94
+ [ :get, :post, :put, :delete ].each do |m|
95
+ %w( audits errors configuration ).each do |resource|
96
+ [ 'something', nil ].each do |asso|
97
+ subject.allow?( resource, m, asso ).must_equal false
98
+ end
99
+ end
100
+ end
94
101
  meth = method.to_s.sub( /allow_/, '' )
102
+ [ :get, :post, :put, :delete ].each do |m|
103
+ %w( audits errors configuration ).each do |resource|
104
+ expected = Ixtlan::UserManagement::Guard::METHODS[ m ]
105
+ subject.allow?( resource, m, 'domain' ).must_equal(expected == meth)
106
+ end
107
+ end
108
+ end
109
+ it "#{method.to_s.sub( /_/, 's ')} with action with associations" do
110
+ subject.all_permissions.each do |p|
111
+ p.send method, 'domain', 'nodomain'
112
+ end
113
+
95
114
  [ :get, :post, :put, :delete ].each do |m|
96
115
  %w( audits errors configuration ).each do |resource|
97
116
  [ 'something', nil ].each do |asso|
@@ -99,10 +118,11 @@ describe Ixtlan::UserManagement::Guard do
99
118
  end
100
119
  end
101
120
  end
121
+ meth = method.to_s.sub( /allow_/, '' )
102
122
  [ :get, :post, :put, :delete ].each do |m|
103
123
  %w( audits errors configuration ).each do |resource|
104
124
  expected = Ixtlan::UserManagement::Guard::METHODS[ m ]
105
- subject.allow?( resource, m, 'domain' ).must_equal (expected == meth)
125
+ subject.allow?( resource, m, 'domain' ).must_equal(expected == meth)
106
126
  end
107
127
  end
108
128
  end
@@ -25,8 +25,8 @@ describe Ixtlan::UserManagement::SessionManager do
25
25
  expected = {
26
26
  "login"=>"root",
27
27
  "name"=>"Root",
28
- "groups"=>[{"name"=>"root"},
29
- {"name"=>"admin"}]
28
+ "groups"=>[{"name"=>"root", "associations"=>nil},
29
+ {"name"=>"admin", "associations"=>nil}]
30
30
  }
31
31
 
32
32
  data = subject.to_session( user )
@@ -43,9 +43,57 @@ describe Ixtlan::UserManagement::Session do
43
43
  result.must_equal expected
44
44
  end
45
45
 
46
+ it 'serializes with associations' do
47
+ guard.permission_for( 'audits' ).allow_all( 12,123 )
48
+
49
+ subject.permissions = guard.all_permissions
50
+
51
+ expected = {
52
+ "session"=>{"idle_session_timeout"=>30,
53
+ "user"=>{
54
+ "id"=>1,
55
+ "login"=>"root",
56
+ "name"=>"Root"
57
+ },
58
+ "permissions"=>[{ "children" => [],
59
+ "resource"=>"audits",
60
+ "actions"=>[],
61
+ "allow"=>false,
62
+ "associations"=>["12", "123"]}]
63
+ }
64
+ }
65
+ result = factory.new_serializer( subject ).to_hash
66
+ result.must_equal expected
67
+ end
68
+
69
+ it 'serializes with empty associations' do
70
+ guard.permission_for( 'audits' ).allow_retrieve( [] )
71
+
72
+ subject.permissions = guard.all_permissions
73
+
74
+ expected = {
75
+ "session"=>{"idle_session_timeout"=>30,
76
+ "user"=>{
77
+ "id"=>1,
78
+ "login"=>"root",
79
+ "name"=>"Root"
80
+ },
81
+ "permissions"=>[{ "children" => [],
82
+ "resource"=>"audits",
83
+ "actions"=>[{ "verb"=>nil,
84
+ "name"=>"retrieve",
85
+ "associations"=>[] }],
86
+ "allow"=>true,
87
+ "associations"=>nil}]
88
+ }
89
+ }
90
+ result = factory.new_serializer( subject ).to_hash
91
+ result.must_equal expected
92
+ end
93
+
46
94
  it 'serializes with root permissions' do
47
95
  %w( audits errors configuration ).each do |resource|
48
- guard.permission( resource ).allow_all
96
+ guard.permission_for( resource ).allow_all
49
97
  end
50
98
 
51
99
  subject.permissions = guard.all_permissions
@@ -57,18 +105,21 @@ describe Ixtlan::UserManagement::Session do
57
105
  "login"=>"root",
58
106
  "name"=>"Root"
59
107
  },
60
- "permissions"=>[{"resource"=>"audits",
108
+ "permissions"=>[{ "children" => [],
109
+ "resource"=>"audits",
61
110
  "actions"=>[],
62
111
  "allow"=>false,
63
- "associations"=>[]},
64
- {"resource"=>"errors",
112
+ "associations"=>nil},
113
+ { "children" => [],
114
+ "resource"=>"errors",
65
115
  "actions"=>[],
66
116
  "allow"=>false,
67
- "associations"=>[]},
68
- {"resource"=>"configuration",
117
+ "associations"=>nil},
118
+ { "children" => [],
119
+ "resource"=>"configuration",
69
120
  "actions"=>[],
70
121
  "allow"=>false,
71
- "associations"=>[]}
122
+ "associations"=>nil}
72
123
  ]
73
124
  }
74
125
  }
@@ -77,10 +128,10 @@ describe Ixtlan::UserManagement::Session do
77
128
  end
78
129
 
79
130
  it 'serializes with some permissions' do
80
- guard.permission( 'audits' ).allow_retrieve
81
- guard.permission( 'errors' ).allow_create
82
- guard.permission( 'configuration' ).allow_update
83
- guard.permission( 'users' ).allow_delete
131
+ guard.permission_for( 'audits' ).allow_retrieve
132
+ guard.permission_for( 'errors' ).allow_create
133
+ guard.permission_for( 'configuration' ).allow_update
134
+ guard.permission_for( 'users' ).allow_delete
84
135
 
85
136
  subject.permissions = guard.all_permissions
86
137
 
@@ -91,26 +142,34 @@ describe Ixtlan::UserManagement::Session do
91
142
  "login"=>"root",
92
143
  "name"=>"Root"
93
144
  },
94
- "permissions"=>[{"resource"=>"audits",
95
- "actions"=>[{"verb"=>nil,
96
- "name"=>"retrieve"}],
145
+ "permissions"=>[{ "children" => [],
146
+ "resource"=>"audits",
147
+ "actions"=>[{ "verb" => nil,
148
+ "name"=>"retrieve",
149
+ "associations"=>nil}],
97
150
  "allow"=>true,
98
- "associations"=>[]},
99
- {"resource"=>"errors",
100
- "actions"=>[{"verb"=>nil,
101
- "name"=>"create"}],
151
+ "associations"=>nil},
152
+ { "children" => [],
153
+ "resource"=>"errors",
154
+ "actions"=>[{ "verb" => nil,
155
+ "name"=>"create",
156
+ "associations"=>nil}],
102
157
  "allow"=>true,
103
- "associations"=>[]},
104
- {"resource"=>"configuration",
105
- "actions"=>[{"verb"=>nil,
106
- "name"=>"update"}],
158
+ "associations"=>nil},
159
+ { "children" => [],
160
+ "resource"=>"configuration",
161
+ "actions"=>[{ "verb" => nil,
162
+ "name"=>"update",
163
+ "associations"=>nil}],
107
164
  "allow"=>true,
108
- "associations"=>[]},
109
- {"resource"=>"users",
110
- "actions"=>[{"verb"=>nil,
111
- "name"=>"delete"}],
165
+ "associations"=>nil},
166
+ { "children" => [],
167
+ "resource"=>"users",
168
+ "actions"=>[{ "verb" => nil,
169
+ "name"=>"delete",
170
+ "associations"=>nil}],
112
171
  "allow"=>true,
113
- "associations"=>[]}
172
+ "associations"=>nil}
114
173
  ]
115
174
  }
116
175
  }
@@ -119,8 +178,8 @@ describe Ixtlan::UserManagement::Session do
119
178
  end
120
179
 
121
180
  it 'serializes permissions with assoications' do
122
- guard.permission( 'audits', 'domain' ).allow_mutate
123
- guard.permission( 'users', 'nodomain', 'domain' ).allow_delete
181
+ guard.permission_for( 'audits', 'domain' ).allow_mutate
182
+ guard.permission_for( 'users', 'nodomain', 'domain' ).allow_delete
124
183
 
125
184
  subject.permissions = guard.all_permissions
126
185
 
@@ -131,18 +190,24 @@ describe Ixtlan::UserManagement::Session do
131
190
  "login"=>"root",
132
191
  "name"=>"Root"
133
192
  },
134
- "permissions"=>[{"resource"=>"audits",
135
- "actions"=>[{"verb"=>nil,
136
- "name"=>"retrieve"},
137
- {"verb"=>nil,
138
- "name"=>"create"},
139
- {"verb"=>nil,
140
- "name"=>"update"}],
193
+ "permissions"=>[{ "children" => [],
194
+ "resource"=>"audits",
195
+ "actions"=>[{ "verb" => nil,
196
+ "name"=>"retrieve",
197
+ "associations"=>nil},
198
+ { "verb" => nil,
199
+ "name"=>"create",
200
+ "associations"=>nil},
201
+ { "verb" => nil,
202
+ "name"=>"update",
203
+ "associations"=>nil}],
141
204
  "allow"=>true,
142
205
  "associations"=>["domain"]},
143
- {"resource"=>"users",
144
- "actions"=>[{"verb"=>nil,
145
- "name"=>"delete"}],
206
+ { "children" => [],
207
+ "resource"=>"users",
208
+ "actions"=>[{ "verb" => nil,
209
+ "name"=>"delete",
210
+ "associations"=>nil}],
146
211
  "allow"=>true,
147
212
  "associations"=>["nodomain", "domain"]}
148
213
  ]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ixtlan-user-management
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-03 00:00:00.000000000 Z
12
+ date: 2013-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -219,6 +219,22 @@ dependencies:
219
219
  none: false
220
220
  prerelease: false
221
221
  type: :development
222
+ - !ruby/object:Gem::Dependency
223
+ name: ixtlan-babel
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - '>='
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ none: false
230
+ requirement: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - '>='
233
+ - !ruby/object:Gem::Version
234
+ version: '0'
235
+ none: false
236
+ prerelease: false
237
+ type: :development
222
238
  - !ruby/object:Gem::Dependency
223
239
  name: json
224
240
  version_requirements: !ruby/object:Gem::Requirement