Merge branch '14328-watch-docker-ps'
[arvados.git] / services / api / test / functional / arvados / v1 / collections_controller_test.rb
index 4cf8778e6aede93043d574634f1ead00df952c03..26b8290e6961452e97f505ad3b239f6ef5a28596 100644 (file)
@@ -14,11 +14,21 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
     Rails.configuration.permit_create_collection_with_unsigned_manifest = isok
   end
 
-  def assert_signed_manifest manifest_text, label=''
+  def assert_signed_manifest manifest_text, label='', token: false
     assert_not_nil manifest_text, "#{label} manifest_text was nil"
     manifest_text.scan(/ [[:xdigit:]]{32}\S*/) do |tok|
       assert_match(PERM_TOKEN_RE, tok,
                    "Locator in #{label} manifest_text was not signed")
+      if token
+        bare = tok.gsub(/\+A[^\+]*/, '').sub(/^ /, '')
+        exp = tok[/\+A[[:xdigit:]]+@([[:xdigit:]]+)/, 1].to_i(16)
+        sig = Blob.sign_locator(
+          bare,
+          key: Rails.configuration.blob_signing_key,
+          expire: exp,
+          api_token: token)[/\+A[^\+]*/, 0]
+        assert_includes tok, sig
+      end
     end
   end
 
@@ -41,6 +51,19 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
     assert(assigns(:objects).andand.any?, "no Collections returned in index")
     refute(json_response["items"].any? { |c| c.has_key?("manifest_text") },
            "basic Collections index included manifest_text")
+    refute(json_response["items"].any? { |c| c["uuid"] == collections(:collection_owned_by_active_past_version_1).uuid },
+           "basic Collections index included past version")
+  end
+
+  test "get index with include_old_versions" do
+    authorize_with :active
+    get :index, {
+      include_old_versions: true
+    }
+    assert_response :success
+    assert(assigns(:objects).andand.any?, "no Collections returned in index")
+    assert(json_response["items"].any? { |c| c["uuid"] == collections(:collection_owned_by_active_past_version_1).uuid },
+           "past version not included on index")
   end
 
   test "collections.get returns signed locators, and no unsigned_manifest_text" do
@@ -52,6 +75,33 @@ class Arvados::V1::CollectionsControllerTest < ActionController::TestCase
     refute_includes json_response, 'unsigned_manifest_text'
   end
 
+  ['v1token', 'v2token'].each do |token_method|
+    test "correct signatures are given for #{token_method}" do
+      token = api_client_authorizations(:active).send(token_method)
+      authorize_with_token token
+      get :show, {id: collections(:foo_file).uuid}
+      assert_response :success
+      assert_signed_manifest json_response['manifest_text'], 'foo_file', token: token
+    end
+
+    test "signatures with #{token_method} are accepted" do
+      token = api_client_authorizations(:active).send(token_method)
+      signed = Blob.sign_locator(
+        'acbd18db4cc2f85cedef654fccc4a4d8+3',
+        key: Rails.configuration.blob_signing_key,
+        api_token: token)
+      authorize_with_token token
+      put :update, {
+            id: collections(:collection_owned_by_active).uuid,
+            collection: {
+              manifest_text: ". #{signed} 0:3:foo.txt\n",
+            },
+          }
+      assert_response :success
+      assert_signed_manifest json_response['manifest_text'], 'updated', token: token
+    end
+  end
+
   test "index with manifest_text selected returns signed locators" do
     columns = %w(uuid owner_uuid manifest_text)
     authorize_with :active
@@ -975,6 +1025,54 @@ EOS
     assert_response 200
   end
 
+  [:admin, :active].each do |user|
+    test "get trashed collection via filters and #{user} user" do
+      uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
+      authorize_with user
+      get :index, {
+        filters: [["current_version_uuid", "=", uuid]],
+        include_trash: true,
+      }
+      assert_response 200
+      # Only the current version is returned
+      assert_equal 1, json_response["items"].size
+    end
+  end
+
+  [:admin, :active].each do |user|
+    test "get trashed collection via filters and #{user} user, including its past versions" do
+      uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
+      authorize_with :admin
+      get :index, {
+        filters: [["current_version_uuid", "=", uuid]],
+        include_trash: true,
+        include_old_versions: true,
+      }
+      assert_response 200
+      # Both current & past version are returned
+      assert_equal 2, json_response["items"].size
+    end
+  end
+
+  test "trash collection also trash its past versions" do
+    uuid = collections(:collection_owned_by_active).uuid
+    authorize_with :active
+    versions = Collection.where(current_version_uuid: uuid)
+    assert_equal 2, versions.size
+    versions.each do |col|
+      refute col.is_trashed
+    end
+    post :trash, {
+      id: uuid,
+    }
+    assert_response 200
+    versions = Collection.where(current_version_uuid: uuid)
+    assert_equal 2, versions.size
+    versions.each do |col|
+      assert col.is_trashed
+    end
+  end
+
   test 'get trashed collection without include_trash' do
     uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
     authorize_with :active
@@ -991,7 +1089,7 @@ EOS
       id: uuid,
     }
     assert_response 200
-    c = Collection.unscoped.find_by_uuid(uuid)
+    c = Collection.find_by_uuid(uuid)
     assert_operator c.trash_at, :<, db_current_time
     assert_equal c.delete_at, c.trash_at + Rails.configuration.blob_signature_ttl
   end
@@ -1003,7 +1101,7 @@ EOS
       id: uuid,
     }
     assert_response 200
-    c = Collection.unscoped.find_by_uuid(uuid)
+    c = Collection.find_by_uuid(uuid)
     assert_operator c.trash_at, :<, db_current_time
     assert_operator c.delete_at, :<, db_current_time
   end
@@ -1023,7 +1121,7 @@ EOS
         id: uuid,
       }
       assert_response 200
-      c = Collection.unscoped.find_by_uuid(uuid)
+      c = Collection.find_by_uuid(uuid)
       assert_operator c.trash_at, :<, db_current_time
       assert_operator c.delete_at, :>=, time_before_trashing + Rails.configuration.default_trash_lifetime
     end
@@ -1112,7 +1210,7 @@ EOS
 
   test 'cannot index collection in trashed subproject' do
     authorize_with :active
-    get :index
+    get :index, { limit: 1000 }
     assert_response :success
     item_uuids = json_response['items'].map do |item|
       item['uuid']
@@ -1123,11 +1221,70 @@ EOS
   test 'can index collection in untrashed subproject' do
     authorize_with :active
     Group.find_by_uuid(groups(:trashed_project).uuid).update! is_trashed: false
-    get :index
+    get :index, { limit: 1000 }
+    assert_response :success
+    item_uuids = json_response['items'].map do |item|
+      item['uuid']
+    end
+    assert_includes(item_uuids, collections(:collection_in_trashed_subproject).uuid)
+  end
+
+  test 'can index trashed subproject collection with include_trash' do
+    authorize_with :active
+    get :index, {
+          include_trash: true,
+          limit: 1000
+        }
     assert_response :success
     item_uuids = json_response['items'].map do |item|
       item['uuid']
     end
     assert_includes(item_uuids, collections(:collection_in_trashed_subproject).uuid)
   end
+
+  test 'can get collection with past versions' do
+    authorize_with :active
+    get :index, {
+      filters: [['current_version_uuid','=',collections(:collection_owned_by_active).uuid]],
+      include_old_versions: true
+    }
+    assert_response :success
+    assert_equal 2, assigns(:objects).length
+    assert_equal 2, json_response['items_available']
+    assert_equal 2, json_response['items'].count
+    json_response['items'].each do |c|
+      assert_equal collections(:collection_owned_by_active).uuid,
+                   c['current_version_uuid'],
+                   'response includes a version from a different collection'
+    end
+  end
+
+  test 'can get old version collection by uuid' do
+    authorize_with :active
+    get :show, {
+      id: collections(:collection_owned_by_active_past_version_1).uuid,
+    }
+    assert_response :success
+    assert_equal collections(:collection_owned_by_active_past_version_1).name,
+                  json_response['name']
+  end
+
+  test 'version and current_version_uuid are ignored at creation time' do
+    permit_unsigned_manifests
+    authorize_with :active
+    manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
+    post :create, {
+      collection: {
+        name: 'Test collection',
+        version: 42,
+        current_version_uuid: collections(:collection_owned_by_active).uuid,
+        manifest_text: manifest_text,
+        # portable_data_hash: "d30fe8ae534397864cb96c544f4cf102+47"
+      }
+    }
+    assert_response :success
+    resp = JSON.parse(@response.body)
+    assert_equal 1, resp['version']
+    assert_equal resp['uuid'], resp['current_version_uuid']
+  end
 end