goz 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/HISTORY.rdoc +6 -0
- data/README.rdoc +2 -17
- data/TODO.md +16 -0
- data/goz.gemspec +5 -1
- data/lib/goz.rb +9 -25
- data/lib/goz/database.rb +10 -0
- data/lib/goz/database/migrations.rb +15 -9
- data/lib/goz/event.rb +78 -16
- data/lib/goz/event_type.rb +4 -4
- data/lib/goz/group.rb +121 -44
- data/lib/goz/group/base.rb +115 -0
- data/lib/goz/group/etc_group.rb +113 -0
- data/lib/goz/group/grouper.rb +153 -0
- data/lib/goz/group/grouper/stemmed_groups.rb +140 -0
- data/lib/goz/group/test_case.rb +200 -0
- data/lib/goz/group_service.rb +5 -10
- data/lib/goz/logger.rb +41 -72
- data/lib/goz/service.rb +50 -30
- data/lib/goz/service/base.rb +43 -0
- data/lib/goz/service/fake_service.rb +81 -0
- data/lib/goz/test_case.rb +26 -14
- data/lib/goz/user.rb +98 -37
- data/lib/goz/user/base.rb +81 -0
- data/lib/goz/user/etc_passwd.rb +56 -0
- data/lib/goz/user/ldap.rb +112 -0
- data/lib/goz/user/test_case.rb +55 -0
- data/lib/goz/version.rb +1 -1
- metadata +89 -45
- data/lib/goz/cache.rb +0 -136
- data/lib/goz/cache/hash_store.rb +0 -75
- data/test/test_admins.rb +0 -189
- data/test/test_cache.rb +0 -90
- data/test/test_event.rb +0 -576
- data/test/test_event_type.rb +0 -47
- data/test/test_goz.rb +0 -22
- data/test/test_group.rb +0 -180
- data/test/test_group_services.rb +0 -241
- data/test/test_hash_store_cash.rb +0 -42
- data/test/test_logger.rb +0 -93
- data/test/test_members.rb +0 -189
- data/test/test_service.rb +0 -150
- data/test/test_user.rb +0 -205
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'goz/service'
|
4
|
+
require 'goz/logger'
|
5
|
+
|
6
|
+
|
7
|
+
module Goz # :nodoc:
|
8
|
+
class Service # :nodoc:
|
9
|
+
|
10
|
+
#
|
11
|
+
# = Goz::Service::Base - TODO
|
12
|
+
#
|
13
|
+
# == Usage
|
14
|
+
#
|
15
|
+
# TODO
|
16
|
+
#
|
17
|
+
# == Author
|
18
|
+
#
|
19
|
+
# blair christensen. <mailto:blair.christensen@gmail.com>
|
20
|
+
#
|
21
|
+
# == Homepage
|
22
|
+
#
|
23
|
+
# https://github.com/blairc/goz/
|
24
|
+
#
|
25
|
+
class Base
|
26
|
+
|
27
|
+
TAG = self.name
|
28
|
+
|
29
|
+
@@cf = {}
|
30
|
+
|
31
|
+
|
32
|
+
#
|
33
|
+
# Set configuration.
|
34
|
+
#
|
35
|
+
def self.configuration(configuration)
|
36
|
+
@@cf = configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'goz/service/base'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
|
7
|
+
module Goz # :nodoc:
|
8
|
+
class Service # :nodoc:
|
9
|
+
|
10
|
+
#
|
11
|
+
# = Goz::Service:FakeService - TODO
|
12
|
+
#
|
13
|
+
# == Usage
|
14
|
+
#
|
15
|
+
# TODO
|
16
|
+
#
|
17
|
+
# == Author
|
18
|
+
#
|
19
|
+
# blair christensen. <mailto:blair.christensen@gmail.com>
|
20
|
+
#
|
21
|
+
# == Homepage
|
22
|
+
#
|
23
|
+
# https://github.com/blairc/goz/
|
24
|
+
#
|
25
|
+
class FakeService < Goz::Service::Base
|
26
|
+
|
27
|
+
FN = 'fake_service_database.yaml'
|
28
|
+
TAG = self.name
|
29
|
+
|
30
|
+
@@registry = nil
|
31
|
+
|
32
|
+
|
33
|
+
# XXX ALL UGLY HACKS!
|
34
|
+
def self.create(g)
|
35
|
+
Goz::Logger.debug TAG, "create( group.name=#{g.name} )"
|
36
|
+
load_registry
|
37
|
+
if @@registry.key? g.name
|
38
|
+
Goz::Logger.info TAG, "create( group.name=#{g.name} ) - group exists"
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
Goz::Logger.info TAG, "create( group.name=#{g.name} ) - creating group"
|
42
|
+
@@registry[ g.name ] = { :group => g.to_hash }
|
43
|
+
save_registry
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.load_registry
|
47
|
+
return @@registry unless @@registry.nil?
|
48
|
+
@@registry = File.exist?(FN) ? YAML.load_file(FN) : {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.save_registry
|
52
|
+
File.open(FN, 'w') { |fh| fh.write YAML.dump(@@registry) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.destroy(g)
|
56
|
+
Goz::Logger.debug TAG, "destroy( group.name=#{g.name} )"
|
57
|
+
load_registry
|
58
|
+
unless @@registry.key? g.name
|
59
|
+
Goz::Logger.info TAG, "destroy( group.name=#{g.name} ) - does not exist"
|
60
|
+
return true
|
61
|
+
end
|
62
|
+
Goz::Logger.info TAG, "destroy( group.name=#{g.name} ) - deleting group"
|
63
|
+
@@registry.delete g.name
|
64
|
+
save_registry
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.sync_group(g, s)
|
68
|
+
Goz::Logger.debug TAG, "sync_group( group.name=#{g.name}, service.name=#{s.name} )"
|
69
|
+
load_registry
|
70
|
+
create(g) unless @@registry.key? g.name
|
71
|
+
@@registry[ g.name ][ :admins ] = {}
|
72
|
+
@@registry[ g.name ][ :members ] = {}
|
73
|
+
g.admins.each { |u| @@registry[ g.name ][:admins][ u.login ] = u.to_hash }
|
74
|
+
g.members.each { |u| @@registry[ g.name ][:members][ u.login ] = u.to_hash }
|
75
|
+
save_registry
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
data/lib/goz/test_case.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'digest/sha1'
|
3
4
|
require 'goz/database'
|
4
5
|
require 'test/unit'
|
5
6
|
|
@@ -26,23 +27,34 @@ module Goz # :nodoc:
|
|
26
27
|
[ :groups, :services, :users ].each { |t| db[t].delete }
|
27
28
|
end
|
28
29
|
|
29
|
-
@groups = {
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
@groups = {}
|
31
|
+
[ :a, :b ].each do |sym|
|
32
|
+
@groups[sym] = { :display_name => "Group:#{ sym.to_s.upcase }",
|
33
|
+
:identifier => Digest::SHA1.hexdigest( sym.to_s ),
|
34
|
+
:klass => 'Goz::Group',
|
35
|
+
:name => "g#{ sym.to_s.upcase }"
|
36
|
+
}
|
37
|
+
end
|
33
38
|
|
34
|
-
@services = {
|
35
|
-
|
36
|
-
|
37
|
-
|
39
|
+
@services = {}
|
40
|
+
[ :a, :b ].each do |sym|
|
41
|
+
@services[sym] = { :name => "Service #{ sym.to_s.upcase }",
|
42
|
+
:klass => 'Goz::Service'
|
43
|
+
}
|
44
|
+
end
|
38
45
|
|
39
|
-
@users = {
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
@users = {}
|
47
|
+
[ :a, :b ].each do |sym|
|
48
|
+
@users[sym] = { :email => "#{ sym.to_s }@example.org",
|
49
|
+
:identifier => Digest::SHA1.hexdigest( sym.to_s ),
|
50
|
+
:klass => 'Goz::User',
|
51
|
+
:login => sym.to_s,
|
52
|
+
:name => "User #{ sym.to_s.upcase }"
|
53
|
+
}
|
54
|
+
end
|
43
55
|
end
|
44
56
|
|
45
|
-
end
|
57
|
+
end
|
46
58
|
|
47
|
-
end
|
59
|
+
end
|
48
60
|
|
data/lib/goz/user.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/inflector'
|
3
4
|
require 'goz/database'
|
4
5
|
require 'goz/event'
|
6
|
+
require 'goz/logger'
|
7
|
+
|
5
8
|
|
6
9
|
module Goz # :nodoc:
|
7
10
|
|
@@ -35,7 +38,6 @@ module Goz # :nodoc:
|
|
35
38
|
# https://github.com/blairc/goz/
|
36
39
|
#
|
37
40
|
class User < Sequel::Model
|
38
|
-
include Comparable
|
39
41
|
|
40
42
|
plugin :validation_helpers
|
41
43
|
|
@@ -55,76 +57,89 @@ module Goz # :nodoc:
|
|
55
57
|
:after_remove => proc { |u, g| Goz::Event.member_remove(g, u) }
|
56
58
|
|
57
59
|
|
60
|
+
ATTRIBUTES = [ :email, :identifier, :klass, :login, :name ]
|
61
|
+
TAG = self.name
|
62
|
+
|
63
|
+
@@api = Goz::User # XXX
|
64
|
+
|
65
|
+
|
58
66
|
#
|
59
67
|
# Initialize new (non-persistent) Goz::User object
|
60
68
|
#
|
61
|
-
def initialize(*params)
|
69
|
+
def initialize( *params )
|
62
70
|
super
|
63
71
|
yield self if block_given?
|
64
72
|
self
|
65
73
|
end
|
66
74
|
|
67
75
|
#
|
68
|
-
#
|
76
|
+
# TODO
|
69
77
|
#
|
70
|
-
def
|
71
|
-
if
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
self.name > other.name ||
|
79
|
-
self.identifier > other.identifier
|
80
|
-
1
|
81
|
-
else
|
82
|
-
0
|
83
|
-
end
|
78
|
+
def self.api( klass = nil, configuration = {} )
|
79
|
+
return @@api if klass.nil?
|
80
|
+
Goz::Logger.info TAG, "changing api from #{@@api} to #{klass}"
|
81
|
+
klass_name = klass.kind_of?(String) ? klass : klass.name
|
82
|
+
require klass_name.underscore
|
83
|
+
klass = klass.constantize if klass.kind_of?(String)
|
84
|
+
klass.configuration configuration
|
85
|
+
@@api = klass
|
84
86
|
end
|
85
87
|
|
86
88
|
#
|
87
|
-
#
|
89
|
+
# Find Goz::User by identifier or return +nil+
|
88
90
|
#
|
89
|
-
def self.
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
def self.find_by_identifier(identifier)
|
92
|
+
Goz::Logger.debug TAG, "find_by_identifier( identifier=#{identifier} )"
|
93
|
+
u = self.find :identifier => identifier
|
94
|
+
return u unless u.nil?
|
95
|
+
return nil if Goz::User == self.api
|
96
|
+
u = self.api.find_by_identifier identifier
|
97
|
+
return nil if u.nil?
|
98
|
+
begin
|
99
|
+
return self.find_or_create u.to_hash
|
100
|
+
rescue => e
|
101
|
+
Goz::Logger.error TAG, "find_by_identifier( identifier=#{identifier} ) => #{ e.to_s }"
|
93
102
|
end
|
94
|
-
|
103
|
+
return nil
|
95
104
|
end
|
96
105
|
|
97
106
|
#
|
98
107
|
# Find Goz::User by login or return +nil+
|
99
108
|
#
|
100
109
|
def self.find_by_login(login)
|
101
|
-
Goz::
|
102
|
-
|
103
|
-
|
110
|
+
Goz::Logger.debug TAG, "find_by_login( login=#{login} )"
|
111
|
+
u = self.find :login => login
|
112
|
+
return u unless u.nil?
|
113
|
+
return nil if Goz::User == self.api
|
114
|
+
u = self.api.find_by_login login
|
115
|
+
return nil if u.nil?
|
116
|
+
return self.find_or_create u.to_hash
|
104
117
|
end
|
105
118
|
|
106
119
|
#
|
107
120
|
# Synchronize user with external data sources (if relevant).
|
108
121
|
#
|
109
122
|
def sync(force = false)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
Goz::Event.user_sync(self)
|
117
|
-
return true
|
123
|
+
Goz::Logger.debug TAG, "#{self.login} - #sync( force=#{force} )"
|
124
|
+
if sync_user && sync_groups && sync_memberships
|
125
|
+
self.synchronized_at = Time.now
|
126
|
+
self.save
|
127
|
+
Goz::Event.user_sync(self)
|
128
|
+
return true
|
118
129
|
end
|
119
130
|
false
|
120
131
|
end
|
121
132
|
|
133
|
+
def to_hash
|
134
|
+
Hash[ ATTRIBUTES.map { |k| [ k, self[k] ] } ]
|
135
|
+
end
|
136
|
+
|
122
137
|
#
|
123
138
|
# Perform model valiations.
|
124
139
|
#
|
125
140
|
def validate
|
126
141
|
super
|
127
|
-
validates_presence [ :email, :identifier, :login, :name ]
|
142
|
+
validates_presence [ :email, :identifier, :klass, :login, :name ]
|
128
143
|
validates_type Time, [ :created_at, :modified_at, :synchronized_at ]
|
129
144
|
validates_unique [ :email, :identifier, :login ]
|
130
145
|
end
|
@@ -134,12 +149,12 @@ module Goz # :nodoc:
|
|
134
149
|
|
135
150
|
def after_destroy
|
136
151
|
super
|
137
|
-
Event.
|
152
|
+
Goz::Event.user_remove(self)
|
138
153
|
end
|
139
154
|
|
140
155
|
def after_create
|
141
156
|
super
|
142
|
-
Event.
|
157
|
+
Goz::Event.user_add(self)
|
143
158
|
end
|
144
159
|
|
145
160
|
def before_create
|
@@ -158,6 +173,52 @@ module Goz # :nodoc:
|
|
158
173
|
self.modified_at = Time.now
|
159
174
|
end
|
160
175
|
|
176
|
+
def klass_instance
|
177
|
+
return @@api if @@api.name == self.klass
|
178
|
+
unless @k
|
179
|
+
@k = self.klass.constantize
|
180
|
+
require self.klass.underscore
|
181
|
+
end
|
182
|
+
return @k
|
183
|
+
end
|
184
|
+
|
185
|
+
# Synchronize user groups with external data source
|
186
|
+
def sync_groups
|
187
|
+
Goz::Logger.debug TAG, "#{self.login} - #sync_groups()"
|
188
|
+
# TODO Does Sequel provide a better option for this?
|
189
|
+
t = Goz::Group.admin(self)
|
190
|
+
t.each { |_| self.add_group(_) unless self.groups.include?(_) }
|
191
|
+
self.groups.each { |_| self.remove_group(_) unless t.include?(_) }
|
192
|
+
# TODO Log! if modified?
|
193
|
+
true
|
194
|
+
end
|
195
|
+
|
196
|
+
# Synchronize user memberships with external data source
|
197
|
+
def sync_memberships
|
198
|
+
Goz::Logger.debug TAG, "#{self.login} - #sync_memberships()"
|
199
|
+
# TODO Does Sequel provide a better option for this?
|
200
|
+
t = Goz::Group.member(self)
|
201
|
+
t.each { |_| self.add_membership(_) unless self.memberships.include?(_) }
|
202
|
+
self.memberships.each { |_| self.remove_membership(_) unless t.include?(_) }
|
203
|
+
# TODO Log! if modified?
|
204
|
+
true
|
205
|
+
end
|
206
|
+
|
207
|
+
# Synchronize user with external data source
|
208
|
+
def sync_user
|
209
|
+
Goz::Logger.debug TAG, "#{self.login} - #sync_user()"
|
210
|
+
return true if Goz::User.name == self.klass
|
211
|
+
u = klass_instance.find_by_login self.login
|
212
|
+
return false if u.nil?
|
213
|
+
[ :email, :identifier, :login, :name ].each do |attr|
|
214
|
+
unless self[attr] == u[attr]
|
215
|
+
Goz::Logger.info TAG, "#{self.login} = #sync_user() - #{attr} changed"
|
216
|
+
self[attr] = u[attr]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
true
|
220
|
+
end
|
221
|
+
|
161
222
|
end # class User
|
162
223
|
|
163
224
|
end # module Goz
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'goz/logger'
|
4
|
+
require 'goz/user'
|
5
|
+
|
6
|
+
|
7
|
+
module Goz # :nodoc:
|
8
|
+
class User # :nodoc:
|
9
|
+
|
10
|
+
#
|
11
|
+
# = Goz::User::Base - TODO
|
12
|
+
#
|
13
|
+
# == Usage
|
14
|
+
#
|
15
|
+
# TODO
|
16
|
+
#
|
17
|
+
# == Author
|
18
|
+
#
|
19
|
+
# blair christensen. <mailto:blair.christensen@gmail.com>
|
20
|
+
#
|
21
|
+
# == Homepage
|
22
|
+
#
|
23
|
+
# https://github.com/blairc/goz/
|
24
|
+
#
|
25
|
+
class Base
|
26
|
+
|
27
|
+
TAG = self.name
|
28
|
+
|
29
|
+
attr_accessor :email, :identifier, :klass, :login, :name
|
30
|
+
|
31
|
+
@@cf = {}
|
32
|
+
|
33
|
+
|
34
|
+
#
|
35
|
+
# TODO
|
36
|
+
#
|
37
|
+
def [](key)
|
38
|
+
send key.to_sym
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Set configuration.
|
43
|
+
#
|
44
|
+
def self.configuration(configuration)
|
45
|
+
@@cf = configuration
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Find Goz::User by login or return +nil+.
|
50
|
+
#
|
51
|
+
# MUST be implemented by API extensions.
|
52
|
+
#
|
53
|
+
def self.find_by_login(login)
|
54
|
+
raise RuntimeError, "not implemented"
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Convert to Goz::User-style hash
|
59
|
+
#
|
60
|
+
def to_hash
|
61
|
+
return { :email => self.email,
|
62
|
+
:identifier => self.identifier,
|
63
|
+
:klass => self.klass,
|
64
|
+
:login => self.login,
|
65
|
+
:name => self.name
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# TODO
|
71
|
+
#
|
72
|
+
def to_s
|
73
|
+
"email=#{email} | identifier=#{identifier} | klass=#{klass} | login=#{login} | name=#{name}"
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|