Merge branch 'master' into 14873-api-rails5-upgrade
authorLucas Di Pentima <ldipentima@veritasgenetics.com>
Fri, 5 Apr 2019 12:26:15 +0000 (09:26 -0300)
committerLucas Di Pentima <ldipentima@veritasgenetics.com>
Fri, 5 Apr 2019 12:26:15 +0000 (09:26 -0300)
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <ldipentima@veritasgenetics.com>

1  2 
services/api/app/models/collection.rb
services/api/db/structure.sql
services/api/test/functional/arvados/v1/collections_controller_test.rb

index e6d8d8655202a2c081d3a696ca4d9a409a027be6,578f25a62fc1eee9a081dfd6a9bac767a44e90d9..590228b1af354f0f10bad06171706f4ed88c05fa
@@@ -14,11 -14,9 +14,11 @@@ class Collection < ArvadosMode
    include CommonApiTemplate
    include Trashable
  
 -  serialize :properties, Hash
 -  serialize :storage_classes_desired, Array
 -  serialize :storage_classes_confirmed, Array
 +  # Posgresql JSONB columns should NOT be declared as serialized, Rails 5
 +  # already know how to properly treat them.
 +  attribute :properties, :jsonbHash, default: {}
 +  attribute :storage_classes_desired, :jsonbArray, default: ["default"]
 +  attribute :storage_classes_confirmed, :jsonbArray, default: []
  
    before_validation :default_empty_manifest
    before_validation :default_storage_classes, on: :create
@@@ -31,6 -29,7 +31,7 @@@
    validate :ensure_storage_classes_contain_non_empty_strings
    validate :versioning_metadata_updates, on: :update
    validate :past_versions_cannot_be_updated, on: :update
+   after_validation :set_file_count_and_total_size
    before_save :set_file_names
    around_update :manage_versioning
  
@@@ -53,6 -52,8 +54,8 @@@
      t.add :version
      t.add :current_version_uuid
      t.add :preserve_version
+     t.add :file_count
+     t.add :file_size_total
    end
  
    after_initialize do
@@@ -85,7 -86,7 +88,7 @@@
  
    FILE_TOKEN = /^[[:digit:]]+:[[:digit:]]+:/
    def check_signatures
 -    return false if self.manifest_text.nil?
 +    throw(:abort) if self.manifest_text.nil?
  
      return true if current_user.andand.is_admin
  
      true
    end
  
+   def set_file_count_and_total_size
+     # Only update the file stats if the manifest changed
+     if self.manifest_text_changed?
+       m = Keep::Manifest.new(self.manifest_text)
+       self.file_size_total = m.files_size
+       self.file_count = m.files_count
+     # If the manifest didn't change but the attributes did, ignore the changes
+     elsif self.file_count_changed? || self.file_size_total_changed?
+       self.file_count = self.file_count_was
+       self.file_size_total = self.file_size_total_was
+     end
+     true
+   end
    def manifest_files
      return '' if !self.manifest_text
  
    end
  
    def check_encoding
 -    if manifest_text.encoding.name == 'UTF-8' and manifest_text.valid_encoding?
 -      true
 -    else
 +    if !(manifest_text.encoding.name == 'UTF-8' and manifest_text.valid_encoding?)
        begin
          # If Ruby thinks the encoding is something else, like 7-bit
          # ASCII, but its stored bytes are equal to the (valid) UTF-8
        rescue
        end
        errors.add :manifest_text, "must use UTF-8 encoding"
 -      false
 +      throw(:abort)
      end
    end
  
        true
      rescue ArgumentError => e
        errors.add :manifest_text, e.message
 -      false
 +      throw(:abort)
      end
    end
  
index 95c44f7f665b5d59864bf994eb041f19c3e96b7f,4520e1bc04623e1a4a2f240ec2282c5308361785..cbe713a1c30dfb889dcb3932d3109b3b5be5ff5d
@@@ -105,18 -105,6 +105,18 @@@ CREATE SEQUENCE public.api_clients_id_s
  ALTER SEQUENCE public.api_clients_id_seq OWNED BY public.api_clients.id;
  
  
 +--
 +-- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: -
 +--
 +
 +CREATE TABLE public.ar_internal_metadata (
 +    key character varying NOT NULL,
 +    value character varying,
 +    created_at timestamp without time zone NOT NULL,
 +    updated_at timestamp without time zone NOT NULL
 +);
 +
 +
  --
  -- Name: authorized_keys; Type: TABLE; Schema: public; Owner: -
  --
@@@ -187,7 -175,9 +187,9 @@@ CREATE TABLE public.collections 
      storage_classes_confirmed_at timestamp without time zone,
      current_version_uuid character varying,
      version integer DEFAULT 1 NOT NULL,
-     preserve_version boolean DEFAULT false
+     preserve_version boolean DEFAULT false,
+     file_count integer DEFAULT 0 NOT NULL,
+     file_size_total bigint DEFAULT 0 NOT NULL
  );
  
  
@@@ -1420,14 -1410,6 +1422,14 @@@ ALTER TABLE ONLY public.api_client
      ADD CONSTRAINT api_clients_pkey PRIMARY KEY (id);
  
  
 +--
 +-- Name: ar_internal_metadata ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: -
 +--
 +
 +ALTER TABLE ONLY public.ar_internal_metadata
 +    ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key);
 +
 +
  --
  -- Name: authorized_keys authorized_keys_pkey; Type: CONSTRAINT; Schema: public; Owner: -
  --
@@@ -2872,190 -2854,373 +2874,192 @@@ CREATE INDEX workflows_search_idx ON pu
  
  SET search_path TO "$user", public;
  
 -INSERT INTO schema_migrations (version) VALUES ('20121016005009');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130105203021');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130105224358');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130105224618');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130107181109');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130107212832');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130109175700');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130109220548');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130113214204');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130116024233');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130116215213');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130118002239');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130122020042');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130122201442');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130122221616');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130123174514');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130123180224');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130123180228');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130125220425');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130128202518');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130128231343');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130130205749');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130203104818');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130203104824');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130203115329');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130207195855');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130218181504');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130226170000');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130313175417');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130315155820');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130315183626');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130315213205');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130318002138');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130319165853');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130319180730');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130319194637');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130319201431');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130319235957');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130320000107');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130326173804');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130326182917');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130415020241');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130425024459');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130425214427');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130523060112');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130523060213');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130524042319');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130528134100');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130606183519');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130608053730');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130610202538');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130611163736');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130612042554');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130617150007');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130626002829');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130626022810');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130627154537');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130627184333');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130708163414');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130708182912');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130708185153');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20130724153034');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20131007180607');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140117231056');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140124222114');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140129184311');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140317135600');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140319160547');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140321191343');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140324024606');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140325175653');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140402001908');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140407184311');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140421140924');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140421151939');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140421151940');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140422011506');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140423132913');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140423133559');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140501165548');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140519205916');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140527152921');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140530200539');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140601022548');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140602143352');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140607150616');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140611173003');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140627210837');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140709172343');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140714184006');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140811184643');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140817035914');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140818125735');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140826180337');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140828141043');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140909183946');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140911221252');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140918141529');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140918153541');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140918153705');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20140924091559');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20141111133038');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20141208164553');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20141208174553');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20141208174653');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20141208185217');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150122175935');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150123142953');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150203180223');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150206210804');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150206230342');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150216193428');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150303210106');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150312151136');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150317132720');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150324152204');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150423145759');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150512193020');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20150526180251');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20151202151426');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20151215134304');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20151229214707');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160208210629');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160209155729');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160324144017');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160506175108');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160509143250');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160808151559');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160819195557');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160819195725');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160901210110');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160909181442');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20160926194129');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161019171346');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161111143147');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161115171221');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161115174218');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161213172944');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161222153434');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20161223090712');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170102153111');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170105160301');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170105160302');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170216170823');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170301225558');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170319063406');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170328215436');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170330012505');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170419173031');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170419173712');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170419175801');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170628185847');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170704160233');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170706141334');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170824202826');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20170906224040');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20171027183824');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20171208203841');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20171212153352');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180216203422');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180228220311');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180313180114');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180501182859');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180514135529');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180607175050');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180608123145');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180806133039');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180820130357');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180820132617');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180820135808');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180824152014');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180824155207');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180904110712');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180913175443');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180915155335');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180917200000');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180917205609');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20180919001158');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20181001175023');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20181004131141');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20181005192222');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20181011184200');
 -
 -INSERT INTO schema_migrations (version) VALUES ('20181213183234');
 +INSERT INTO "schema_migrations" (version) VALUES
 +('20121016005009'),
 +('20130105203021'),
 +('20130105224358'),
 +('20130105224618'),
 +('20130107181109'),
 +('20130107212832'),
 +('20130109175700'),
 +('20130109220548'),
 +('20130113214204'),
 +('20130116024233'),
 +('20130116215213'),
 +('20130118002239'),
 +('20130122020042'),
 +('20130122201442'),
 +('20130122221616'),
 +('20130123174514'),
 +('20130123180224'),
 +('20130123180228'),
 +('20130125220425'),
 +('20130128202518'),
 +('20130128231343'),
 +('20130130205749'),
 +('20130203104818'),
 +('20130203104824'),
 +('20130203115329'),
 +('20130207195855'),
 +('20130218181504'),
 +('20130226170000'),
 +('20130313175417'),
 +('20130315155820'),
 +('20130315183626'),
 +('20130315213205'),
 +('20130318002138'),
 +('20130319165853'),
 +('20130319180730'),
 +('20130319194637'),
 +('20130319201431'),
 +('20130319235957'),
 +('20130320000107'),
 +('20130326173804'),
 +('20130326182917'),
 +('20130415020241'),
 +('20130425024459'),
 +('20130425214427'),
 +('20130523060112'),
 +('20130523060213'),
 +('20130524042319'),
 +('20130528134100'),
 +('20130606183519'),
 +('20130608053730'),
 +('20130610202538'),
 +('20130611163736'),
 +('20130612042554'),
 +('20130617150007'),
 +('20130626002829'),
 +('20130626022810'),
 +('20130627154537'),
 +('20130627184333'),
 +('20130708163414'),
 +('20130708182912'),
 +('20130708185153'),
 +('20130724153034'),
 +('20131007180607'),
 +('20140117231056'),
 +('20140124222114'),
 +('20140129184311'),
 +('20140317135600'),
 +('20140319160547'),
 +('20140321191343'),
 +('20140324024606'),
 +('20140325175653'),
 +('20140402001908'),
 +('20140407184311'),
 +('20140421140924'),
 +('20140421151939'),
 +('20140421151940'),
 +('20140422011506'),
 +('20140423132913'),
 +('20140423133559'),
 +('20140501165548'),
 +('20140519205916'),
 +('20140527152921'),
 +('20140530200539'),
 +('20140601022548'),
 +('20140602143352'),
 +('20140607150616'),
 +('20140611173003'),
 +('20140627210837'),
 +('20140709172343'),
 +('20140714184006'),
 +('20140811184643'),
 +('20140817035914'),
 +('20140818125735'),
 +('20140826180337'),
 +('20140828141043'),
 +('20140909183946'),
 +('20140911221252'),
 +('20140918141529'),
 +('20140918153541'),
 +('20140918153705'),
 +('20140924091559'),
 +('20141111133038'),
 +('20141208164553'),
 +('20141208174553'),
 +('20141208174653'),
 +('20141208185217'),
 +('20150122175935'),
 +('20150123142953'),
 +('20150203180223'),
 +('20150206210804'),
 +('20150206230342'),
 +('20150216193428'),
 +('20150303210106'),
 +('20150312151136'),
 +('20150317132720'),
 +('20150324152204'),
 +('20150423145759'),
 +('20150512193020'),
 +('20150526180251'),
 +('20151202151426'),
 +('20151215134304'),
 +('20151229214707'),
 +('20160208210629'),
 +('20160209155729'),
 +('20160324144017'),
 +('20160506175108'),
 +('20160509143250'),
 +('20160808151559'),
 +('20160819195557'),
 +('20160819195725'),
 +('20160901210110'),
 +('20160909181442'),
 +('20160926194129'),
 +('20161019171346'),
 +('20161111143147'),
 +('20161115171221'),
 +('20161115174218'),
 +('20161213172944'),
 +('20161222153434'),
 +('20161223090712'),
 +('20170102153111'),
 +('20170105160301'),
 +('20170105160302'),
 +('20170216170823'),
 +('20170301225558'),
 +('20170319063406'),
 +('20170328215436'),
 +('20170330012505'),
 +('20170419173031'),
 +('20170419173712'),
 +('20170419175801'),
 +('20170628185847'),
 +('20170704160233'),
 +('20170706141334'),
 +('20170824202826'),
 +('20170906224040'),
 +('20171027183824'),
 +('20171208203841'),
 +('20171212153352'),
 +('20180216203422'),
 +('20180228220311'),
 +('20180313180114'),
 +('20180501182859'),
 +('20180514135529'),
 +('20180607175050'),
 +('20180608123145'),
 +('20180806133039'),
 +('20180820130357'),
 +('20180820132617'),
 +('20180820135808'),
 +('20180824152014'),
 +('20180824155207'),
 +('20180904110712'),
 +('20180913175443'),
 +('20180915155335'),
 +('20180917200000'),
 +('20180917205609'),
 +('20180919001158'),
 +('20181001175023'),
 +('20181004131141'),
 +('20181005192222'),
 +('20181011184200'),
 +('20181213183234'),
 +('20190214214814');
  
 -INSERT INTO schema_migrations (version) VALUES ('20190214214814');
  
+ INSERT INTO schema_migrations (version) VALUES ('20190322174136');
index 2b2a736901e15d9aa081147b4a902c36b1d24089,ff581e44291d89a109f0228a2e4bf23399345c8d..72c83e515e349839cc6a4d11f6f3d5dac60b00d0
@@@ -57,7 -57,7 +57,7 @@@ class Arvados::V1::CollectionsControlle
  
    test "get index with include_old_versions" do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        include_old_versions: true
      }
      assert_response :success
@@@ -69,7 -69,7 +69,7 @@@
    test "collections.get returns signed locators, and no unsigned_manifest_text" do
      permit_unsigned_manifests
      authorize_with :active
 -    get :show, {id: collections(:foo_file).uuid}
 +    get :show, params: {id: collections(:foo_file).uuid}
      assert_response :success
      assert_signed_manifest json_response['manifest_text'], 'foo_file'
      refute_includes json_response, 'unsigned_manifest_text'
@@@ -79,7 -79,7 +79,7 @@@
      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}
 +      get :show, params: {id: collections(:foo_file).uuid}
        assert_response :success
        assert_signed_manifest json_response['manifest_text'], 'foo_file', token: token
      end
@@@ -91,7 -91,7 +91,7 @@@
          key: Rails.configuration.blob_signing_key,
          api_token: token)
        authorize_with_token token
 -      put :update, {
 +      put :update, params: {
              id: collections(:collection_owned_by_active).uuid,
              collection: {
                manifest_text: ". #{signed} 0:3:foo.txt\n",
    test "index with manifest_text selected returns signed locators" do
      columns = %w(uuid owner_uuid manifest_text)
      authorize_with :active
 -    get :index, select: columns
 +    get :index, params: {select: columns}
      assert_response :success
      assert(assigns(:objects).andand.any?,
             "no Collections returned for index with columns selected")
  
    test "index with unsigned_manifest_text selected returns only unsigned locators" do
      authorize_with :active
 -    get :index, select: ['unsigned_manifest_text']
 +    get :index, params: {select: ['unsigned_manifest_text']}
      assert_response :success
      assert_operator json_response["items"].count, :>, 0
      locs = 0
    ['', nil, false, 'null'].each do |select|
      test "index with select=#{select.inspect} returns everything except manifest" do
        authorize_with :active
 -      get :index, select: select
 +      get :index, params: {select: select}
        assert_response :success
        assert json_response['items'].any?
        json_response['items'].each do |coll|
     '["uuid", "manifest_text"]'].each do |select|
      test "index with select=#{select.inspect} returns no name" do
        authorize_with :active
 -      get :index, select: select
 +      get :index, params: {select: select}
        assert_response :success
        assert json_response['items'].any?
        json_response['items'].each do |coll|
    [0,1,2].each do |limit|
      test "get index with limit=#{limit}" do
        authorize_with :active
 -      get :index, limit: limit
 +      get :index, params: {limit: limit}
        assert_response :success
        assert_equal limit, assigns(:objects).count
        resp = JSON.parse(@response.body)
  
    test "items.count == items_available" do
      authorize_with :active
 -    get :index, limit: 100000
 +    get :index, params: {limit: 100000}
      assert_response :success
      resp = JSON.parse(@response.body)
      assert_equal resp['items_available'], assigns(:objects).length
  
    test "items.count == items_available with filters" do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        limit: 100,
        filters: [['uuid','=',collections(:foo_file).uuid]]
      }
    test "get index with limit=2 offset=99999" do
      # Assume there are not that many test fixtures.
      authorize_with :active
 -    get :index, limit: 2, offset: 99999
 +    get :index, params: {limit: 2, offset: 99999}
      assert_response :success
      assert_equal 0, assigns(:objects).count
      resp = JSON.parse(@response.body)
      coll1 = collections(:collection_1_of_201)
      Rails.configuration.max_index_database_read =
        yield(coll1.manifest_text.size)
 -    get :index, {
 +    get :index, params: {
        select: %w(uuid manifest_text),
        filters: [["owner_uuid", "=", coll1.owner_uuid]],
        limit: 300,
@@@ -301,7 -301,7 +301,7 @@@ EO
      # post :create will modify test_collection in place, so we save a copy first.
      # Hash.deep_dup is not sufficient as it preserves references of strings (??!?)
      post_collection = Marshal.load(Marshal.dump(test_collection))
 -    post :create, {
 +    post :create, params: {
        collection: post_collection
      }
  
        foo_collection = collections(:foo_file)
  
        # Get foo_file using its portable data hash
 -      get :show, {
 +      get :show, params: {
          id: foo_collection[:portable_data_hash]
        }
        assert_response :success
      permit_unsigned_manifests
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: 'zzzzz-j7d0g-rew6elm53kancon',
          manifest_text: manifest_text,
      permit_unsigned_manifests
      authorize_with :admin
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: 'zzzzz-tpzed-000000000000000',
          manifest_text: manifest_text,
        if !unsigned
          manifest_text = Collection.sign_manifest manifest_text, api_token(:active)
        end
 -      post :create, {
 +      post :create, params: {
          collection: {
            owner_uuid: users(:active).uuid,
            manifest_text: manifest_text,
      permit_unsigned_manifests
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: groups(:active_user_has_can_manage).uuid,
          manifest_text: manifest_text,
      permit_unsigned_manifests
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: groups(:all_users).uuid,
          manifest_text: manifest_text,
      permit_unsigned_manifests
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: groups(:public).uuid,
          manifest_text: manifest_text,
      permit_unsigned_manifests
      authorize_with :admin
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          owner_uuid: 'zzzzz-j7d0g-it30l961gq3t0oi',
          manifest_text: manifest_text,
    test "should create with collection passed as json" do
      permit_unsigned_manifests
      authorize_with :active
 -    post :create, {
 +    post :create, params: {
        collection: <<-EOS
        {
          "manifest_text":". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n",\
    test "should fail to create with checksum mismatch" do
      permit_unsigned_manifests
      authorize_with :active
 -    post :create, {
 +    post :create, params: {
        collection: <<-EOS
        {
          "manifest_text":". d41d8cd98f00b204e9800998ecf8427e 0:0:bar.txt\n",\
    test "collection UUID is normalized when created" do
      permit_unsigned_manifests
      authorize_with :active
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n",
          portable_data_hash: "d30fe8ae534397864cb96c544f4cf102+47+Khint+Xhint+Zhint"
  
    test "get full provenance for baz file" do
      authorize_with :active
 -    get :provenance, id: 'ea10d51bcf88862dbcc36eb292017dfd+45'
 +    get :provenance, params: {id: 'ea10d51bcf88862dbcc36eb292017dfd+45'}
      assert_response :success
      resp = JSON.parse(@response.body)
      assert_not_nil resp['ea10d51bcf88862dbcc36eb292017dfd+45'] # baz
    test "get no provenance for foo file" do
      # spectator user cannot even see baz collection
      authorize_with :spectator
 -    get :provenance, id: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'
 +    get :provenance, params: {id: '1f4b0bc7583c2a7f9102c395f4ffc5e3+45'}
      assert_response 404
    end
  
    test "get partial provenance for baz file" do
      # spectator user can see bar->baz job, but not foo->bar job
      authorize_with :spectator
 -    get :provenance, id: 'ea10d51bcf88862dbcc36eb292017dfd+45'
 +    get :provenance, params: {id: 'ea10d51bcf88862dbcc36eb292017dfd+45'}
      assert_response :success
      resp = JSON.parse(@response.body)
      assert_not_nil resp['ea10d51bcf88862dbcc36eb292017dfd+45'] # baz
    test "search collections with 'any' operator" do
      expect_pdh = collections(:docker_image).portable_data_hash
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        where: { any: ['contains', expect_pdh[5..25]] }
      }
      assert_response :success
          ". " + signed_locators[1] + " 0:0:foo.txt\n" +
          ". " + signed_locators[2] + " 0:0:foo.txt\n"
  
 -      post :create, {
 +      post :create, params: {
          collection: {
            manifest_text: signed_manifest,
            portable_data_hash: manifest_uuid,
        ". " + Blob.sign_locator(locators[1], signing_opts) + " 0:0:foo.txt\n" +
        ". " + Blob.sign_locator(locators[2], signing_opts) + " 0:0:foo.txt\n"
  
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: signed_manifest,
          portable_data_hash: manifest_uuid,
        unsigned_manifest.length.to_s
  
      bad_manifest = ". #{bad_locator} 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: bad_manifest,
          portable_data_hash: manifest_uuid
        '+' +
        signed_manifest.length.to_s
  
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: signed_manifest,
          portable_data_hash: manifest_uuid
  
    test "reject manifest with unsigned block as stream name" do
      authorize_with :active
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: "00000000000000000000000000000000+1234 d41d8cd98f00b204e9800998ecf8427e+0 0:0:foo.txt\n"
        }
        portable_data_hash: manifest_uuid,
      }
      post_collection = Marshal.load(Marshal.dump(test_collection))
 -    post :create, {
 +    post :create, params: {
        collection: post_collection
      }
      assert_response :success
      signed_locators = locators.map { |loc| Blob.sign_locator loc, signing_opts }
      signed_manifest = [".", *signed_locators, "0:0:foo.txt\n"].join(" ")
  
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: signed_manifest,
          portable_data_hash: manifest_uuid,
      authorize_with :active
      unsigned_manifest = ". 0cc175b9c0f1b6a831c399e269772661+1 0:1:a.txt\n"
      manifest_uuid = Digest::MD5.hexdigest(unsigned_manifest)
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: unsigned_manifest,
          portable_data_hash: manifest_uuid,
  
    test 'List expired collection returns empty list' do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        where: {name: 'expired_collection'},
      }
      assert_response :success
  
    test 'Show expired collection returns 404' do
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: 'zzzzz-4zz18-mto52zx1s7sn3ih',
      }
      assert_response 404
  
    test 'Update expired collection returns 404' do
      authorize_with :active
 -    post :update, {
 +    post :update, params: {
        id: 'zzzzz-4zz18-mto52zx1s7sn3ih',
        collection: {
          name: "still expired"
  
    test 'List collection with future expiration time succeeds' do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        where: {name: 'collection_expires_in_future'},
      }
      found = assigns(:objects)
  
    test 'Show collection with future expiration time succeeds' do
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: 'zzzzz-4zz18-padkqo7yb8d9i3j',
      }
      assert_response :success
  
    test 'Update collection with future expiration time succeeds' do
      authorize_with :active
 -    post :update, {
 +    post :update, params: {
        id: 'zzzzz-4zz18-padkqo7yb8d9i3j',
        collection: {
          name: "still not expired"
  
    test "get collection and verify that file_names is not included" do
      authorize_with :active
 -    get :show, {id: collections(:foo_file).uuid}
 +    get :show, params: {id: collections(:foo_file).uuid}
      assert_response :success
      assert_equal collections(:foo_file).uuid, json_response['uuid']
      assert_nil json_response['file_names']
          description = description + description
        end
  
 -      post :create, collection: {
 -        manifest_text: ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:foo.txt\n",
 -        description: description,
 +      post :create, params: {
 +        collection: {
 +          manifest_text: ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:foo.txt\n",
 +          description: description,
 +        }
        }
  
        assert_response expected_response
      test "Set replication_desired=#{ask.inspect}" do
        Rails.configuration.default_collection_replication = 2
        authorize_with :active
 -      put :update, {
 +      put :update, params: {
          id: collections(:replication_undesired_unconfirmed).uuid,
          collection: {
            replication_desired: ask,
  
    test "get collection with properties" do
      authorize_with :active
 -    get :show, {id: collections(:collection_with_one_property).uuid}
 +    get :show, params: {id: collections(:collection_with_one_property).uuid}
      assert_response :success
      assert_not_nil json_response['uuid']
      assert_equal 'value1', json_response['properties']['property1']
    test "create collection with properties" do
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          manifest_text: manifest_text,
          portable_data_hash: "d30fe8ae534397864cb96c544f4cf102+47",
      assert_equal 'value_1', json_response['properties']['property_1']
    end
  
+   [
+     [". d41d8cd98f00b204e9800998ecf8427e 0:34:foo.txt\n", 1, 34],
+     [". d41d8cd98f00b204e9800998ecf8427e 0:34:foo.txt 0:30:foo.txt 0:30:foo1.txt 0:30:foo2.txt 0:30:foo3.txt 0:30:foo4.txt\n", 5, 184],
+     [". d41d8cd98f00b204e9800998ecf8427e 0:0:.\n", 0, 0]
+   ].each do |manifest, count, size|
+     test "create collection with valid manifest #{manifest} and expect file stats" do
+       authorize_with :active
+       post :create, {
+         collection: {
+           manifest_text: manifest
+         }
+       }
+       assert_response 200
+       assert_equal count, json_response['file_count']
+       assert_equal size, json_response['file_size_total']
+     end
+   end
+   test "update collection manifest and expect new file stats" do
+     authorize_with :active
+     post :update, {
+       id: collections(:collection_owned_by_active_with_file_stats).uuid,
+       collection: {
+         manifest_text: ". d41d8cd98f00b204e9800998ecf8427e 0:34:foo.txt\n"
+       }
+     }
+     assert_response 200
+     assert_equal 1, json_response['file_count']
+     assert_equal 34, json_response['file_size_total']
+   end
+   [
+     ['file_count', 1],
+     ['file_size_total', 34]
+   ].each do |attribute, val|
+     test "create collection with #{attribute} and expect overwrite" do
+       authorize_with :active
+       post :create, {
+         collection: {
+           manifest_text: ". d41d8cd98f00b204e9800998ecf8427e 0:34:foo.txt\n",
+           "#{attribute}": 10
+         }
+       }
+       assert_response 200
+       assert_equal val, json_response[attribute]
+     end
+   end
+   [
+     ['file_count', 1],
+     ['file_size_total', 3]
+   ].each do |attribute, val|
+     test "update collection with #{attribute} and expect ignore" do
+       authorize_with :active
+       post :update, {
+         id: collections(:collection_owned_by_active_with_file_stats).uuid,
+         collection: {
+           "#{attribute}": 10
+         }
+       }
+       assert_response 200
+       assert_equal val, json_response[attribute]
+     end
+   end
+   [
+     ['file_count', 1],
+     ['file_size_total', 34]
+   ].each do |attribute, val|
+     test "update collection with #{attribute} and manifest and expect manifest values" do
+       authorize_with :active
+       post :update, {
+         id: collections(:collection_owned_by_active_with_file_stats).uuid,
+         collection: {
+           manifest_text: ". d41d8cd98f00b204e9800998ecf8427e 0:34:foo.txt\n",
+           "#{attribute}": 10
+         }
+       }
+       assert_response 200
+       assert_equal val, json_response[attribute]
+     end
+   end
    [
      ". 0:0:foo.txt",
      ". d41d8cd98f00b204e9800998ecf8427e foo.txt",
    ].each do |manifest_text|
      test "create collection with invalid manifest #{manifest_text} and expect error" do
        authorize_with :active
 -      post :create, {
 +      post :create, params: {
          collection: {
            manifest_text: manifest_text,
            portable_data_hash: "d41d8cd98f00b204e9800998ecf8427e+0"
    ].each do |manifest_text, pdh|
      test "create collection with valid manifest #{manifest_text.inspect} and expect success" do
        authorize_with :active
 -      post :create, {
 +      post :create, params: {
          collection: {
            manifest_text: manifest_text,
            portable_data_hash: pdh
    ].each do |manifest_text|
      test "update collection with invalid manifest #{manifest_text} and expect error" do
        authorize_with :active
 -      post :update, {
 +      post :update, params: {
          id: 'zzzzz-4zz18-bv31uwvy3neko21',
          collection: {
            manifest_text: manifest_text,
    ].each do |manifest_text|
      test "update collection with valid manifest #{manifest_text.inspect} and expect success" do
        authorize_with :active
 -      post :update, {
 +      post :update, params: {
          id: 'zzzzz-4zz18-bv31uwvy3neko21',
          collection: {
            manifest_text: manifest_text,
    test 'get trashed collection with include_trash' do
      uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: uuid,
        include_trash: true,
      }
      test "get trashed collection via filters and #{user} user" do
        uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
        authorize_with user
 -      get :index, {
 +      get :index, params: {
          filters: [["current_version_uuid", "=", uuid]],
          include_trash: true,
        }
      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, {
 +      get :index, params: {
          filters: [["current_version_uuid", "=", uuid]],
          include_trash: true,
          include_old_versions: true,
      versions.each do |col|
        refute col.is_trashed
      end
 -    post :trash, {
 +    post :trash, params: {
        id: uuid,
      }
      assert_response 200
    test 'get trashed collection without include_trash' do
      uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: uuid,
      }
      assert_response 404
    test 'trash collection using http DELETE verb' do
      uuid = collections(:collection_owned_by_active).uuid
      authorize_with :active
 -    delete :destroy, {
 +    delete :destroy, params: {
        id: uuid,
      }
      assert_response 200
    test 'delete long-trashed collection immediately using http DELETE verb' do
      uuid = 'zzzzz-4zz18-mto52zx1s7sn3ih' # expired_collection
      authorize_with :active
 -    delete :destroy, {
 +    delete :destroy, params: {
        id: uuid,
      }
      assert_response 200
        end
        authorize_with :active
        time_before_trashing = db_current_time
 -      post :trash, {
 +      post :trash, params: {
          id: uuid,
        }
        assert_response 200
  
    test 'untrash a trashed collection' do
      authorize_with :active
 -    post :untrash, {
 +    post :untrash, params: {
        id: collections(:expired_collection).uuid,
      }
      assert_response 200
  
    test 'untrash error on not trashed collection' do
      authorize_with :active
 -    post :untrash, {
 +    post :untrash, params: {
        id: collections(:collection_owned_by_active).uuid,
      }
      assert_response 422
    [:active, :admin].each do |user|
      test "get trashed collections as #{user}" do
        authorize_with user
 -      get :index, {
 +      get :index, params: {
          filters: [["is_trashed", "=", true]],
          include_trash: true,
        }
  
    test 'untrash collection with same name as another with no ensure unique name' do
      authorize_with :active
 -    post :untrash, {
 +    post :untrash, params: {
        id: collections(:trashed_collection_to_test_name_conflict_on_untrash).uuid,
      }
      assert_response 422
  
    test 'untrash collection with same name as another with ensure unique name' do
      authorize_with :active
 -    post :untrash, {
 +    post :untrash, params: {
        id: collections(:trashed_collection_to_test_name_conflict_on_untrash).uuid,
        ensure_unique_name: true
      }
  
    test 'cannot show collection in trashed subproject' do
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: collections(:collection_in_trashed_subproject).uuid,
        format: :json
      }
    test 'can show collection in untrashed subproject' do
      authorize_with :active
      Group.find_by_uuid(groups(:trashed_project).uuid).update! is_trashed: false
 -    get :show, {
 +    get :show, params: {
        id: collections(:collection_in_trashed_subproject).uuid,
        format: :json,
      }
  
    test 'cannot index collection in trashed subproject' do
      authorize_with :active
 -    get :index, { limit: 1000 }
 +    get :index, params: { limit: 1000 }
      assert_response :success
      item_uuids = json_response['items'].map do |item|
        item['uuid']
    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, { limit: 1000 }
 +    get :index, params: { limit: 1000 }
      assert_response :success
      item_uuids = json_response['items'].map do |item|
        item['uuid']
  
    test 'can index trashed subproject collection with include_trash' do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
            include_trash: true,
            limit: 1000
          }
  
    test 'can get collection with past versions' do
      authorize_with :active
 -    get :index, {
 +    get :index, params: {
        filters: [['current_version_uuid','=',collections(:collection_owned_by_active).uuid]],
        include_old_versions: true
      }
  
    test 'can get old version collection by uuid' do
      authorize_with :active
 -    get :show, {
 +    get :show, params: {
        id: collections(:collection_owned_by_active_past_version_1).uuid,
      }
      assert_response :success
      permit_unsigned_manifests
      authorize_with :active
      manifest_text = ". d41d8cd98f00b204e9800998ecf8427e 0:0:foo.txt\n"
 -    post :create, {
 +    post :create, params: {
        collection: {
          name: 'Test collection',
          version: 42,
        key: Rails.configuration.blob_signing_key,
        api_token: token)
      authorize_with_token token
 -    put :update, {
 +    put :update, params: {
            id: col.uuid,
            collection: {
              manifest_text: ". #{signed} 0:3:foo.txt\n",