21059: Fix "Arvado" typo. Use URI::join.
[arvados.git] / services / api / test / integration / remote_user_test.rb
index 179d30f3cbf3c255a1570ba3227b732603dd8ef9..f42fda415077ae4db9ba4496e0e3269df4734453 100644 (file)
@@ -55,7 +55,6 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
         SSLCertName: [["CN", WEBrick::Utils::getservername]],
         StartCallback: lambda { ready.push(true) })
       srv.mount_proc '/discovery/v1/apis/arvados/v1/rest' do |req, res|
-        Rails.cache.delete 'arvados_v1_rest_discovery'
         res.body = Arvados::V1::SchemaController.new.send(:discovery_doc).to_json
       end
       srv.mount_proc '/arvados/v1/users/current' do |req, res|
@@ -75,10 +74,15 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
         end
         res.status = @stub_token_status
         if res.status == 200
-          res.body = {
+          body = {
             uuid: api_client_authorizations(:active).uuid.sub('zzzzz', clusterid),
+            owner_uuid: "#{clusterid}-tpzed-00000000000000z",
             scopes: @stub_token_scopes,
-          }.to_json
+          }
+          if @stub_content.is_a?(Hash) and owner_uuid = @stub_content[:uuid]
+            body[:owner_uuid] = owner_uuid
+          end
+          res.body = body.to_json
         end
       end
       Thread.new do
@@ -96,12 +100,15 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       uuid: 'zbbbb-tpzed-000000000000001',
       email: 'foo@example.com',
       username: 'barney',
+      first_name: "Barney",
+      last_name: "Foo",
       is_admin: true,
       is_active: true,
       is_invited: true,
     }
     @stub_token_status = 200
     @stub_token_scopes = ["all"]
+    ActionMailer::Base.deliveries = []
   end
 
   teardown do
@@ -110,6 +117,15 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     end
   end
 
+  def uncache_token(src)
+    if match = src.match(/\b(?:[a-z0-9]{5}-){2}[a-z0-9]{15}\b/)
+      tokens = ApiClientAuthorization.where(uuid: match[0])
+    else
+      tokens = ApiClientAuthorization.where("uuid like ?", "#{src}-%")
+    end
+    tokens.update_all(expires_at: "1995-05-15T01:02:03Z")
+  end
+
   test 'authenticate with remote token that has limited scope' do
     get '/arvados/v1/collections',
         params: {format: 'json'},
@@ -124,10 +140,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
         headers: auth(remote: 'zbbbb')
     assert_response :success
 
-    # simulate cache expiry
-    ApiClientAuthorization.where('uuid like ?', 'zbbbb-%').
-      update_all(expires_at: db_current_time - 1.minute)
-
+    uncache_token('zbbbb')
     # re-authorize after cache expires
     get '/arvados/v1/collections',
         params: {format: 'json'},
@@ -135,6 +148,14 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_response 403
   end
 
+  test "authenticate with remote token with limited initial scope" do
+    @stub_token_scopes = ["GET /arvados/v1/users/"]
+    get "/arvados/v1/users/#{@stub_content[:uuid]}",
+        params: {format: "json"},
+        headers: auth(remote: "zbbbb")
+    assert_response :success
+  end
+
   test 'authenticate with remote token' do
     get '/arvados/v1/users/current',
       params: {format: 'json'},
@@ -147,7 +168,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_equal 'barney', json_response['username']
 
     # revoke original token
-    @stub_status = 401
+    @stub_token_status = 401
 
     # re-authorize before cache expires
     get '/arvados/v1/users/current',
@@ -155,10 +176,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       headers: auth(remote: 'zbbbb')
     assert_response :success
 
-    # simulate cache expiry
-    ApiClientAuthorization.where('uuid like ?', 'zbbbb-%').
-      update_all(expires_at: db_current_time - 1.minute)
-
+    uncache_token('zbbbb')
     # re-authorize after cache expires
     get '/arvados/v1/users/current',
       params: {format: 'json'},
@@ -173,7 +191,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
       update_all(user_id: users(:active).id)
 
     # revive original token and re-authorize
-    @stub_status = 200
+    @stub_token_status = 200
     @stub_content[:username] = 'blarney'
     @stub_content[:email] = 'blarney@example.com'
     get '/arvados/v1/users/current',
@@ -196,11 +214,7 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     @stub_content[:is_active] = false
     @stub_content[:is_invited] = false
 
-    # simulate cache expiry
-    ApiClientAuthorization.where(
-      uuid: salted_active_token(remote: 'zbbbb').split('/')[1]).
-      update_all(expires_at: db_current_time - 1.minute)
-
+    uncache_token('zbbbb')
     # re-authorize after cache expires
     get '/arvados/v1/users/current',
       params: {format: 'json'},
@@ -355,6 +369,12 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
 
   test 'get user from Login cluster' do
     Rails.configuration.Login.LoginCluster = 'zbbbb'
+    email_dest = ActiveSupport::OrderedOptions.new
+    email_dest[:'arvados-admin@example.com'] = ActiveSupport::OrderedOptions.new
+    Rails.configuration.Users.UserNotifierEmailBcc = email_dest
+    Rails.configuration.Users.NewUserNotificationRecipients = email_dest
+    Rails.configuration.Users.NewInactiveUserNotificationRecipients = email_dest
+
     get '/arvados/v1/users/current',
       params: {format: 'json'},
       headers: auth(remote: 'zbbbb')
@@ -364,14 +384,18 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_equal true, json_response['is_active']
     assert_equal 'foo@example.com', json_response['email']
     assert_equal 'barney', json_response['username']
+
+    assert_equal 2, ActionMailer::Base.deliveries.length
+    assert_equal "Welcome to Arvados - account enabled", ActionMailer::Base.deliveries[0].subject
+    assert_equal "[ARVADOS] New user created notification", ActionMailer::Base.deliveries[1].subject
   end
 
   [true, false].each do |trusted|
     [true, false].each do |logincluster|
-      [true, false].each do |admin|
-        [true, false].each do |active|
+      [true, false, nil].each do |admin|
+        [true, false, nil].each do |active|
           [true, false].each do |autosetup|
-            [true, false].each do |invited|
+            [true, false, nil].each do |invited|
               test "get invited=#{invited}, active=#{active}, admin=#{admin} user from #{if logincluster then "Login" else "peer" end} cluster when AutoSetupNewUsers=#{autosetup} ActivateUsers=#{trusted}" do
                 Rails.configuration.Login.LoginCluster = 'zbbbb' if logincluster
                 Rails.configuration.RemoteClusters['zbbbb'].ActivateUsers = trusted
@@ -389,9 +413,9 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
                     headers: auth(remote: 'zbbbb')
                 assert_response :success
                 assert_equal 'zbbbb-tpzed-000000000000001', json_response['uuid']
-                assert_equal (logincluster && admin && invited && active), json_response['is_admin']
-                assert_equal (invited and (logincluster || trusted || autosetup)), json_response['is_invited']
-                assert_equal (invited and (logincluster || trusted) and active), json_response['is_active']
+                assert_equal (logincluster && !!admin && (invited != false) && !!active), json_response['is_admin']
+                assert_equal ((invited == true || (invited == nil && !!active)) && (logincluster || trusted || autosetup)), json_response['is_invited']
+                assert_equal ((invited != false) && (logincluster || trusted) && !!active), json_response['is_active']
                 assert_equal 'foo@example.com', json_response['email']
                 assert_equal 'barney', json_response['username']
               end
@@ -446,11 +470,8 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_equal 'foo@example.com', json_response['email']
     assert_equal 'barney', json_response['username']
 
-    # Delete cached value.  User should be inactive now.
-    act_as_system_user do
-      ApiClientAuthorization.delete_all
-    end
-
+    uncache_token('zbbbb')
+    # User should be inactive now.
     get '/arvados/v1/users/current',
       params: {format: 'json'},
       headers: auth(remote: 'zbbbb')
@@ -572,5 +593,40 @@ class RemoteUsersTest < ActionDispatch::IntegrationTest
     assert_equal 'zzzzz-tpzed-anonymouspublic', json_response['uuid']
   end
 
+  [401, 403, 422, 500, 502, 503].each do |status|
+    test "propagate #{status} response from getting remote token" do
+      @stub_token_status = status
+      get "/arvados/v1/users/#{@stub_content[:uuid]}",
+          params: {format: "json"},
+          headers: auth(remote: "zbbbb")
+      assert_response status
+    end
+
+    test "propagate #{status} response from getting uncached user" do
+      @stub_status = status
+      get "/arvados/v1/users/#{@stub_content[:uuid]}",
+          params: {format: "json"},
+          headers: auth(remote: "zbbbb")
+      assert_response status
+    end
 
+    test "use cached user after getting #{status} response" do
+      url_path = "/arvados/v1/users/#{@stub_content[:uuid]}"
+      params = {format: "json"}
+      headers = auth(remote: "zbbbb")
+
+      get url_path, params: params, headers: headers
+      assert_response :success
+
+      uncache_token(headers["HTTP_AUTHORIZATION"])
+      expect_email = @stub_content[:email]
+      @stub_content[:email] = "new#{expect_email}"
+      @stub_status = status
+      get url_path, params: params, headers: headers
+      assert_response :success
+      user = User.find_by_uuid(@stub_content[:uuid])
+      assert_not_nil user
+      assert_equal expect_email, user.email
+    end
+  end
 end