ixtlan-user-management 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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