nakamura 0.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.
- data/lib/nakamura/authz.rb +93 -0
- data/lib/nakamura/contacts.rb +83 -0
- data/lib/nakamura/file.rb +81 -0
- data/lib/nakamura/full_group_creator.rb +290 -0
- data/lib/nakamura/message.rb +46 -0
- data/lib/nakamura/search.rb +39 -0
- data/lib/nakamura/test.rb +92 -0
- data/lib/nakamura/users.rb +312 -0
- data/lib/nakamura.rb +412 -0
- metadata +55 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'test/unit.rb'
|
2
|
+
require 'nakamura'
|
3
|
+
require 'nakamura/users'
|
4
|
+
require 'nakamura/file'
|
5
|
+
require 'nakamura/search'
|
6
|
+
require 'tempfile'
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
module SlingTest
|
10
|
+
|
11
|
+
@@log_level = Logger::DEBUG
|
12
|
+
|
13
|
+
def SlingTest.setLogLevel(level)
|
14
|
+
@@log_level = level
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup
|
18
|
+
@s = SlingInterface::Sling.new()
|
19
|
+
@um = SlingUsers::UserManager.new(@s)
|
20
|
+
@search = SlingSearch::SearchManager.new(@s)
|
21
|
+
@created_nodes = []
|
22
|
+
@created_users = []
|
23
|
+
@created_groups = []
|
24
|
+
@delete = true
|
25
|
+
@log = Logger.new(STDOUT)
|
26
|
+
@log.level = @@log_level
|
27
|
+
end
|
28
|
+
|
29
|
+
def teardown
|
30
|
+
if ( @delete ) then
|
31
|
+
@s.switch_user(SlingUsers::User.admin_user)
|
32
|
+
@created_nodes.reverse.each { |n| @s.delete_node(n) }
|
33
|
+
@created_groups.each { |g| @um.delete_group(g) }
|
34
|
+
@created_users.each { |u| @um.delete_user(u.name) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_node(path, props={})
|
39
|
+
#puts "Path is #{path}"
|
40
|
+
res = @s.create_node(path, props)
|
41
|
+
assert_not_equal("500", res.code, "Expected to be able to create node "+res.body)
|
42
|
+
@created_nodes << path
|
43
|
+
return path
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_file_node(path, fieldname, filename, data, content_type="text/plain")
|
47
|
+
res = @s.create_file_node(path, fieldname, filename, data, content_type)
|
48
|
+
@created_nodes << path unless @created_nodes.include?(path)
|
49
|
+
return res
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_user(username, firstname = nil, lastname = nil)
|
53
|
+
u = @um.create_user(username, firstname, lastname)
|
54
|
+
assert_not_nil(u, "Expected user to be created: #{username}")
|
55
|
+
@created_users << u
|
56
|
+
return u
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_test_user(i)
|
60
|
+
u = @um.create_test_user(i)
|
61
|
+
assert_not_nil(u, "Expected user to be created: #{i}")
|
62
|
+
@created_users << u
|
63
|
+
return u
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_group(groupname, title = nil)
|
67
|
+
g = @um.create_group(groupname, title)
|
68
|
+
assert_not_nil(g, "Expected group to be created: #{groupname}")
|
69
|
+
@created_groups << groupname
|
70
|
+
return g
|
71
|
+
end
|
72
|
+
|
73
|
+
def wait_for_indexer()
|
74
|
+
magic_content = "#{Time.now().to_i}_#{rand(1000).to_s}"
|
75
|
+
filename = "wait_for_indexer_#{magic_content}"
|
76
|
+
|
77
|
+
fm = SlingFile::FileManager.new(@s)
|
78
|
+
fm.upload_pooled_file(filename, magic_content, 'text/plain')
|
79
|
+
|
80
|
+
# Give the indexer up to 20 seconds to catch up, but stop waiting early if
|
81
|
+
# we find our test item has landed in the index.
|
82
|
+
20.times do
|
83
|
+
res = @s.execute_get(@s.url_for("/var/search/files/allfiles.json?q=#{filename}"))
|
84
|
+
if JSON.parse(res.body)["total"] != 0
|
85
|
+
break
|
86
|
+
end
|
87
|
+
sleep(1)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,312 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'digest/sha1'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
$USERMANAGER_URI="system/userManager/"
|
7
|
+
$GROUP_URI="#{$USERMANAGER_URI}group.create.html"
|
8
|
+
$USER_URI="#{$USERMANAGER_URI}user.create.html"
|
9
|
+
$DEFAULT_PASSWORD="testuser"
|
10
|
+
|
11
|
+
module SlingUsers
|
12
|
+
|
13
|
+
class Principal
|
14
|
+
|
15
|
+
attr_accessor :name
|
16
|
+
|
17
|
+
def initialize(name)
|
18
|
+
@name = name
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# Get the public path for a user
|
23
|
+
def public_path_for(sling)
|
24
|
+
return home_path_for(sling) + "/public"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get the private path for a user
|
28
|
+
def private_path_for(sling)
|
29
|
+
return home_path_for(sling) + "/private"
|
30
|
+
end
|
31
|
+
|
32
|
+
def message_path_for(sling,messageid,mailbox)
|
33
|
+
#return home_path_for(sling) + "/message/"+messageid[0,2]+"/"+messageid[2,2]+"/"+messageid[4,2]+"/"+messageid[6,2]+"/"+messageid
|
34
|
+
return home_path_for(sling) + "/message/#{mailbox}/#{messageid}"
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
class Group < Principal
|
41
|
+
def to_s
|
42
|
+
return "Group: #{@name}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_properties(sling, props)
|
46
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"), props)
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_member(sling, principal, type)
|
50
|
+
principal_path = "/#{$USERMANAGER_URI}#{type}/#{principal}"
|
51
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
52
|
+
{ ":member" => principal_path })
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_members(sling, principals)
|
56
|
+
principal_paths = principals.collect do |principal|
|
57
|
+
if principal.index("g-") == 0
|
58
|
+
type = "group"
|
59
|
+
else
|
60
|
+
type = "user"
|
61
|
+
end
|
62
|
+
"/#{$USERMANAGER_URI}#{type}/#{principal}"
|
63
|
+
end
|
64
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
65
|
+
{ ":member" => principal_paths })
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_manager(sling, principal)
|
69
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
70
|
+
{ ":manager" => principal })
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_viewer(sling, principal)
|
74
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
75
|
+
{ ":viewer" => principal })
|
76
|
+
end
|
77
|
+
|
78
|
+
def details(sling)
|
79
|
+
return sling.get_node_props(group_url)
|
80
|
+
end
|
81
|
+
|
82
|
+
def remove_member(sling, principal, type)
|
83
|
+
principal_path = "/#{$USERMANAGER_URI}#{type}/#{principal}"
|
84
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
85
|
+
{ ":member@Delete" => principal_path })
|
86
|
+
end
|
87
|
+
|
88
|
+
def has_member(sling, principal)
|
89
|
+
detail = self.details(sling)
|
90
|
+
members = detail["members"]
|
91
|
+
if (members == nil)
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
return members.include?(principal)
|
95
|
+
end
|
96
|
+
|
97
|
+
def remove_member_viewer(sling, principal)
|
98
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
99
|
+
{ ":member@Delete" => principal, ":viewer@Delete" => principal })
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_member_viewer(sling, principal)
|
103
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
104
|
+
{ ":member" => principal, ":viewer" => principal })
|
105
|
+
end
|
106
|
+
|
107
|
+
def remove_manager(sling, principal)
|
108
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
109
|
+
{ ":manager@Delete" => principal })
|
110
|
+
end
|
111
|
+
|
112
|
+
def remove_viewer(sling, principal)
|
113
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
114
|
+
{ ":viewer@Delete" => principal })
|
115
|
+
end
|
116
|
+
|
117
|
+
def remove_members(sling, principals)
|
118
|
+
principal_paths = principals.collect do |principal|
|
119
|
+
if principal.index("g-") == 0
|
120
|
+
type = "group"
|
121
|
+
else
|
122
|
+
type = "user"
|
123
|
+
end
|
124
|
+
"/#{$USERMANAGER_URI}#{type}/#{principal}"
|
125
|
+
end
|
126
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"),
|
127
|
+
{ ":member@Delete" => principal_paths })
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_joinable(sling, joinable)
|
131
|
+
return sling.execute_post(sling.url_for("#{group_url}.update.html"), "sakai:joinable" => joinable)
|
132
|
+
end
|
133
|
+
|
134
|
+
def members(sling)
|
135
|
+
props = sling.get_node_props(group_url)
|
136
|
+
return props["members"]
|
137
|
+
end
|
138
|
+
|
139
|
+
# Get the home folder of a group.
|
140
|
+
def home_path_for(sling)
|
141
|
+
return "/~#{@name}"
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.url_for(name)
|
145
|
+
return "#{$USERMANAGER_URI}group/#{name}"
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def group_url
|
150
|
+
return Group.url_for(@name)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
class User < Principal
|
156
|
+
attr_accessor :password
|
157
|
+
|
158
|
+
def initialize(username, password=$DEFAULT_PASSWORD)
|
159
|
+
super(username)
|
160
|
+
@password = password
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.admin_user
|
164
|
+
return User.new("admin", "admin")
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.anonymous
|
168
|
+
return AnonymousUser.new
|
169
|
+
end
|
170
|
+
|
171
|
+
def do_request_auth(req)
|
172
|
+
req.basic_auth(@name, @password)
|
173
|
+
end
|
174
|
+
|
175
|
+
def do_curl_auth(c)
|
176
|
+
c.userpwd = "#{@name}:#{@password}"
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_s
|
180
|
+
return "User: #{@name} (pass: #{@password})"
|
181
|
+
end
|
182
|
+
|
183
|
+
def update_properties(sling, props)
|
184
|
+
return sling.execute_post(sling.url_for("#{user_url}.update.html"), props)
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def change_password(sling, newpassword)
|
189
|
+
return sling.execute_post(sling.url_for("#{user_url}.changePassword.html"), "oldPwd" => @password, "newPwd" => newpassword, "newPwdConfirm" => newpassword)
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
# Get the home folder of a group.
|
194
|
+
def home_path_for(sling)
|
195
|
+
return "/~#{@name}"
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def self.url_for(name)
|
200
|
+
return "#{$USERMANAGER_URI}user/#{name}"
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
def user_url
|
205
|
+
return User.url_for(@name)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class AnonymousUser < User
|
210
|
+
|
211
|
+
def initialize()
|
212
|
+
super("anonymous", "none")
|
213
|
+
end
|
214
|
+
|
215
|
+
def do_curl_auth(c)
|
216
|
+
# do nothing
|
217
|
+
end
|
218
|
+
|
219
|
+
def do_request_auth(r)
|
220
|
+
# do nothing
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
class UserManager
|
226
|
+
|
227
|
+
attr_accessor :log
|
228
|
+
|
229
|
+
def initialize(sling)
|
230
|
+
@sling = sling
|
231
|
+
@date = Time.now().strftime("%Y%m%d%H%M%S%3N")
|
232
|
+
@log = Logger.new(STDOUT)
|
233
|
+
@log.level = Logger::WARN
|
234
|
+
end
|
235
|
+
|
236
|
+
def delete_test_user(id)
|
237
|
+
return delete_user("testuser#{@date}-#{id}")
|
238
|
+
end
|
239
|
+
|
240
|
+
def delete_user(username)
|
241
|
+
result = @sling.execute_post(@sling.url_for("#{User.url_for(username)}.delete.html"),
|
242
|
+
{ "go" => 1 })
|
243
|
+
if (result.code.to_i > 299)
|
244
|
+
@log.info "Error deleting user"
|
245
|
+
return false
|
246
|
+
end
|
247
|
+
return true
|
248
|
+
end
|
249
|
+
|
250
|
+
def delete_group(groupname)
|
251
|
+
result = @sling.execute_post(@sling.url_for("#{Group.url_for(groupname)}.delete.html"),
|
252
|
+
{ "go" => 1 })
|
253
|
+
if (result.code.to_i > 299)
|
254
|
+
@log.info "Error deleting group"
|
255
|
+
return false
|
256
|
+
end
|
257
|
+
return true
|
258
|
+
end
|
259
|
+
|
260
|
+
def create_test_user(id)
|
261
|
+
return create_user("testuser#{@date}-#{id}")
|
262
|
+
end
|
263
|
+
|
264
|
+
def create_user(username, firstname = nil, lastname = nil)
|
265
|
+
@log.info "Creating user: #{username}"
|
266
|
+
user = User.new(username)
|
267
|
+
data = { ":name" => user.name,
|
268
|
+
"pwd" => user.password,
|
269
|
+
"pwdConfirm" => user.password
|
270
|
+
}
|
271
|
+
if (!firstname.nil? and !lastname.nil?)
|
272
|
+
data[":sakai:profile-import"] = "{'basic': {'access': 'everybody', 'elements': {'email': {'value': '#{username}@sakai.invalid'}, 'firstName': {'value': '#{firstname}'}, 'lastName': {'value': '#{lastname}'}}}}"
|
273
|
+
# data[":sakai:pages-template"] = "/var/templates/site/defaultuser"
|
274
|
+
end
|
275
|
+
result = @sling.execute_post(@sling.url_for("#{$USER_URI}"), data)
|
276
|
+
if (result.code.to_i > 299)
|
277
|
+
@log.info "Error creating user"
|
278
|
+
return nil
|
279
|
+
end
|
280
|
+
return user
|
281
|
+
end
|
282
|
+
|
283
|
+
def create_group(groupname, title = nil)
|
284
|
+
@log.info "Creating group: #{groupname}"
|
285
|
+
group = Group.new(groupname)
|
286
|
+
params = { ":name" => group.name }
|
287
|
+
if (title)
|
288
|
+
params['sakai:group-title'] = title
|
289
|
+
end
|
290
|
+
params['sakai:group-description'] = ''
|
291
|
+
params['sakai:group-id'] = groupname
|
292
|
+
# params[':sakai:pages-template'] = '/var/templates/site/defaultgroup'
|
293
|
+
params['sakai:pages-visible'] = 'public'
|
294
|
+
params['sakai:group-joinable'] = 'yes'
|
295
|
+
result = @sling.execute_post(@sling.url_for($GROUP_URI), params)
|
296
|
+
if (result.code.to_i > 299)
|
297
|
+
return nil
|
298
|
+
end
|
299
|
+
return group
|
300
|
+
end
|
301
|
+
|
302
|
+
def get_user_props(name)
|
303
|
+
return @sling.get_node_props(User.url_for(name))
|
304
|
+
end
|
305
|
+
|
306
|
+
def get_group_props(name)
|
307
|
+
return @sling.get_node_props(Group.url_for(name))
|
308
|
+
end
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|