goz 0.0.3 → 0.1.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/.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
|
+
|