valkyrie 1.1.2 → 1.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +5 -0
  4. data/CHANGELOG.md +28 -0
  5. data/README.md +43 -7
  6. data/db/migrate/20180802220739_add_optimistic_locking_to_orm_resources.rb +6 -0
  7. data/lib/generators/valkyrie/templates/resource.rb.erb +0 -1
  8. data/lib/valkyrie/change_set.rb +4 -0
  9. data/lib/valkyrie/id.rb +5 -0
  10. data/lib/valkyrie/metadata_adapter.rb +1 -0
  11. data/lib/valkyrie/persistence/composite_persister.rb +12 -1
  12. data/lib/valkyrie/persistence/fedora/list_node.rb +3 -3
  13. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +4 -0
  14. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +5 -0
  15. data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +0 -1
  16. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +2 -0
  17. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +33 -3
  18. data/lib/valkyrie/persistence/fedora/persister.rb +57 -16
  19. data/lib/valkyrie/persistence/fedora/query_service.rb +2 -0
  20. data/lib/valkyrie/persistence/fedora.rb +2 -0
  21. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +4 -0
  22. data/lib/valkyrie/persistence/memory/persister.rb +37 -14
  23. data/lib/valkyrie/persistence/memory/query_service.rb +2 -0
  24. data/lib/valkyrie/persistence/optimistic_lock_token.rb +34 -0
  25. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +11 -2
  26. data/lib/valkyrie/persistence/postgres/orm_converter.rb +35 -5
  27. data/lib/valkyrie/persistence/postgres/persister.rb +10 -12
  28. data/lib/valkyrie/persistence/postgres/query_service.rb +5 -4
  29. data/lib/valkyrie/persistence/postgres/resource_converter.rb +21 -1
  30. data/lib/valkyrie/persistence/postgres/resource_factory.rb +22 -18
  31. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +5 -1
  32. data/lib/valkyrie/persistence/solr/model_converter.rb +32 -2
  33. data/lib/valkyrie/persistence/solr/orm_converter.rb +22 -5
  34. data/lib/valkyrie/persistence/solr/persister.rb +2 -0
  35. data/lib/valkyrie/persistence/solr/query_service.rb +2 -0
  36. data/lib/valkyrie/persistence/solr/repository.rb +21 -8
  37. data/lib/valkyrie/persistence/solr/resource_factory.rb +6 -3
  38. data/lib/valkyrie/persistence.rb +10 -3
  39. data/lib/valkyrie/resource/access_controls.rb +0 -1
  40. data/lib/valkyrie/resource.rb +31 -8
  41. data/lib/valkyrie/specs/shared_specs/change_set_persister.rb +0 -1
  42. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +9 -0
  43. data/lib/valkyrie/specs/shared_specs/persister.rb +134 -7
  44. data/lib/valkyrie/specs/shared_specs/queries.rb +20 -2
  45. data/lib/valkyrie/specs/shared_specs/resource.rb +0 -1
  46. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +0 -1
  47. data/lib/valkyrie/storage/fedora.rb +29 -20
  48. data/lib/valkyrie/types.rb +11 -1
  49. data/lib/valkyrie/version.rb +1 -1
  50. data/lib/valkyrie.rb +0 -2
  51. metadata +7 -6
  52. data/config/fedora.yml +0 -10
@@ -4,12 +4,11 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
4
4
  raise 'persister must be set with `let(:persister)`' unless defined? persister
5
5
  class CustomResource < Valkyrie::Resource
6
6
  include Valkyrie::Resource::AccessControls
7
- attribute :id, Valkyrie::Types::ID.optional
8
7
  attribute :title
9
8
  attribute :author
10
9
  attribute :member_ids
11
10
  attribute :nested_resource
12
- attribute :single_value, Valkyrie::Types::String
11
+ attribute :single_value, Valkyrie::Types::String.optional
13
12
  end
14
13
  end
15
14
  after do
@@ -31,16 +30,12 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
31
30
  expect(saved.id).not_to be_blank
32
31
  end
33
32
 
34
- it "does not save non-array properties" do
35
- resource.single_value = "A Single Value"
36
- expect { persister.save(resource: resource) }.to raise_error ::Valkyrie::Persistence::UnsupportedDatatype
37
- end
38
-
39
33
  it "can save multiple resources at once" do
40
34
  resource2 = resource_class.new
41
35
  results = persister.save_all(resources: [resource, resource2])
42
36
 
43
37
  expect(results.map(&:id).uniq.length).to eq 2
38
+ expect(persister.save_all(resources: [])).to eq []
44
39
  end
45
40
 
46
41
  it "can save nested resources" do
@@ -51,6 +46,20 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
51
46
  expect(reloaded.nested_resource.first.title).to eq ["Nested"]
52
47
  end
53
48
 
49
+ it "can persist single values" do
50
+ resource.single_value = "A single value"
51
+
52
+ output = persister.save(resource: resource)
53
+
54
+ expect(output.single_value).to eq "A single value"
55
+ end
56
+
57
+ it "returns nil for an unset single value" do
58
+ output = persister.save(resource: resource_class.new)
59
+
60
+ expect(output.single_value).to be_nil
61
+ end
62
+
54
63
  it "can mix properties with nested resources" do
55
64
  pending "No support for mixed nesting." if flags.include?(:no_mixed_nesting)
56
65
  book2 = resource_class.new(title: "Nested", id: SecureRandom.uuid)
@@ -281,4 +290,122 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
281
290
  persister.wipe!
282
291
  expect(query_service.find_all.to_a.length).to eq 0
283
292
  end
293
+
294
+ context "optimistic locking" do
295
+ before do
296
+ class MyLockingResource < Valkyrie::Resource
297
+ enable_optimistic_locking
298
+ attribute :title
299
+ end
300
+ end
301
+
302
+ after do
303
+ ActiveSupport::Dependencies.remove_constant("MyLockingResource")
304
+ end
305
+
306
+ describe "#save" do
307
+ context "when creating a resource" do
308
+ it "returns the value of the system-generated optimistic locking attribute on the resource" do
309
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
310
+ saved_resource = persister.save(resource: resource)
311
+ expect(saved_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
312
+ end
313
+ end
314
+
315
+ context "when updating a resource with a correct lock token" do
316
+ it "successfully saves the resource and returns the updated value of the optimistic locking attribute" do
317
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
318
+ initial_resource = persister.save(resource: resource)
319
+ updated_resource = persister.save(resource: initial_resource)
320
+ expect(initial_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK])
321
+ .not_to eq updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
322
+ end
323
+ end
324
+
325
+ context "when updating a resource with an incorrect lock token" do
326
+ it "raises a Valkyrie::Persistence::StaleObjectError" do
327
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
328
+ resource = persister.save(resource: resource)
329
+ # update the resource in the datastore to make its token stale
330
+ persister.save(resource: resource)
331
+
332
+ expect { persister.save(resource: resource) }.to raise_error(Valkyrie::Persistence::StaleObjectError, resource.id.to_s)
333
+ end
334
+ end
335
+
336
+ context "when lock token is nil" do
337
+ it "successfully saves the resource and returns the updated value of the optimistic locking attribute" do
338
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
339
+ initial_resource = persister.save(resource: resource)
340
+ initial_token = initial_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first
341
+ initial_resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", [])
342
+ updated_resource = persister.save(resource: initial_resource)
343
+ expect(initial_token.serialize)
344
+ .not_to eq(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first.serialize)
345
+ expect(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
346
+ end
347
+ end
348
+
349
+ context "when there is a token, but it's for a different adapter (migration use case)" do
350
+ it "successfully saves the resource and returns a token for the adapter that was saved to" do
351
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
352
+ initial_resource = persister.save(resource: resource)
353
+ new_token = Valkyrie::Persistence::OptimisticLockToken.new(
354
+ adapter_id: Valkyrie::ID.new("fake_adapter"),
355
+ token: "token"
356
+ )
357
+ initial_resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", [new_token])
358
+ updated_resource = persister.save(resource: initial_resource)
359
+ expect(new_token.serialize)
360
+ .not_to eq(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first.serialize)
361
+ expect(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
362
+ end
363
+ end
364
+ end
365
+
366
+ describe "#save_all" do
367
+ context "when creating multiple resources" do
368
+ it "returns an array of resources with their system-generated optimistic locking attributes" do
369
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
370
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
371
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
372
+ saved_resources = persister.save_all(resources: [resource1, resource2, resource3])
373
+ saved_resources.each do |saved_resource|
374
+ expect(saved_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
375
+ end
376
+ end
377
+ end
378
+
379
+ context "when updating multiple resources that all have a correct lock token" do
380
+ it "saves the resources and returns them with updated values of the optimistic locking attribute" do
381
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
382
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
383
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
384
+ saved_resources = persister.save_all(resources: [resource1, resource2, resource3])
385
+ initial_lock_tokens = saved_resources.map do |r|
386
+ r[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
387
+ end
388
+ updated_resources = persister.save_all(resources: saved_resources)
389
+ updated_lock_tokens = updated_resources.map do |r|
390
+ r[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
391
+ end
392
+ expect(initial_lock_tokens & updated_lock_tokens).to be_empty
393
+ end
394
+ end
395
+
396
+ context "when one of the resources has an incorrect lock token" do
397
+ it "raises a Valkyrie::Persistence::StaleObjectError" do
398
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
399
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
400
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
401
+ resource1, resource2, resource3 = persister.save_all(resources: [resource1, resource2, resource3])
402
+ # update a resource in the datastore to make its token stale
403
+ persister.save(resource: resource2)
404
+
405
+ expect { persister.save_all(resources: [resource1, resource2, resource3]) }
406
+ .to raise_error(Valkyrie::Persistence::StaleObjectError, "Valkyrie::Persistence::StaleObjectError")
407
+ end
408
+ end
409
+ end
410
+ end
284
411
  end
@@ -4,14 +4,12 @@ RSpec.shared_examples 'a Valkyrie query provider' do
4
4
  raise 'adapter must be set with `let(:adapter)`' unless
5
5
  defined? adapter
6
6
  class CustomResource < Valkyrie::Resource
7
- attribute :id, Valkyrie::Types::ID.optional
8
7
  attribute :alternate_ids, Valkyrie::Types::Array
9
8
  attribute :title
10
9
  attribute :member_ids, Valkyrie::Types::Array
11
10
  attribute :a_member_of
12
11
  end
13
12
  class SecondResource < Valkyrie::Resource
14
- attribute :id, Valkyrie::Types::ID.optional
15
13
  end
16
14
  end
17
15
  after do
@@ -291,4 +289,24 @@ RSpec.shared_examples 'a Valkyrie query provider' do
291
289
  expect(query_service.custom_queries.find_by_user_id).to eq 1
292
290
  end
293
291
  end
292
+
293
+ context "optimistic locking" do
294
+ before do
295
+ class CustomLockingQueryResource < Valkyrie::Resource
296
+ enable_optimistic_locking
297
+ attribute :title
298
+ end
299
+ end
300
+ after do
301
+ Object.send(:remove_const, :CustomLockingQueryResource)
302
+ end
303
+
304
+ it "retrieves the lock token and casts it to optimistic_lock_token attribute" do
305
+ resource = CustomLockingQueryResource.new(title: "My Title")
306
+ resource = persister.save(resource: resource)
307
+ resource = query_service.find_by(id: resource.id)
308
+ # we can't know the value in the general case
309
+ expect(resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
310
+ end
311
+ end
294
312
  end
@@ -53,7 +53,6 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
53
53
  describe "#human_readable_type" do
54
54
  before do
55
55
  class MyCustomResource < Valkyrie::Resource
56
- attribute :id, Valkyrie::Types::ID.optional
57
56
  attribute :title, Valkyrie::Types::Set
58
57
  end
59
58
  end
@@ -6,7 +6,6 @@ RSpec.shared_examples 'a Valkyrie::StorageAdapter' do
6
6
  raise 'file must be set with `let(:file)`' unless
7
7
  defined? file
8
8
  class CustomResource < Valkyrie::Resource
9
- attribute :id, Valkyrie::Types::ID.optional
10
9
  end
11
10
  end
12
11
  after do
@@ -2,10 +2,13 @@
2
2
  module Valkyrie::Storage
3
3
  # Implements the DataMapper Pattern to store binary data in fedora
4
4
  class Fedora
5
- attr_reader :connection
5
+ attr_reader :connection, :base_path
6
6
  PROTOCOL = 'fedora://'
7
- def initialize(connection:)
7
+
8
+ # @param [Ldp::Client] connection
9
+ def initialize(connection:, base_path: "/")
8
10
  @connection = connection
11
+ @base_path = base_path
9
12
  end
10
13
 
11
14
  # @param id [Valkyrie::ID]
@@ -29,14 +32,13 @@ module Valkyrie::Storage
29
32
  # @param resource [Valkyrie::Resource]
30
33
  # @return [Valkyrie::StorageAdapter::StreamFile]
31
34
  def upload(file:, original_filename:, resource:)
32
- # TODO: this is a very naive aproach. Change to PCDM
33
- identifier = resource.id.to_uri + '/original'
34
- ActiveFedora::File.new(identifier) do |af|
35
- af.content = file
36
- af.original_name = original_filename
37
- af.save!
38
- af.metadata.set_value(:type, af.metadata.type + [::RDF::URI('http://pcdm.org/use#OriginalFile')])
39
- af.metadata.save
35
+ identifier = id_to_uri(resource.id) + '/original'
36
+ connection.http.put do |request|
37
+ request.url identifier
38
+ request.headers['Content-Type'] = file.content_type
39
+ request.headers['Content-Disposition'] = "attachment; filename=\"#{original_filename}\""
40
+ request.headers['digest'] = "sha1=#{Digest::SHA1.file(file)}"
41
+ request.body = file.tempfile.read
40
42
  end
41
43
  find_by(id: Valkyrie::ID.new(identifier.to_s.sub(/^.+\/\//, PROTOCOL)))
42
44
  end
@@ -44,22 +46,22 @@ module Valkyrie::Storage
44
46
  # Delete the file in Fedora associated with the given identifier.
45
47
  # @param id [Valkyrie::ID]
46
48
  def delete(id:)
47
- ActiveFedora::File.new(active_fedora_identifier(id: id)).ldp_source.delete
49
+ connection.http.delete(fedora_identifier(id: id))
48
50
  end
49
51
 
50
52
  class IOProxy
51
53
  # @param response [Ldp::Resource::BinarySource]
52
54
  attr_reader :size
53
- def initialize(source, size)
55
+ def initialize(source)
54
56
  @source = source
55
- @size = size
57
+ @size = source.size
56
58
  end
57
59
  delegate :each, :read, :rewind, to: :io
58
60
 
59
61
  # There is no streaming support in faraday (https://github.com/lostisland/faraday/pull/604)
60
62
  # @return [StringIO]
61
63
  def io
62
- @io ||= StringIO.new(@source.get.response.body)
64
+ @io ||= StringIO.new(@source)
63
65
  end
64
66
  end
65
67
  private_constant :IOProxy
@@ -68,17 +70,24 @@ module Valkyrie::Storage
68
70
 
69
71
  # @return [IOProxy]
70
72
  def response(id:)
71
- af_file = ActiveFedora::File.new(active_fedora_identifier(id: id))
72
- raise Valkyrie::StorageAdapter::FileNotFound if af_file.ldp_source.new?
73
- IOProxy.new(af_file.ldp_source, af_file.size)
73
+ response = connection.http.get(fedora_identifier(id: id))
74
+ raise Valkyrie::StorageAdapter::FileNotFound unless response.success?
75
+ IOProxy.new(response.body)
74
76
  end
75
77
 
76
78
  # Translate the Valkrie ID into a URL for the fedora file
77
79
  # @return [RDF::URI]
78
- def active_fedora_identifier(id:)
79
- scheme = URI(ActiveFedora.config.credentials[:url]).scheme
80
- identifier = id.to_s.sub(PROTOCOL, "#{scheme}://")
80
+ def fedora_identifier(id:)
81
+ identifier = id.to_s.sub(PROTOCOL, "#{connection.http.scheme}://")
81
82
  RDF::URI(identifier)
82
83
  end
84
+
85
+ def id_to_uri(id)
86
+ RDF::URI("#{connection_prefix}/#{CGI.escape(id.to_s)}")
87
+ end
88
+
89
+ def connection_prefix
90
+ "#{connection.http.url_prefix}/#{base_path}"
91
+ end
83
92
  end
84
93
  end
@@ -3,9 +3,11 @@ module Valkyrie
3
3
  # Namespace for Dry::Types types.
4
4
  # Includes Dry::Types built-in types and defines custom Valkyrie types
5
5
  #
6
+ # Types allow your models to automatically cast attributes to the appropriate type
7
+ # or even fail to instantiate should you give an inappropriate type.
8
+ #
6
9
  # @example Use types in property definitions on a resource
7
10
  # class Book < Valkyrie::Resource
8
- # attribute :id, Valkyrie::Types::ID.optional
9
11
  # attribute :title, Valkyrie::Types::Set.optional # default type if none is specified
10
12
  # attribute :member_ids, Valkyrie::Types::Array
11
13
  # end
@@ -38,6 +40,14 @@ module Valkyrie
38
40
  end
39
41
  end
40
42
 
43
+ # Optimistic Lock Token
44
+ OptimisticLockToken =
45
+ Dry::Types::Definition
46
+ .new(::Valkyrie::Persistence::OptimisticLockToken)
47
+ .constructor do |input|
48
+ Valkyrie::Persistence::OptimisticLockToken.deserialize(input)
49
+ end
50
+
41
51
  # Used for casting {Valkyrie::Resources} if possible.
42
52
  Anything = Valkyrie::Types::Any.constructor do |value|
43
53
  if value.respond_to?(:fetch) && value.fetch(:internal_resource, nil)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
- VERSION = "1.1.2"
3
+ VERSION = "1.2.0.rc1"
4
4
  end
data/lib/valkyrie.rb CHANGED
@@ -13,10 +13,8 @@ require 'rdf'
13
13
  require 'valkyrie/rdf_patches'
14
14
  require 'json/ld'
15
15
  require 'logger'
16
- require 'active_triples'
17
16
  require 'rdf/vocab'
18
17
  require 'rails'
19
- require 'active_fedora'
20
18
 
21
19
  module Valkyrie
22
20
  require 'valkyrie/id'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkyrie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trey Pendragon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-08 00:00:00.000000000 Z
11
+ date: 2018-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -441,7 +441,6 @@ files:
441
441
  - bin/rspec
442
442
  - bin/setup
443
443
  - browserslist
444
- - config/fedora.yml
445
444
  - config/valkyrie.yml
446
445
  - db/config.yml
447
446
  - db/migrate/20160111215816_enable_uuid_extension.rb
@@ -451,6 +450,7 @@ files:
451
450
  - db/migrate/20171011224121_create_path_gin_index.rb
452
451
  - db/migrate/20171204224121_create_internal_resource_index.rb
453
452
  - db/migrate/20180212092225_create_updated_at_index.rb
453
+ - db/migrate/20180802220739_add_optimistic_locking_to_orm_resources.rb
454
454
  - db/schema.rb
455
455
  - db/seeds.rb
456
456
  - lib/config/database_connection.rb
@@ -485,6 +485,7 @@ files:
485
485
  - lib/valkyrie/persistence/memory/metadata_adapter.rb
486
486
  - lib/valkyrie/persistence/memory/persister.rb
487
487
  - lib/valkyrie/persistence/memory/query_service.rb
488
+ - lib/valkyrie/persistence/optimistic_lock_token.rb
488
489
  - lib/valkyrie/persistence/postgres.rb
489
490
  - lib/valkyrie/persistence/postgres/metadata_adapter.rb
490
491
  - lib/valkyrie/persistence/postgres/orm.rb
@@ -567,12 +568,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
567
568
  version: '0'
568
569
  required_rubygems_version: !ruby/object:Gem::Requirement
569
570
  requirements:
570
- - - ">="
571
+ - - ">"
571
572
  - !ruby/object:Gem::Version
572
- version: '0'
573
+ version: 1.3.1
573
574
  requirements: []
574
575
  rubyforge_project:
575
- rubygems_version: 2.6.14
576
+ rubygems_version: 2.7.7
576
577
  signing_key:
577
578
  specification_version: 4
578
579
  summary: An ORM using the Data Mapper pattern, specifically built to solve Digital
data/config/fedora.yml DELETED
@@ -1,10 +0,0 @@
1
- development:
2
- user: fedoraAdmin
3
- password: fedoraAdmin
4
- url: http://localhost:<%= ENV['FCREPO_DEVELOPMENT_PORT'] || 8986 %>/rest
5
- base_path: /dev
6
- test:
7
- user: fedoraAdmin
8
- password: fedoraAdmin
9
- url: http://localhost:<%= ENV['FCREPO_TEST_PORT'] || 8988 %>/rest
10
- base_path: /test