Refactor AdminNotifier.
[arvados.git] / services / api / test / unit / user_test.rb
1 require 'test_helper'
2
3 class UserTest < ActiveSupport::TestCase
4   include CurrentApiClient
5
6   # The fixture services/api/test/fixtures/users.yml serves as the input for this test case
7   setup do
8     # Make sure system_user exists before making "pre-test users" list
9     system_user
10
11     @all_users = User.find(:all)
12
13     @all_users.each do |user|
14       if user.uuid == system_user_uuid
15         @system_user = user
16       elsif user.is_admin && user.is_active
17         @admin_user = user
18       elsif user.is_active && !user.is_admin
19         @active_user = user
20       elsif !user.is_active && !user.is_invited
21         @uninvited_user = user
22       end
23     end
24   end
25
26   test "check non-admin active user properties" do
27     assert !@active_user.is_admin, 'is_admin should not be set for a non-admin user'
28     assert @active_user.is_active, 'user should be active'
29     assert @active_user.is_invited, 'is_invited should be set'
30     assert_not_nil @active_user.prefs, "user's preferences should be non-null, but may be size zero"
31     assert (@active_user.can? :read=>"#{@active_user.uuid}"), "user should be able to read own object"
32     assert (@active_user.can? :write=>"#{@active_user.uuid}"), "user should be able to write own object"
33     assert (@active_user.can? :manage=>"#{@active_user.uuid}"), "user should be able to manage own object"
34
35     assert @active_user.groups_i_can(:read).size > 0, "active user should be able read at least one group"
36
37     # non-admin user cannot manage or write other user objects
38     assert !(@active_user.can? :read=>"#{@uninvited_user.uuid}")
39     assert !(@active_user.can? :write=>"#{@uninvited_user.uuid}")
40     assert !(@active_user.can? :manage=>"#{@uninvited_user.uuid}")
41   end
42
43   test "check admin user properties" do
44     assert @admin_user.is_admin, 'is_admin should be set for admin user'
45     assert @admin_user.is_active, 'admin user cannot be inactive'
46     assert @admin_user.is_invited, 'is_invited should be set'
47     assert_not_nil @admin_user.uuid.size, "user's uuid should be non-null"
48     assert_not_nil @admin_user.prefs, "user's preferences should be non-null, but may be size zero"
49     assert @admin_user.identity_url.size > 0, "user's identity url is expected"
50     assert @admin_user.can? :read=>"#{@admin_user.uuid}"
51     assert @admin_user.can? :write=>"#{@admin_user.uuid}"
52     assert @admin_user.can? :manage=>"#{@admin_user.uuid}"
53
54     assert @admin_user.groups_i_can(:read).size > 0, "admin active user should be able read at least one group"
55     assert @admin_user.groups_i_can(:write).size > 0, "admin active user should be able write to at least one group"
56     assert @admin_user.groups_i_can(:manage).size > 0, "admin active user should be able manage at least one group"
57
58     # admin user can also write or manage other users
59     assert @admin_user.can? :read=>"#{@uninvited_user.uuid}"
60     assert @admin_user.can? :write=>"#{@uninvited_user.uuid}"
61     assert @admin_user.can? :manage=>"#{@uninvited_user.uuid}"
62   end
63
64   test "check inactive and uninvited user properties" do
65     assert !@uninvited_user.is_admin, 'is_admin should not be set for a non-admin user'
66     assert !@uninvited_user.is_active, 'user should be inactive'
67     assert !@uninvited_user.is_invited, 'is_invited should not be set'
68     assert @uninvited_user.can? :read=>"#{@uninvited_user.uuid}"
69     assert @uninvited_user.can? :write=>"#{@uninvited_user.uuid}"
70     assert @uninvited_user.can? :manage=>"#{@uninvited_user.uuid}"
71
72     assert @uninvited_user.groups_i_can(:read).size == 0, "inactive and uninvited user should not be able read any groups"
73     assert @uninvited_user.groups_i_can(:write).size == 0, "inactive and uninvited user should not be able write to any groups"
74     assert @uninvited_user.groups_i_can(:manage).size == 0, "inactive and uninvited user should not be able manage any groups"
75   end
76
77   test "find user method checks" do
78     User.find(:all).each do |user|
79       assert_not_nil user.uuid, "non-null uuid expected for " + user.full_name
80     end
81
82     user = users(:active)     # get the active user
83
84     found_user = User.find(user.id)   # find a user by the row id
85
86     assert_equal found_user.full_name, user.first_name + ' ' + user.last_name
87     assert_equal found_user.identity_url, user.identity_url
88   end
89
90   test "full name should not contain spurious whitespace" do
91     Thread.current[:user] = @admin_user   # set admin user as the current user
92
93     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: 'foo@example.com' })
94
95     assert_equal '', user.full_name
96
97     user.first_name = 'John'
98     user.last_name = 'Smith'
99
100     assert_equal user.first_name + ' ' + user.last_name, user.full_name
101   end
102
103   test "create new user" do
104     Thread.current[:user] = @admin_user   # set admin user as the current user
105
106     user = User.new
107     user.first_name = "first_name_for_newly_created_user"
108     user.save
109
110     # verify there is one extra user in the db now
111     assert_equal @all_users.size+1, User.find(:all).size
112
113     user = User.find(user.id)   # get the user back
114     assert_equal(user.first_name, 'first_name_for_newly_created_user')
115     assert_not_nil user.uuid, 'uuid should be set for newly created user'
116     assert_nil user.email, 'email should be null for newly created user, because it was not passed in'
117     assert_nil user.identity_url, 'identity_url should be null for newly created user, because it was not passed in'
118
119     user.first_name = 'first_name_for_newly_created_user_updated'
120     user.save
121     user = User.find(user.id)   # get the user back
122     assert_equal(user.first_name, 'first_name_for_newly_created_user_updated')
123   end
124
125   test "create new inactive user with new_inactive_user_notification_recipients empty" do
126     Thread.current[:user] = @admin_user   # set admin user as the current user
127
128     Rails.configuration.new_inactive_user_notification_recipients = ''
129
130     ActionMailer::Base.deliveries = []
131
132     user = User.new
133     user.first_name = "first_name_for_newly_created_user"
134     user.is_active = false
135     user.save
136
137     assert_equal '', Rails.configuration.new_inactive_user_notification_recipients
138
139     ActionMailer::Base.deliveries.each do |d|
140       assert_not_equal "#{Rails.configuration.email_subject_prefix}New inactive user notification", setup_email.subject
141     end
142
143   end
144
145   test "create new inactive user with new_user_notification_recipients empty" do
146     Thread.current[:user] = @admin_user   # set admin user as the current user
147
148     Rails.configuration.new_user_notification_recipients = ''
149
150     ActionMailer::Base.deliveries = []
151
152     user = User.new
153     user.first_name = "first_name_for_newly_created_user"
154     user.is_active = false
155     user.save
156
157     assert_equal '', Rails.configuration.new_user_notification_recipients
158
159     ActionMailer::Base.deliveries.each do |d|
160       assert_not_equal "#{Rails.configuration.email_subject_prefix}New user notification", d.subject
161     end
162
163   end
164
165   test "create new inactive user with new_user_notification_recipients and new_inactive_user_notification_recipients set" do
166     Thread.current[:user] = @admin_user   # set admin user as the current user
167
168     Rails.configuration.new_user_notification_recipients = 'foo_new@example.com'
169     Rails.configuration.new_inactive_user_notification_recipients = 'foo_new_inactive@example.com'
170
171     ActionMailer::Base.deliveries = []
172
173     user = User.new
174     user.first_name = "first_name_for_newly_created_user"
175     user.is_active = false
176     user.save
177
178     new_user_email = nil
179     new_inactive_user_email = nil
180     ActionMailer::Base.deliveries.each do |d|
181       if d.subject == "#{Rails.configuration.email_subject_prefix}New inactive user notification" then
182         new_inactive_user_email = d
183       end
184       if d.subject == "#{Rails.configuration.email_subject_prefix}New user notification" then
185         new_user_email = d
186       end
187     end
188
189     assert_not_nil new_inactive_user_email, 'Expected new inactive user email after setup'
190     assert_not_nil new_user_email, 'Expected new user email after setup'
191
192     assert_equal 'foo_new@example.com', Rails.configuration.new_user_notification_recipients
193     assert_equal 'foo_new_inactive@example.com', Rails.configuration.new_inactive_user_notification_recipients
194
195     assert_equal Rails.configuration.user_notifier_email_from, new_inactive_user_email.from[0]
196     assert_equal 'foo_new_inactive@example.com', new_inactive_user_email.to[0]
197     assert_equal "#{Rails.configuration.email_subject_prefix}New inactive user notification", new_inactive_user_email.subject
198
199     assert_equal Rails.configuration.user_notifier_email_from, new_user_email.from[0]
200     assert_equal 'foo_new@example.com', new_user_email.to[0]
201     assert_equal "#{Rails.configuration.email_subject_prefix}New user notification", new_user_email.subject
202   end
203
204   test "create new inactive user with new_user_notification_recipients set" do
205     Thread.current[:user] = @admin_user   # set admin user as the current user
206
207     Rails.configuration.new_user_notification_recipients = 'foo@example.com'
208
209     user = User.new
210     user.first_name = "first_name_for_newly_created_user"
211     user.is_active = false
212     user.save
213
214     new_user_email = nil
215
216     ActionMailer::Base.deliveries.each do |d|
217       if d.subject == "#{Rails.configuration.email_subject_prefix}New user notification" then
218         new_user_email = d
219         break
220       end
221     end
222
223     assert_not_nil new_user_email, 'Expected email after setup'
224
225     assert_equal 'foo@example.com', Rails.configuration.new_user_notification_recipients
226
227     assert_equal Rails.configuration.user_notifier_email_from, new_user_email.from[0]
228     assert_equal 'foo@example.com', new_user_email.to[0]
229     assert_equal "#{Rails.configuration.email_subject_prefix}New user notification", new_user_email.subject
230   end
231
232   test "create new active user with new_inactive_user_notification_recipients set" do
233     Thread.current[:user] = @admin_user   # set admin user as the current user
234
235     Rails.configuration.new_inactive_user_notification_recipients = 'foo@example.com'
236
237     ActionMailer::Base.deliveries = []
238
239     user = User.new
240     user.first_name = "first_name_for_newly_created_user"
241     user.is_active = true
242     user.save
243
244     assert_equal 'foo@example.com', Rails.configuration.new_inactive_user_notification_recipients
245
246     ActionMailer::Base.deliveries.each do |d|
247       assert_not_equal "#{Rails.configuration.email_subject_prefix}New inactive user notification", setup_email.subject
248     end
249
250   end
251
252
253   test "update existing user" do
254     Thread.current[:user] = @active_user    # set active user as current user
255     @active_user.first_name = "first_name_changed"
256     @active_user.save
257
258     @active_user = User.find(@active_user.id)   # get the user back
259     assert_equal(@active_user.first_name, 'first_name_changed')
260
261     # admin user also should be able to update the "active" user info
262     Thread.current[:user] = @admin_user # set admin user as current user
263     @active_user.first_name = "first_name_changed_by_admin_for_active_user"
264     @active_user.save
265
266     @active_user = User.find(@active_user.id)   # get the user back
267     assert_equal(@active_user.first_name, 'first_name_changed_by_admin_for_active_user')
268   end
269
270   test "delete a user and verify" do
271     active_user_uuid = @active_user.uuid
272
273     Thread.current[:user] = @admin_user
274     @active_user.delete
275
276     found_deleted_user = false
277     User.find(:all).each do |user|
278       if user.uuid == active_user_uuid
279         found_deleted_user = true
280         break
281       end
282     end
283     assert !found_deleted_user, "found deleted user: "+active_user_uuid
284
285   end
286
287   test "create new user as non-admin user" do
288     Thread.current[:user] = @active_user
289
290     begin
291       user = User.new
292       user.save
293     rescue ArvadosModel::PermissionDeniedError => e
294     end
295     assert (e.message.include? 'PermissionDeniedError'),
296         'Expected PermissionDeniedError'
297   end
298
299   test "setup new user" do
300     Thread.current[:user] = @admin_user
301
302     email = 'foo@example.com'
303     openid_prefix = 'http://openid/prefix'
304
305     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
306
307     vm = VirtualMachine.create
308
309     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
310
311     resp_user = find_obj_in_resp response, 'User'
312     verify_user resp_user, email
313
314     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
315
316     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
317         resp_user[:uuid]
318
319     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
320         'expected identity_url_prefix not found for oid_login_perm'
321
322     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
323     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
324
325     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
326     verify_link repo_perm, 'permission', 'can_write', resp_user[:uuid], nil
327
328     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
329     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
330   end
331
332   test "setup new user with junk in database" do
333     Thread.current[:user] = @admin_user
334
335     email = 'foo@example.com'
336     openid_prefix = 'http://openid/prefix'
337
338     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
339
340     vm = VirtualMachine.create
341
342     # Set up the bogus Link
343     bad_uuid = 'zzzzz-tpzed-xyzxyzxyzxyzxyz'
344
345     resp_link = Link.create ({tail_uuid: email, link_class: 'permission',
346         name: 'can_login', head_uuid: bad_uuid})
347     resp_link.save(validate: false)
348
349     verify_link resp_link, 'permission', 'can_login', email, bad_uuid
350
351     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
352
353     resp_user = find_obj_in_resp response, 'User'
354     verify_user resp_user, email
355
356     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
357
358     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
359         resp_user[:uuid]
360
361     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
362         'expected identity_url_prefix not found for oid_login_perm'
363
364     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
365     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
366
367     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
368     verify_link repo_perm, 'permission', 'can_write', resp_user[:uuid], nil
369
370     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
371     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
372   end
373
374
375
376   test "setup new user in multiple steps" do
377     Thread.current[:user] = @admin_user
378
379     email = 'foo@example.com'
380     openid_prefix = 'http://openid/prefix'
381
382     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
383
384     response = User.setup user, openid_prefix
385
386     resp_user = find_obj_in_resp response, 'User'
387     verify_user resp_user, email
388
389     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
390     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
391         resp_user[:uuid]
392     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
393         'expected identity_url_prefix not found for oid_login_perm'
394
395     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
396     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
397
398     # invoke setup again with repo_name
399     response = User.setup user, openid_prefix, 'test_repo'
400     resp_user = find_obj_in_resp response, 'User', nil
401     verify_user resp_user, email
402     assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
403
404     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
405     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
406
407     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
408     verify_link repo_perm, 'permission', 'can_write', resp_user[:uuid], nil
409
410     # invoke setup again with a vm_uuid
411     vm = VirtualMachine.create
412
413     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
414
415     resp_user = find_obj_in_resp response, 'User', nil
416     verify_user resp_user, email
417     assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
418
419     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
420     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
421
422     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
423     verify_link repo_perm, 'permission', 'can_write', resp_user[:uuid], nil
424
425     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
426     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
427   end
428
429   def find_obj_in_resp (response_items, object_type, head_kind=nil)
430     return_obj = nil
431     response_items.each { |x|
432       if !x
433         next
434       end
435
436       if object_type == 'User'
437         if ArvadosModel::resource_class_for_uuid(x['uuid']) == User
438           return_obj = x
439           break
440         end
441       else  # looking for a link
442         if ArvadosModel::resource_class_for_uuid(x['head_uuid']).kind == head_kind
443           return_obj = x
444           break
445         end
446       end
447     }
448     return return_obj
449   end
450
451   def verify_user (resp_user, email)
452     assert_not_nil resp_user, 'expected user object'
453     assert_not_nil resp_user['uuid'], 'expected user object'
454     assert_equal email, resp_user['email'], 'expected email not found'
455
456   end
457
458   def verify_link (link_object, link_class, link_name, tail_uuid, head_uuid)
459     assert_not_nil link_object, "expected link for #{link_class} #{link_name}"
460     assert_not_nil link_object[:uuid],
461         "expected non-nil uuid for link for #{link_class} #{link_name}"
462     assert_equal link_class, link_object[:link_class],
463         "expected link_class not found for #{link_class} #{link_name}"
464     assert_equal link_name, link_object[:name],
465         "expected link_name not found for #{link_class} #{link_name}"
466     assert_equal tail_uuid, link_object[:tail_uuid],
467         "expected tail_uuid not found for #{link_class} #{link_name}"
468     if head_uuid
469       assert_equal head_uuid, link_object[:head_uuid],
470           "expected head_uuid not found for #{link_class} #{link_name}"
471     end
472   end
473
474 end