9ba5646013fc8a17ae25955e607f19653c14b7b8
[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   end
11
12   %w(a aa a0 aA Aa AA A0).each do |username|
13     test "#{username.inspect} is a valid username" do
14       user = User.new(username: username)
15       assert(user.valid?)
16     end
17   end
18
19   test "username is not required" do
20     user = User.new(username: nil)
21     assert(user.valid?)
22   end
23
24   test "username beginning with numeral is invalid" do
25     user = User.new(username: "0a")
26     refute(user.valid?)
27   end
28
29   "\\.-_/!@#$%^&*()[]{}".each_char do |bad_char|
30     test "username containing #{bad_char.inspect} is invalid" do
31       user = User.new(username: "bad#{bad_char}username")
32       refute(user.valid?)
33     end
34   end
35
36   test "username must be unique" do
37     user = User.new(username: users(:active).username)
38     refute(user.valid?)
39   end
40
41   test "non-admin can't update username" do
42     set_user_from_auth :active_trustedclient
43     user = User.find_by_uuid(users(:active).uuid)
44     user.username = "selfupdate"
45     begin
46       refute(user.save)
47     rescue ArvadosModel::PermissionDeniedError
48       # That works too.
49     end
50   end
51
52   def check_admin_username_change(fixture_name)
53     set_user_from_auth :admin_trustedclient
54     user = User.find_by_uuid(users(fixture_name).uuid)
55     user.username = "newnamefromtest"
56     assert(user.save)
57   end
58
59   test "admin can set username" do
60     check_admin_username_change(:active_no_prefs)
61   end
62
63   test "admin can update username" do
64     check_admin_username_change(:active)
65   end
66
67   test "admin can update own username" do
68     check_admin_username_change(:admin)
69   end
70
71   def check_new_username_setting(email_name, expect_name)
72     set_user_from_auth :admin
73     user = User.create!(email: "#{email_name}@example.org")
74     assert_equal(expect_name, user.username)
75   end
76
77   test "new username set from e-mail" do
78     check_new_username_setting("dakota", "dakota")
79   end
80
81   test "new username set from e-mail with leading digits" do
82     check_new_username_setting("1dakota9", "dakota9")
83   end
84
85   test "new username set from e-mail with punctuation" do
86     check_new_username_setting("dakota.9", "dakota9")
87   end
88
89   test "new username set from e-mail with leading digits and punctuation" do
90     check_new_username_setting("1.dakota.z", "dakotaz")
91   end
92
93   test "new username set from e-mail with extra part" do
94     check_new_username_setting("dakota+arvados", "dakota")
95   end
96
97   test "new username set with deduplication" do
98     name = users(:active).username
99     check_new_username_setting(name, "#{name}2")
100   end
101
102   test "new username set avoiding blacklist" do
103     Rails.configuration.auto_setup_name_blacklist = ["root"]
104     check_new_username_setting("root", "root2")
105   end
106
107   test "no username set when no base available" do
108     check_new_username_setting("_", nil)
109   end
110
111   [[false, 'foo@example.com', true, nil],
112    [false, 'bar@example.com', nil, true],
113    [true, 'foo@example.com', true, nil],
114    [true, 'bar@example.com', true, true],
115    [false, false, nil, nil],
116    [true, false, true, nil]
117   ].each do |auto_admin_first_user_config, auto_admin_user_config, foo_should_be_admin, bar_should_be_admin|
118     # In each case, 'foo' is created first, then 'bar', then 'bar2', then 'baz'.
119     test "auto admin with auto_admin_first=#{auto_admin_first_user_config} auto_admin=#{auto_admin_user_config}" do
120
121       if auto_admin_first_user_config
122         # This test requires no admin users exist (except for the system user)
123         users(:admin).delete
124         @all_users = User.where("uuid not like '%-000000000000000'").where(:is_admin => true).find(:all)
125         assert_equal 0, @all_users.size, "No admin users should exist (except for the system user)"
126       end
127
128       Rails.configuration.auto_admin_first_user = auto_admin_first_user_config
129       Rails.configuration.auto_admin_user = auto_admin_user_config
130
131       # See if the foo user has is_admin
132       foo = User.new
133       foo.first_name = 'foo'
134       foo.email = 'foo@example.com'
135
136       act_as_system_user do
137         foo.save!
138       end
139
140       foo = User.find(foo.id)   # get the user back
141       assert_equal foo_should_be_admin, foo.is_admin, "is_admin is wrong for user foo"
142       assert_equal 'foo', foo.first_name
143
144       # See if the bar user has is_admin
145       bar = User.new
146       bar.first_name = 'bar'
147       bar.email = 'bar@example.com'
148
149       act_as_system_user do
150         bar.save!
151       end
152
153       bar = User.find(bar.id)   # get the user back
154       assert_equal bar_should_be_admin, bar.is_admin, "is_admin is wrong for user bar"
155       assert_equal 'bar', bar.first_name
156
157       # A subsequent user with the bar@example.com address should never be
158       # elevated to admin
159       bar2 = User.new
160       bar2.first_name = 'bar2'
161       bar2.email = 'bar@example.com'
162
163       act_as_system_user do
164         bar2.save!
165       end
166
167       bar2 = User.find(bar2.id)   # get the user back
168       assert !bar2.is_admin, "is_admin is wrong for user bar2"
169       assert_equal 'bar2', bar2.first_name
170
171       # An ordinary new user should not be elevated to admin
172       baz = User.new
173       baz.first_name = 'baz'
174       baz.email = 'baz@example.com'
175
176       act_as_system_user do
177         baz.save!
178       end
179
180       baz = User.find(baz.id)   # get the user back
181       assert !baz.is_admin
182       assert_equal 'baz', baz.first_name
183
184     end
185   end
186
187   test "check non-admin active user properties" do
188     @active_user = users(:active)     # get the active user
189     assert !@active_user.is_admin, 'is_admin should not be set for a non-admin user'
190     assert @active_user.is_active, 'user should be active'
191     assert @active_user.is_invited, 'is_invited should be set'
192     assert_not_nil @active_user.prefs, "user's preferences should be non-null, but may be size zero"
193     assert (@active_user.can? :read=>"#{@active_user.uuid}"), "user should be able to read own object"
194     assert (@active_user.can? :write=>"#{@active_user.uuid}"), "user should be able to write own object"
195     assert (@active_user.can? :manage=>"#{@active_user.uuid}"), "user should be able to manage own object"
196
197     assert @active_user.groups_i_can(:read).size > 0, "active user should be able read at least one group"
198
199     # non-admin user cannot manage or write other user objects
200     @uninvited_user = users(:inactive_uninvited)     # get the uninvited user
201     assert !(@active_user.can? :read=>"#{@uninvited_user.uuid}")
202     assert !(@active_user.can? :write=>"#{@uninvited_user.uuid}")
203     assert !(@active_user.can? :manage=>"#{@uninvited_user.uuid}")
204   end
205
206   test "check admin user properties" do
207     @admin_user = users(:admin)     # get the admin user
208     assert @admin_user.is_admin, 'is_admin should be set for admin user'
209     assert @admin_user.is_active, 'admin user cannot be inactive'
210     assert @admin_user.is_invited, 'is_invited should be set'
211     assert_not_nil @admin_user.uuid.size, "user's uuid should be non-null"
212     assert_not_nil @admin_user.prefs, "user's preferences should be non-null, but may be size zero"
213     assert @admin_user.identity_url.size > 0, "user's identity url is expected"
214     assert @admin_user.can? :read=>"#{@admin_user.uuid}"
215     assert @admin_user.can? :write=>"#{@admin_user.uuid}"
216     assert @admin_user.can? :manage=>"#{@admin_user.uuid}"
217
218     assert @admin_user.groups_i_can(:read).size > 0, "admin active user should be able read at least one group"
219     assert @admin_user.groups_i_can(:write).size > 0, "admin active user should be able write to at least one group"
220     assert @admin_user.groups_i_can(:manage).size > 0, "admin active user should be able manage at least one group"
221
222     # admin user can also write or manage other users
223     @uninvited_user = users(:inactive_uninvited)     # get the uninvited user
224     assert @admin_user.can? :read=>"#{@uninvited_user.uuid}"
225     assert @admin_user.can? :write=>"#{@uninvited_user.uuid}"
226     assert @admin_user.can? :manage=>"#{@uninvited_user.uuid}"
227   end
228
229   test "check inactive and uninvited user properties" do
230     @uninvited_user = users(:inactive_uninvited)     # get the uninvited user
231     assert !@uninvited_user.is_admin, 'is_admin should not be set for a non-admin user'
232     assert !@uninvited_user.is_active, 'user should be inactive'
233     assert !@uninvited_user.is_invited, 'is_invited should not be set'
234     assert @uninvited_user.can? :read=>"#{@uninvited_user.uuid}"
235     assert @uninvited_user.can? :write=>"#{@uninvited_user.uuid}"
236     assert @uninvited_user.can? :manage=>"#{@uninvited_user.uuid}"
237
238     assert @uninvited_user.groups_i_can(:read).size == 1, "inactive and uninvited user can only read anonymous user group"
239     assert @uninvited_user.groups_i_can(:read).first.ends_with? 'anonymouspublic' , "inactive and uninvited user can only read anonymous user group"
240     assert @uninvited_user.groups_i_can(:write).size == 0, "inactive and uninvited user should not be able write to any groups"
241     assert @uninvited_user.groups_i_can(:manage).size == 0, "inactive and uninvited user should not be able manage any groups"
242   end
243
244   test "find user method checks" do
245     User.find(:all).each do |user|
246       assert_not_nil user.uuid, "non-null uuid expected for " + user.full_name
247     end
248
249     user = users(:active)     # get the active user
250
251     found_user = User.find(user.id)   # find a user by the row id
252
253     assert_equal found_user.full_name, user.first_name + ' ' + user.last_name
254     assert_equal found_user.identity_url, user.identity_url
255   end
256
257   test "full name should not contain spurious whitespace" do
258     set_user_from_auth :admin
259
260     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: 'foo@example.com' })
261
262     assert_equal '', user.full_name
263
264     user.first_name = 'John'
265     user.last_name = 'Smith'
266
267     assert_equal user.first_name + ' ' + user.last_name, user.full_name
268   end
269
270   test "create new user" do
271     set_user_from_auth :admin
272
273     @all_users = User.find(:all)
274
275     user = User.new
276     user.first_name = "first_name_for_newly_created_user"
277     user.save
278
279     # verify there is one extra user in the db now
280     assert_equal @all_users.size+1, User.find(:all).size
281
282     user = User.find(user.id)   # get the user back
283     assert_equal(user.first_name, 'first_name_for_newly_created_user')
284     assert_not_nil user.uuid, 'uuid should be set for newly created user'
285     assert_nil user.email, 'email should be null for newly created user, because it was not passed in'
286     assert_nil user.identity_url, 'identity_url should be null for newly created user, because it was not passed in'
287
288     user.first_name = 'first_name_for_newly_created_user_updated'
289     user.save
290     user = User.find(user.id)   # get the user back
291     assert_equal(user.first_name, 'first_name_for_newly_created_user_updated')
292   end
293
294   test "create new user with notifications" do
295     set_user_from_auth :admin
296
297     create_user_and_verify_setup_and_notifications true, 'active-notify-address@example.com', 'inactive-notify-address@example.com', nil, false
298     create_user_and_verify_setup_and_notifications true, 'active-notify-address@example.com', [], nil, false
299     create_user_and_verify_setup_and_notifications true, [], [], nil, false
300     create_user_and_verify_setup_and_notifications false, 'active-notify-address@example.com', 'inactive-notify-address@example.com', nil, false
301     create_user_and_verify_setup_and_notifications false, [], 'inactive-notify-address@example.com', nil, false
302     create_user_and_verify_setup_and_notifications false, [], [], nil, false
303   end
304
305   [
306     [false, [], [], 'inactive-none@example.com', false, false, true],
307     [false, [], [], 'inactive-vm@example.com', true, false, true],
308     [false, [], [], 'inactive-repo@example.com', false, true, true],
309     [false, [], [], 'inactive-both@example.com', true, true, true],
310
311     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'active-none@example.com', false, false, true],
312     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'active-vm@example.com', true, false, true],
313     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'active-repo@example.com', false, true, true],
314     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'active-both@example.com', true, true, true],
315
316     [false, [], [], nil, true, true, false],
317
318     [false, [], [], 'arvados', true, true, false],
319     [false, [], [], 'arvados', true, false, false],   # blacklisted username
320     [false, [], [], 'arvados', false, false, true],   # since we are not creating repo and vm login, this blacklisted name is not a problem
321
322     [false, [], [], 'arvados@example.com', false, false, true],   # since we are not creating repo and vm login, this blacklisted name is not a problem
323     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'arvados@example.com', false, false, true],   # since we are not creating repo and vm login, this blacklisted name is not a problem
324     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'root@example.com', true, false, false], # blacklisted name
325     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'root@example.com', true, false, false], # blacklisted name
326     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'roo_t@example.com', false, true, true], # not blacklisted name
327
328     [false, [], [], '@example.com', true, false, false],  # incorrect format
329     [false, [], [], '@example.com', false, true, false],
330     [false, [], [], '@example.com', false, false, true],  # no repo and vm login, so no issue with email format
331
332     [false, [], [], '^^incorrect_format@example.com', true, true, false],
333
334     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_repo@example.com', true, true, true],  # existing repository name 'auto_setup_repo'
335     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_repo@example.com', true, false, true],  # existing repository name 'auto_setup_repo'
336     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_repo@example.com', false, true, true],  # existing repository name 'auto_setup_repo'
337     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_repo@example.com', false, false, true],  # existing repository name 'auto_setup_repo', but we are not creating repo or login link
338
339     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_vm_login@example.com', true, true, true], # existing vm login name
340     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_vm_login@example.com', true, false, true], # existing vm login name
341     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_vm_login@example.com', false, true, true], # existing vm login name
342     [false, 'active-notify@example.com', 'inactive-notify@example.com', 'auto_setup_vm_login@example.com', false, false, true], # existing vm login name, but we are not creating repo or login link
343
344     [true, 'active-notify@example.com', 'inactive-notify@example.com', '*!*@example.com', true, false, false], # username is invalid format
345     [false, 'active-notify@example.com', 'inactive-notify@example.com', '*!*@example.com', false, false, true], # since no repo and vm login, username is ok (not validated)
346     [true, 'active-notify@example.com', 'inactive-notify@example.com', '*!*@example.com', false, false, true], # since no repo and vm login, username is ok (not validated)
347
348     [true, 'active-notify@example.com', 'inactive-notify@example.com', '&4ad@example.com', true, true, false], # username is invalid format
349     [true, 'active-notify@example.com', 'inactive-notify@example.com', '&4ad@example.com', false, false, true], # no repo or vm login, so format not checked
350     [false, 'active-notify@example.com', 'inactive-notify@example.com', '&4ad@example.com', true, true, false], # username is invalid format
351     [false, 'active-notify@example.com', 'inactive-notify@example.com', '&4ad@example.com', false, false, true], # no repo or vm login, so format not checked
352
353     [true, 'active-notify@example.com', 'inactive-notify@example.com', '4ad@example.com', true, true, false], # username is invalid format
354     [true, 'active-notify@example.com', 'inactive-notify@example.com', '4ad@example.com', false, false, true], # no repo or vm login, so format not checked
355     [false, 'active-notify@example.com', 'inactive-notify@example.com', '4ad@example.com', false, false, true], # no repo or vm login, so format not checked
356
357     [true, 'active-notify@example.com', 'inactive-notify@example.com', '.foo@example.com', false, false, true], # no repo or vm login, so format not checked
358     [true, 'active-notify@example.com', 'inactive-notify@example.com', '.foo@example.com', true, false, false], # invalid format
359
360     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'bar.@example.com', false, false, true], # no repo or vm login, so format not checked
361     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'bar.@example.com', true, false, false], # valid format
362
363     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'ice9@example.com', false, false, true], # no repo or vm login, so format not checked
364     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'ice9@example.com', true, false, true], # valid format
365
366     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'o_o@example.com', false, false, true], # no repo or vm login, so format not checked
367     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'o_o@example.com', true, false, true], # valid format
368
369     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'r00t@example.com', false, false, true], # no repo or vm login, so format not checked
370     [true, 'active-notify@example.com', 'inactive-notify@example.com', 'r00t@example.com', true, false, true], # valid format
371
372   ].each do |active, new_user_recipients, inactive_recipients, email, auto_setup_vm, auto_setup_repo, ok_to_auto_setup|
373     test "create new user with auto setup #{active} #{email} #{auto_setup_vm} #{auto_setup_repo}" do
374       auto_setup_new_users = Rails.configuration.auto_setup_new_users
375       auto_setup_new_users_with_vm_uuid = Rails.configuration.auto_setup_new_users_with_vm_uuid
376       auto_setup_new_users_with_repository = Rails.configuration.auto_setup_new_users_with_repository
377
378       begin
379         set_user_from_auth :admin
380
381         Rails.configuration.auto_setup_new_users = true
382
383         if auto_setup_vm
384           Rails.configuration.auto_setup_new_users_with_vm_uuid = virtual_machines(:testvm)['uuid']
385         else
386           Rails.configuration.auto_setup_new_users_with_vm_uuid = false
387         end
388
389         Rails.configuration.auto_setup_new_users_with_repository = auto_setup_repo
390
391         create_user_and_verify_setup_and_notifications active, new_user_recipients, inactive_recipients, email, ok_to_auto_setup
392       ensure
393         Rails.configuration.auto_setup_new_users = auto_setup_new_users
394         Rails.configuration.auto_setup_new_users_with_vm_uuid = auto_setup_new_users_with_vm_uuid
395         Rails.configuration.auto_setup_new_users_with_repository = auto_setup_new_users_with_repository
396       end
397     end
398   end
399
400   test "update existing user" do
401     set_user_from_auth :active    # set active user as current user
402
403     @active_user = users(:active)     # get the active user
404
405     @active_user.first_name = "first_name_changed"
406     @active_user.save
407
408     @active_user = User.find(@active_user.id)   # get the user back
409     assert_equal(@active_user.first_name, 'first_name_changed')
410
411     # admin user also should be able to update the "active" user info
412     set_user_from_auth :admin # set admin user as current user
413     @active_user.first_name = "first_name_changed_by_admin_for_active_user"
414     @active_user.save
415
416     @active_user = User.find(@active_user.id)   # get the user back
417     assert_equal(@active_user.first_name, 'first_name_changed_by_admin_for_active_user')
418   end
419
420   test "delete a user and verify" do
421     @active_user = users(:active)     # get the active user
422     active_user_uuid = @active_user.uuid
423
424     set_user_from_auth :admin
425     @active_user.delete
426
427     found_deleted_user = false
428     User.find(:all).each do |user|
429       if user.uuid == active_user_uuid
430         found_deleted_user = true
431         break
432       end
433     end
434     assert !found_deleted_user, "found deleted user: "+active_user_uuid
435
436   end
437
438   test "create new user as non-admin user" do
439     set_user_from_auth :active
440
441     begin
442       user = User.new
443       user.save
444     rescue ArvadosModel::PermissionDeniedError => e
445     end
446     assert (e.message.include? 'PermissionDeniedError'),
447         'Expected PermissionDeniedError'
448   end
449
450   test "setup new user" do
451     set_user_from_auth :admin
452
453     email = 'foo@example.com'
454     openid_prefix = 'http://openid/prefix'
455
456     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
457
458     vm = VirtualMachine.create
459
460     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
461
462     resp_user = find_obj_in_resp response, 'User'
463     verify_user resp_user, email
464
465     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
466
467     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
468         resp_user[:uuid]
469
470     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
471         'expected identity_url_prefix not found for oid_login_perm'
472
473     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
474     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
475
476     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
477     verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
478
479     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
480     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
481   end
482
483   test "setup new user with junk in database" do
484     set_user_from_auth :admin
485
486     email = 'foo@example.com'
487     openid_prefix = 'http://openid/prefix'
488
489     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
490
491     vm = VirtualMachine.create
492
493     # Set up the bogus Link
494     bad_uuid = 'zzzzz-tpzed-xyzxyzxyzxyzxyz'
495
496     resp_link = Link.create ({tail_uuid: email, link_class: 'permission',
497         name: 'can_login', head_uuid: bad_uuid})
498     resp_link.save(validate: false)
499
500     verify_link resp_link, 'permission', 'can_login', email, bad_uuid
501
502     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
503
504     resp_user = find_obj_in_resp response, 'User'
505     verify_user resp_user, email
506
507     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
508
509     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
510         resp_user[:uuid]
511
512     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
513         'expected identity_url_prefix not found for oid_login_perm'
514
515     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
516     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
517
518     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
519     verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
520
521     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
522     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
523   end
524
525   test "setup new user in multiple steps" do
526     set_user_from_auth :admin
527
528     email = 'foo@example.com'
529     openid_prefix = 'http://openid/prefix'
530
531     user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
532
533     response = User.setup user, openid_prefix
534
535     resp_user = find_obj_in_resp response, 'User'
536     verify_user resp_user, email
537
538     oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
539     verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
540         resp_user[:uuid]
541     assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
542         'expected identity_url_prefix not found for oid_login_perm'
543
544     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
545     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
546
547     # invoke setup again with repo_name
548     response = User.setup user, openid_prefix, 'test_repo'
549     resp_user = find_obj_in_resp response, 'User', nil
550     verify_user resp_user, email
551     assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
552
553     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
554     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
555
556     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
557     verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
558
559     # invoke setup again with a vm_uuid
560     vm = VirtualMachine.create
561
562     response = User.setup user, openid_prefix, 'test_repo', vm.uuid
563
564     resp_user = find_obj_in_resp response, 'User', nil
565     verify_user resp_user, email
566     assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
567
568     group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
569     verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
570
571     repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
572     verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
573
574     vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
575     verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
576   end
577
578   def find_obj_in_resp (response_items, object_type, head_kind=nil)
579     return_obj = nil
580     response_items.each { |x|
581       if !x
582         next
583       end
584
585       if object_type == 'User'
586         if ArvadosModel::resource_class_for_uuid(x['uuid']) == User
587           return_obj = x
588           break
589         end
590       else  # looking for a link
591         if ArvadosModel::resource_class_for_uuid(x['head_uuid']).kind == head_kind
592           return_obj = x
593           break
594         end
595       end
596     }
597     return return_obj
598   end
599
600   def verify_user (resp_user, email)
601     assert_not_nil resp_user, 'expected user object'
602     assert_not_nil resp_user['uuid'], 'expected user object'
603     assert_equal email, resp_user['email'], 'expected email not found'
604
605   end
606
607   def verify_link (link_object, link_class, link_name, tail_uuid, head_uuid)
608     assert_not_nil link_object, "expected link for #{link_class} #{link_name}"
609     assert_not_nil link_object[:uuid],
610         "expected non-nil uuid for link for #{link_class} #{link_name}"
611     assert_equal link_class, link_object[:link_class],
612         "expected link_class not found for #{link_class} #{link_name}"
613     assert_equal link_name, link_object[:name],
614         "expected link_name not found for #{link_class} #{link_name}"
615     assert_equal tail_uuid, link_object[:tail_uuid],
616         "expected tail_uuid not found for #{link_class} #{link_name}"
617     if head_uuid
618       assert_equal head_uuid, link_object[:head_uuid],
619           "expected head_uuid not found for #{link_class} #{link_name}"
620     end
621   end
622
623   def create_user_and_verify_setup_and_notifications (active, new_user_recipients, inactive_recipients, email, ok_to_auto_setup)
624     Rails.configuration.new_user_notification_recipients = new_user_recipients
625     Rails.configuration.new_inactive_user_notification_recipients = inactive_recipients
626
627     assert_equal new_user_recipients, Rails.configuration.new_user_notification_recipients
628     assert_equal inactive_recipients, Rails.configuration.new_inactive_user_notification_recipients
629
630     ActionMailer::Base.deliveries = []
631
632     user = User.new
633     user.first_name = "first_name_for_newly_created_user"
634     user.email = email
635     user.is_active = active
636     user.save!
637
638     # check user setup
639     group = Group.where(name: 'All users').select do |g|
640       g[:uuid].match /-f+$/
641     end.first
642
643     if !Rails.configuration.auto_setup_new_users || !ok_to_auto_setup
644       # verify that the user is not added to "All groups" by auto_setup
645       verify_link_exists false, group[:uuid], user.uuid, 'permission', 'can_read', nil, nil
646
647       # check oid login link not created by auto_setup
648       verify_link_exists false, user.uuid, user.email, 'permission', 'can_login', nil, nil
649     else
650       # verify that auto_setup took place
651       # verify that the user is added to "All groups"
652       verify_link_exists true, group[:uuid], user.uuid, 'permission', 'can_read', nil, nil
653
654       # check oid login link
655       verify_link_exists true, user.uuid, user.email, 'permission', 'can_login', nil, nil
656
657       username = user.email.partition('@')[0] if email
658
659       # check repo
660       repo_names = []
661       if Rails.configuration.auto_setup_new_users_with_repository
662         repos = Repository.where('name like ?', "%#{username}%")
663         assert_not_nil repos, 'repository not found'
664         assert_equal true, repos.any?, 'repository not found'
665         repo_uuids = []
666         repos.each do |repo|
667           repo_uuids << repo[:uuid]
668           repo_names << repo[:name]
669         end
670         if username == 'auto_setup_repo'
671           begin
672             repo_names.delete('auto_setup_repo')
673           ensure
674             assert_equal true, repo_names.any?, 'Repository name for username foo is not unique'
675           end
676         end
677         verify_link_exists true, repo_uuids, user.uuid, 'permission', 'can_manage', nil, nil
678       end
679
680       # if username is existing vm login name, make sure the username used to generate any repo is unique
681       if username == 'auto_setup_vm_login' || username == 'auto_setup_repo'
682         if repo_names.any?
683           assert repo_names.first.start_with? username
684           assert_not_nil /\d$/.match(repo_names.first)
685         end
686       end
687
688       # check vm uuid
689       vm_uuid = Rails.configuration.auto_setup_new_users_with_vm_uuid
690       if vm_uuid
691         verify_link_exists true, vm_uuid, user.uuid, 'permission', 'can_login', 'username', (username == 'auto_setup_repo' ? repo_names.first : username)
692       else
693         verify_link_exists false, vm_uuid, user.uuid, 'permission', 'can_login', 'username', (username == 'auto_setup_repo' ? repo_names.first : username)
694       end
695     end
696
697     # check email notifications
698     new_user_email = nil
699     new_inactive_user_email = nil
700
701     new_user_email_subject = "#{Rails.configuration.email_subject_prefix}New user created notification"
702     if Rails.configuration.auto_setup_new_users
703       new_user_email_subject = (ok_to_auto_setup || active) ?
704                                  "#{Rails.configuration.email_subject_prefix}New user created and setup notification" :
705                                  "#{Rails.configuration.email_subject_prefix}New user created, but not setup notification"
706     end
707
708     ActionMailer::Base.deliveries.each do |d|
709       if d.subject == new_user_email_subject then
710         new_user_email = d
711       elsif d.subject == "#{Rails.configuration.email_subject_prefix}New inactive user notification" then
712         new_inactive_user_email = d
713       end
714     end
715
716     # both active and inactive user creations should result in new user creation notification mails,
717     # if the new user email recipients config parameter is set
718     if not new_user_recipients.empty? then
719       assert_not_nil new_user_email, 'Expected new user email after setup'
720       assert_equal Rails.configuration.user_notifier_email_from, new_user_email.from[0]
721       assert_equal new_user_recipients, new_user_email.to[0]
722       assert_equal new_user_email_subject, new_user_email.subject
723     else
724       assert_nil new_user_email, 'Did not expect new user email after setup'
725     end
726
727     if not active
728       if not inactive_recipients.empty? then
729         assert_not_nil new_inactive_user_email, 'Expected new inactive user email after setup'
730         assert_equal Rails.configuration.user_notifier_email_from, new_inactive_user_email.from[0]
731         assert_equal inactive_recipients, new_inactive_user_email.to[0]
732         assert_equal "#{Rails.configuration.email_subject_prefix}New inactive user notification", new_inactive_user_email.subject
733       else
734         assert_nil new_inactive_user_email, 'Did not expect new inactive user email after setup'
735       end
736     else
737       assert_nil new_inactive_user_email, 'Expected no inactive user email after setting up active user'
738     end
739     ActionMailer::Base.deliveries = []
740
741   end
742
743   def verify_link_exists link_exists, head_uuid, tail_uuid, link_class, link_name, property_name, property_value
744     all_links = Link.where(head_uuid: head_uuid,
745                            tail_uuid: tail_uuid,
746                            link_class: link_class,
747                            name: link_name)
748     assert_equal link_exists, all_links.any?, "Link #{'not' if link_exists} found for #{link_name} #{link_class} #{property_value}"
749     if link_exists && property_name && property_value
750       all_links.each do |link|
751         assert_equal true, all_links.first.properties[property_name].start_with?(property_value), 'Property not found in link'
752       end
753     end
754   end
755
756 end