archivesspace-client 0.1.2 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/README.md +27 -17
- data/Rakefile +5 -3
- data/archivesspace-client.gemspec +20 -19
- data/examples/export.rb +33 -12
- data/examples/password_reset.rb +6 -4
- data/examples/repo_and_user.rb +48 -27
- data/examples/test_connection.rb +21 -0
- data/lib/archivesspace/client.rb +14 -14
- data/lib/archivesspace/client/client.rb +5 -5
- data/lib/archivesspace/client/configuration.rb +9 -10
- data/lib/archivesspace/client/helpers.rb +69 -108
- data/lib/archivesspace/client/request.rb +16 -18
- data/lib/archivesspace/client/response.rb +3 -4
- data/lib/archivesspace/client/template.rb +6 -8
- data/lib/archivesspace/client/version.rb +3 -1
- data/spec/archivesspace/client_spec.rb +8 -12
- data/spec/archivesspace/configuration_spec.rb +6 -6
- data/spec/fixtures/cassettes/backend_version.yml +1 -1
- data/spec/spec_helper.rb +8 -6
- metadata +46 -47
- data/examples/perms_and_groups.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2087a90bf94b94f918d9b1453442e8e7a682ef75a76092fcd7dbe63d21816b83
|
4
|
+
data.tar.gz: 3f8e168c3e7a04e6dbb67e3bef8227f77d46ea3b9c009f08eddd24de3441f736
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6977881509e613d26e24bbfa7b20204d20aac113a3d3297d798ba3b5c2f0cc673d217d77f9c161a906229a69a8710cdf9745e9c96b27262f8b0f2ac20583e51
|
7
|
+
data.tar.gz: 2480484be2b5ec0379b3c7c280e8473897a9930cb5a6abc2ec7b28decb81722478e70703a1d8bd38992866d6adaf94492e06480679126213bf500205e948a749
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
Archivesspace Client
|
2
|
-
===
|
1
|
+
# Archivesspace Client
|
3
2
|
|
4
|
-
Interact with ArchivesSpace via
|
3
|
+
Interact with ArchivesSpace via the API.
|
5
4
|
|
6
|
-
Installation
|
7
|
-
---
|
5
|
+
## Installation
|
8
6
|
|
9
7
|
Add this line to your application's Gemfile:
|
10
8
|
|
@@ -20,10 +18,11 @@ bundle install
|
|
20
18
|
|
21
19
|
Or install it yourself as:
|
22
20
|
|
23
|
-
|
21
|
+
```bash
|
22
|
+
gem install archivesspace-client
|
23
|
+
```
|
24
24
|
|
25
|
-
Usage
|
26
|
-
---
|
25
|
+
## Usage
|
27
26
|
|
28
27
|
See the examples directory for a range of use cases.
|
29
28
|
|
@@ -37,8 +36,6 @@ client = ArchivesSpace::Client.new.login
|
|
37
36
|
|
38
37
|
**Custom configuration**
|
39
38
|
|
40
|
-
To supply custom configuration to client:
|
41
|
-
|
42
39
|
```ruby
|
43
40
|
config = ArchivesSpace::Configuration.new({
|
44
41
|
base_uri: "https://archives.university.edu/api",
|
@@ -90,8 +87,7 @@ client.get('digital_objects') # instead of "repositories/2/digital_objects" etc.
|
|
90
87
|
client.config.base_repo = ""
|
91
88
|
```
|
92
89
|
|
93
|
-
Development
|
94
|
-
---
|
90
|
+
## Development
|
95
91
|
|
96
92
|
To run the examples start a local instance of ArchivesSpace then:
|
97
93
|
|
@@ -99,7 +95,9 @@ To run the examples start a local instance of ArchivesSpace then:
|
|
99
95
|
bundle exec ruby examples/repo_and_user.rb
|
100
96
|
```
|
101
97
|
|
102
|
-
Any script placed in the examples directory with a `my_` prefix are ignored by
|
98
|
+
Any script placed in the examples directory with a `my_` prefix are ignored by
|
99
|
+
git. Follow the convention used by the existing scripts to bootstrap and
|
100
|
+
experiment away.
|
103
101
|
|
104
102
|
To run the tests:
|
105
103
|
|
@@ -107,13 +105,25 @@ To run the tests:
|
|
107
105
|
bundle exec rake
|
108
106
|
```
|
109
107
|
|
110
|
-
|
111
|
-
|
108
|
+
## Publishing
|
109
|
+
|
110
|
+
Bump version in `lib/archivesspace/client/version.rb` then:
|
111
|
+
|
112
|
+
```bash
|
113
|
+
VERSION=0.1.7
|
114
|
+
gem build archivesspace-client
|
115
|
+
git add . && git commit -m "Bump to $VERSION"
|
116
|
+
git tag v$VERSION
|
117
|
+
git push origin master
|
118
|
+
git push --tags
|
119
|
+
gem push archivesspace-client-$VERSION.gem
|
120
|
+
```
|
121
|
+
|
122
|
+
## Contributing
|
112
123
|
|
113
124
|
Bug reports and pull requests are welcome on GitHub at https://github.com/lyrasis/archivesspace-client.
|
114
125
|
|
115
|
-
License
|
116
|
-
---
|
126
|
+
## License
|
117
127
|
|
118
128
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
119
129
|
|
data/Rakefile
CHANGED
@@ -1,31 +1,32 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'archivesspace/client/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'archivesspace-client'
|
8
9
|
spec.version = ArchivesSpace::Client::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Mark Cooper']
|
11
|
+
spec.email = ['mark.c.cooper@outlook.com']
|
12
|
+
spec.summary = 'Interact with ArchivesSpace via the API.'
|
13
|
+
spec.description = 'Interact with ArchivesSpace via the API.'
|
14
|
+
spec.homepage = ''
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0")
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
22
|
+
spec.add_development_dependency 'awesome_print', '~> 1.8.0'
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '3.6.0'
|
26
|
+
spec.add_development_dependency 'vcr', '3.0.3'
|
27
|
+
spec.add_development_dependency 'webmock', '3.0.1'
|
27
28
|
|
28
|
-
spec.add_dependency
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
29
|
+
spec.add_dependency 'httparty', '~> 0.14'
|
30
|
+
spec.add_dependency 'json', '~> 2.0'
|
31
|
+
spec.add_dependency 'nokogiri', '~> 1.10'
|
31
32
|
end
|
data/examples/export.rb
CHANGED
@@ -1,15 +1,36 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
2
4
|
require 'awesome_print'
|
3
5
|
require 'archivesspace/client'
|
4
6
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
# official sandbox
|
8
|
+
config = ArchivesSpace::Configuration.new(
|
9
|
+
{
|
10
|
+
base_uri: 'http://test.archivesspace.org/staff/api',
|
11
|
+
base_repo: '',
|
12
|
+
username: 'admin',
|
13
|
+
password: 'admin',
|
14
|
+
page_size: 50,
|
15
|
+
throttle: 0,
|
16
|
+
verify_ssl: false
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
20
|
+
client = ArchivesSpace::Client.new(config).login
|
21
|
+
client.config.throttle = 0.5
|
22
|
+
client.config.base_repo = 'repositories/2'
|
23
|
+
|
24
|
+
begin
|
25
|
+
# date -d '2021-02-01 00:00:00' +'%s' # 1612166400
|
26
|
+
client.resources(query: { modified_since: '1612166400' }).each do |resource|
|
27
|
+
# for now we are just printing ...
|
28
|
+
# but you would actually write to a zip file or whatever
|
29
|
+
id = resource['uri'].split('/')[-1]
|
30
|
+
opts = { include_unpublished: false }
|
31
|
+
response = client.get("resource_descriptions/#{id}.xml", opts)
|
32
|
+
puts Nokogiri::XML(response.body).to_xml
|
33
|
+
end
|
34
|
+
rescue ArchivesSpace::RequestError => e
|
35
|
+
puts e.message
|
36
|
+
end
|
data/examples/password_reset.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
2
4
|
require 'awesome_print'
|
3
5
|
require 'archivesspace/client'
|
4
6
|
|
5
|
-
username =
|
6
|
-
password =
|
7
|
+
username = 'mrx'
|
8
|
+
password = '123456'
|
7
9
|
|
8
10
|
# default client connection: localhost:8089, admin, admin
|
9
11
|
client = ArchivesSpace::Client.new.login
|
10
12
|
begin
|
11
13
|
client.password_reset username, password
|
12
14
|
puts "Successfully updated password for #{username}."
|
13
|
-
rescue
|
15
|
+
rescue StandardError => e
|
14
16
|
puts "Failed to update password for #{username},\n#{e.message}"
|
15
17
|
end
|
data/examples/repo_and_user.rb
CHANGED
@@ -1,40 +1,61 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
2
4
|
require 'awesome_print'
|
3
5
|
require 'archivesspace/client'
|
4
6
|
|
7
|
+
# official sandbox
|
8
|
+
config = ArchivesSpace::Configuration.new(
|
9
|
+
{
|
10
|
+
base_uri: 'http://sandbox.archivesspace.org/api',
|
11
|
+
base_repo: '',
|
12
|
+
username: 'admin',
|
13
|
+
password: 'admin',
|
14
|
+
page_size: 50,
|
15
|
+
throttle: 0,
|
16
|
+
verify_ssl: false
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
5
20
|
# default client connection: localhost:8089, admin, admin
|
6
|
-
client = ArchivesSpace::Client.new.login
|
21
|
+
client = ArchivesSpace::Client.new(config).login
|
7
22
|
|
8
23
|
ap ArchivesSpace::Template.list # view available templates
|
9
24
|
|
10
25
|
repo_data = {
|
11
|
-
repo_code:
|
12
|
-
name:
|
13
|
-
agent_contact_name:
|
26
|
+
repo_code: 'XYZ',
|
27
|
+
name: 'XYZ Archive',
|
28
|
+
agent_contact_name: 'John Doe'
|
14
29
|
}
|
15
30
|
|
16
|
-
repository = ArchivesSpace::Template.process_template(:repository_with_agent, repo_data)
|
17
|
-
response = client.post('/repositories/with_agent', repository)
|
18
|
-
if response.status_code == 201
|
19
|
-
repository = client.repositories.find { |r| r["repo_code"] == "XYZ" }
|
20
|
-
ap repository
|
21
|
-
ap client.delete(repository["uri"])
|
22
|
-
else
|
23
|
-
ap response.parsed
|
24
|
-
end
|
25
|
-
|
26
31
|
user_data = {
|
27
|
-
username:
|
28
|
-
name:
|
29
|
-
is_admin: true
|
32
|
+
username: 'lmessi',
|
33
|
+
name: 'Lionel Messi',
|
34
|
+
is_admin: true
|
30
35
|
}
|
36
|
+
user_password = '123456'
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
repository = ArchivesSpace::Template.process_template(:repository_with_agent, repo_data)
|
39
|
+
|
40
|
+
begin
|
41
|
+
response = client.post('/repositories/with_agent', repository)
|
42
|
+
if response.status_code.to_s =~ /^2/
|
43
|
+
repository = client.repositories.find { |r| r['repo_code'] == 'XYZ' }
|
44
|
+
ap repository
|
45
|
+
ap client.delete(repository['uri'])
|
46
|
+
else
|
47
|
+
ap response.parsed
|
48
|
+
end
|
49
|
+
|
50
|
+
user = ArchivesSpace::Template.process_template(:user, user_data)
|
51
|
+
response = client.post('users', user, { password: user_password })
|
52
|
+
if response.status_code.to_s =~ /^2/
|
53
|
+
user = client.users.find { |r| r['username'] == 'lmessi' }
|
54
|
+
ap user
|
55
|
+
ap client.delete user['uri']
|
56
|
+
else
|
57
|
+
ap response.parsed
|
58
|
+
end
|
59
|
+
rescue ArchivesSpace::RequestError => e
|
60
|
+
puts e.message
|
61
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
4
|
+
require 'awesome_print'
|
5
|
+
require 'archivesspace/client'
|
6
|
+
|
7
|
+
# official sandbox
|
8
|
+
config = ArchivesSpace::Configuration.new(
|
9
|
+
{
|
10
|
+
base_uri: 'http://sandbox.archivesspace.org/api',
|
11
|
+
base_repo: '',
|
12
|
+
username: 'admin',
|
13
|
+
password: 'admin',
|
14
|
+
page_size: 50,
|
15
|
+
throttle: 0,
|
16
|
+
verify_ssl: false
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
20
|
+
client = ArchivesSpace::Client.new(config).login
|
21
|
+
puts client.get('version').body
|
data/lib/archivesspace/client.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'httparty'
|
2
4
|
require 'json'
|
3
5
|
require 'nokogiri'
|
4
6
|
|
5
7
|
# mixins required first
|
6
|
-
require
|
8
|
+
require 'archivesspace/client/helpers'
|
7
9
|
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
10
|
+
require 'archivesspace/client/client'
|
11
|
+
require 'archivesspace/client/configuration'
|
12
|
+
require 'archivesspace/client/request'
|
13
|
+
require 'archivesspace/client/response'
|
14
|
+
require 'archivesspace/client/template'
|
15
|
+
require 'archivesspace/client/version'
|
14
16
|
|
15
17
|
module ArchivesSpace
|
16
|
-
|
17
|
-
class
|
18
|
-
class
|
19
|
-
class
|
20
|
-
|
21
|
-
|
22
|
-
end
|
18
|
+
class ConnectionError < RuntimeError; end
|
19
|
+
class ContextError < RuntimeError; end
|
20
|
+
class ParamsError < RuntimeError; end
|
21
|
+
class RequestError < RuntimeError; end
|
22
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ArchivesSpace
|
3
4
|
class Client
|
4
5
|
include Helpers
|
5
6
|
attr_accessor :token
|
6
7
|
attr_reader :config
|
7
8
|
|
8
9
|
def initialize(config = Configuration.new)
|
9
|
-
raise
|
10
|
+
raise 'Invalid configuration object' unless config.is_a? ArchivesSpace::Configuration
|
11
|
+
|
10
12
|
@config = config
|
11
13
|
@token = nil
|
12
14
|
end
|
@@ -31,11 +33,9 @@ module ArchivesSpace
|
|
31
33
|
|
32
34
|
def request(method, path, options = {})
|
33
35
|
sleep config.throttle
|
34
|
-
options[:headers] = {
|
36
|
+
options[:headers] = { 'X-ArchivesSpace-Session' => token } if token
|
35
37
|
result = Request.new(config, method, path, options).execute
|
36
38
|
Response.new result
|
37
39
|
end
|
38
|
-
|
39
40
|
end
|
40
|
-
|
41
41
|
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ArchivesSpace
|
3
4
|
class Configuration
|
4
|
-
|
5
5
|
def defaults
|
6
6
|
{
|
7
|
-
base_uri:
|
8
|
-
base_repo:
|
9
|
-
username:
|
10
|
-
password:
|
7
|
+
base_uri: 'http://localhost:8089',
|
8
|
+
base_repo: '',
|
9
|
+
username: 'admin',
|
10
|
+
password: 'admin',
|
11
11
|
page_size: 50,
|
12
12
|
throttle: 0,
|
13
|
-
verify_ssl: true
|
13
|
+
verify_ssl: true
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
@@ -18,11 +18,10 @@ module ArchivesSpace
|
|
18
18
|
settings = defaults.merge(settings)
|
19
19
|
settings.each do |property, value|
|
20
20
|
next unless defaults.keys.include? property
|
21
|
+
|
21
22
|
instance_variable_set("@#{property}", value)
|
22
23
|
self.class.send(:attr_accessor, property)
|
23
24
|
end
|
24
25
|
end
|
25
|
-
|
26
26
|
end
|
27
|
-
|
28
|
-
end
|
27
|
+
end
|
@@ -1,168 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# needed for roundtrip hash merging
|
2
4
|
class ::Hash
|
3
5
|
def deep_merge(second)
|
4
|
-
merger = proc { |
|
5
|
-
|
6
|
+
merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
7
|
+
merge(second, &merger)
|
6
8
|
end
|
7
9
|
end
|
8
10
|
|
9
11
|
module ArchivesSpace
|
10
|
-
|
11
12
|
module Helpers
|
13
|
+
def accessions(options = {})
|
14
|
+
all('accessions', options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def all(path, options = {})
|
18
|
+
Enumerator.new do |yielder|
|
19
|
+
page = 1
|
20
|
+
unlimited_listing = false
|
21
|
+
loop do
|
22
|
+
options[:query] ||= {}
|
23
|
+
options[:query][:page] = page
|
24
|
+
result = get(path, options)
|
25
|
+
results = []
|
26
|
+
|
27
|
+
if result.parsed.respond_to?(:key) && result.parsed.key?('results')
|
28
|
+
results = result.parsed['results']
|
29
|
+
else
|
30
|
+
results = result.parsed
|
31
|
+
unlimited_listing = true
|
32
|
+
end
|
12
33
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
34
|
+
if results.any?
|
35
|
+
results.each do |i|
|
36
|
+
yielder << i
|
37
|
+
end
|
38
|
+
raise StopIteration if unlimited_listing
|
19
39
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
result = get(path, options.merge({ query: { all_ids: true } } ))
|
27
|
-
raise RequestError.new result.status if result.status_code != 200
|
28
|
-
ids = result.parsed
|
29
|
-
ids = ids.map{ |object| object["uri"].split("/")[-1] } if parse_id
|
30
|
-
ids.each do |id|
|
31
|
-
path_with_id = format ? "#{format}/#{id}.xml" : "#{path}/#{id}"
|
32
|
-
result = get(path_with_id, options)
|
33
|
-
raise RequestError.new result.status if result.status_code != 200
|
34
|
-
record = format ? Nokogiri::XML(result.body).to_xml : result.parsed
|
35
|
-
yield record if block_given?
|
36
|
-
all << record
|
37
|
-
end
|
38
|
-
all
|
40
|
+
page += 1
|
41
|
+
else
|
42
|
+
raise StopIteration
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end.lazy
|
39
46
|
end
|
40
47
|
|
41
48
|
def backend_version
|
42
|
-
get
|
49
|
+
get 'version'
|
43
50
|
end
|
44
51
|
|
45
52
|
def batch_import(payload, params = {})
|
46
53
|
# create "batch_import", payload, params
|
47
54
|
end
|
48
55
|
|
49
|
-
def
|
50
|
-
|
51
|
-
path = "digital_objects/#{format}/#{id}.xml"
|
52
|
-
get_xml path, options
|
53
|
-
end
|
54
|
-
|
55
|
-
def digital_objects(format = nil, options = {}, &block)
|
56
|
-
path = "digital_objects"
|
57
|
-
format = format ? "#{path}/#{format}" : nil
|
58
|
-
records = all(path, options.merge({ format: format })) do |record|
|
59
|
-
yield record if block_given?
|
60
|
-
end
|
61
|
-
records
|
56
|
+
def digital_objects(options = {})
|
57
|
+
all('digital_objects', options)
|
62
58
|
end
|
63
59
|
|
64
|
-
def groups
|
65
|
-
|
66
|
-
yield record if block_given?
|
67
|
-
end
|
68
|
-
records
|
60
|
+
def groups(options = {})
|
61
|
+
all('groups', options)
|
69
62
|
end
|
70
63
|
|
71
64
|
def group_user_assignment(users_with_roles, params = { with_members: true })
|
72
65
|
updated = []
|
73
|
-
groups do |group|
|
66
|
+
groups.each do |group|
|
74
67
|
changed = false
|
75
68
|
|
76
69
|
users_with_roles.each do |user, roles|
|
77
|
-
if roles.include? group[
|
78
|
-
unless group[
|
79
|
-
group[
|
70
|
+
if roles.include? group['group_code']
|
71
|
+
unless group['member_usernames'].include? user
|
72
|
+
group['member_usernames'] << user
|
80
73
|
changed = true
|
81
74
|
end
|
82
75
|
else
|
83
|
-
if group[
|
84
|
-
group[
|
76
|
+
if group['member_usernames'].include? user
|
77
|
+
group['member_usernames'].delete user
|
85
78
|
changed = true
|
86
79
|
end
|
87
80
|
end
|
88
81
|
end
|
89
82
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
83
|
+
next unless changed
|
84
|
+
|
85
|
+
id = group['uri'].split('/')[-1]
|
86
|
+
response = post("/groups/#{id}", group, params)
|
87
|
+
updated << response.parsed
|
95
88
|
end
|
96
89
|
updated
|
97
90
|
end
|
98
91
|
|
99
92
|
def login
|
100
|
-
username
|
93
|
+
username = config.username
|
94
|
+
password = config.password
|
101
95
|
result = request('POST', "/users/#{username}/login", { query: { password: password } })
|
102
|
-
|
103
|
-
|
96
|
+
unless result.parsed['session']
|
97
|
+
raise ConnectionError, "Failed to connect to ArchivesSpace backend as #{username} #{password}"
|
98
|
+
end
|
99
|
+
|
100
|
+
@token = result.parsed['session']
|
104
101
|
self
|
105
102
|
end
|
106
103
|
|
107
104
|
def password_reset(username, password)
|
108
|
-
user = all('users').find { |u| u[
|
109
|
-
raise RequestError
|
110
|
-
post(user["uri"], user, { password: password })
|
111
|
-
end
|
105
|
+
user = all('users').find { |u| u['username'] == username }
|
106
|
+
raise RequestError, user.status unless user
|
112
107
|
|
113
|
-
|
114
|
-
records = get('repositories').parsed.each do |record|
|
115
|
-
yield record if block_given?
|
116
|
-
end
|
117
|
-
records
|
108
|
+
post(user['uri'], user, { password: password })
|
118
109
|
end
|
119
110
|
|
120
|
-
def
|
121
|
-
|
111
|
+
def repositories(options = {})
|
112
|
+
all('repositories', options)
|
122
113
|
end
|
123
114
|
|
124
|
-
def
|
125
|
-
id = resource["uri"].split("/")[-1]
|
126
|
-
path = format == "ead" ? "resource_descriptions/#{id}.xml" : "resources/#{format}/#{id}.xml"
|
127
|
-
get_xml path, options
|
128
|
-
end
|
115
|
+
def repositories_with_agent; end
|
129
116
|
|
130
|
-
def resources(
|
131
|
-
|
132
|
-
# the api is inconsistent with the path structure for resource ead (and pdf)
|
133
|
-
if format
|
134
|
-
if format =~ /(ead|pdf)/
|
135
|
-
format = "resource_descriptions"
|
136
|
-
else
|
137
|
-
format = "#{path}/#{format}"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
records = all(path, options.merge({ format: format })) do |record|
|
141
|
-
yield record if block_given?
|
142
|
-
end
|
143
|
-
records
|
117
|
+
def resources(options = {})
|
118
|
+
all('resources', options)
|
144
119
|
end
|
145
120
|
|
146
121
|
def search(params)
|
147
122
|
# get "search", params
|
148
123
|
end
|
149
124
|
|
150
|
-
def users
|
151
|
-
|
152
|
-
yield record if block_given?
|
153
|
-
end
|
154
|
-
records
|
155
|
-
end
|
156
|
-
|
157
|
-
private
|
158
|
-
|
159
|
-
def get_xml(path, options = {})
|
160
|
-
# add xml headers
|
161
|
-
response = get(path, options)
|
162
|
-
raise RequestError.new path unless response.status_code == 200
|
163
|
-
Nokogiri::XML(response.body).to_xml
|
125
|
+
def users(options = {})
|
126
|
+
all('users', options)
|
164
127
|
end
|
165
|
-
|
166
128
|
end
|
167
|
-
|
168
|
-
end
|
129
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ArchivesSpace
|
3
4
|
class Request
|
4
5
|
include HTTParty
|
5
6
|
attr_reader :config, :headers, :method, :path, :options
|
@@ -9,36 +10,33 @@ module ArchivesSpace
|
|
9
10
|
delete: {},
|
10
11
|
get: {},
|
11
12
|
post: {
|
12
|
-
|
13
|
-
|
13
|
+
'Content-Type' => 'application/json',
|
14
|
+
'Content-Length' => 'nnnn'
|
14
15
|
},
|
15
16
|
put: {
|
16
|
-
|
17
|
-
|
17
|
+
'Content-Type' => 'application/json',
|
18
|
+
'Content-Length' => 'nnnn'
|
18
19
|
}
|
19
20
|
}
|
20
21
|
headers[method]
|
21
22
|
end
|
22
23
|
|
23
|
-
def initialize(config, method =
|
24
|
-
@config
|
25
|
-
@method
|
26
|
-
@path
|
24
|
+
def initialize(config, method = 'GET', path = '', options = {})
|
25
|
+
@config = config
|
26
|
+
@method = method.downcase.to_sym
|
27
|
+
@path = path.gsub(%r{^/+}, '')
|
28
|
+
@options = options
|
29
|
+
@options[:headers] = options[:headers] ? default_headers(@method).merge(options[:headers]) : default_headers(@method)
|
30
|
+
@options[:verify] = config.verify_ssl
|
31
|
+
@options[:query] = {} unless options.key? :query
|
27
32
|
|
28
|
-
|
29
|
-
@options[:headers] = options[:headers] ? default_headers(@method).merge(options[:headers]) : default_headers
|
30
|
-
@options[:verify] = config.verify_ssl
|
31
|
-
@options[:query] = {} unless options.has_key? :query
|
33
|
+
base_uri = config.base_repo&.length&.positive? ? File.join(config.base_uri, config.base_repo) : config.base_uri
|
32
34
|
|
33
|
-
base_uri = (config.base_repo.nil? or config.base_repo.empty?) ? config.base_uri : "#{config.base_uri}/#{config.base_repo}"
|
34
35
|
self.class.base_uri base_uri
|
35
|
-
# self.class.default_params abc: 123
|
36
36
|
end
|
37
37
|
|
38
38
|
def execute
|
39
39
|
self.class.send method, "/#{path}", options
|
40
40
|
end
|
41
|
-
|
42
41
|
end
|
43
|
-
|
44
|
-
end
|
42
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ArchivesSpace
|
3
4
|
class Response
|
4
5
|
attr_reader :result, :parsed, :body, :headers, :status, :status_code, :xml
|
5
6
|
|
@@ -12,7 +13,5 @@ module ArchivesSpace
|
|
12
13
|
@status = result.response
|
13
14
|
@status_code = result.code.to_i
|
14
15
|
end
|
15
|
-
|
16
16
|
end
|
17
|
-
|
18
|
-
end
|
17
|
+
end
|
@@ -1,25 +1,23 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ArchivesSpace
|
3
4
|
module Template
|
4
|
-
|
5
5
|
def self.list
|
6
6
|
[]
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.process_template(template, data)
|
10
|
-
t = ERB.new(
|
11
|
-
r = t.result(binding).gsub(/\n+/,"\n")
|
10
|
+
t = ERB.new(read_template(template))
|
11
|
+
r = t.result(binding).gsub(/\n+/, "\n")
|
12
12
|
JSON.parse(r)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.read_template(file)
|
16
|
-
File.read("#{
|
16
|
+
File.read("#{templates_path}/#{file}.json.erb")
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.templates_path
|
20
20
|
File.join(File.dirname(File.expand_path(__FILE__)), 'templates')
|
21
21
|
end
|
22
|
-
|
23
22
|
end
|
24
|
-
|
25
|
-
end
|
23
|
+
end
|
@@ -1,43 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe ArchivesSpace::Client do
|
4
|
-
|
5
6
|
let(:client) { ArchivesSpace::Client.new }
|
6
7
|
let(:login) { -> { client.login } }
|
7
8
|
|
8
|
-
describe
|
9
|
-
|
9
|
+
describe 'Configuration' do
|
10
10
|
it 'will use the default configuration if none is provided' do
|
11
11
|
client = ArchivesSpace::Client.new
|
12
12
|
expect(client.config.base_uri).to eq DEFAULT_BASE_URI
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'will raise an error if supplied configuration is of invalid type' do
|
16
|
-
expect{ ArchivesSpace::Client.new({ base_uri: CUSTOM_BASE_URI }) }.to raise_error(RuntimeError)
|
16
|
+
expect { ArchivesSpace::Client.new({ base_uri: CUSTOM_BASE_URI }) }.to raise_error(RuntimeError)
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'will allow a configuration object to be provided' do
|
20
20
|
client = ArchivesSpace::Client.new(ArchivesSpace::Configuration.new({ base_uri: CUSTOM_BASE_URI }))
|
21
21
|
expect(client.config.base_uri).to eq CUSTOM_BASE_URI
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
|
26
|
-
describe
|
27
|
-
|
25
|
+
describe 'Version information' do
|
28
26
|
it 'has a version number' do
|
29
27
|
expect(ArchivesSpace::Client::VERSION).not_to be nil
|
30
28
|
end
|
31
29
|
|
32
|
-
it
|
30
|
+
it 'can retrieve the backend version info' do
|
33
31
|
VCR.use_cassette('backend_version') do
|
34
32
|
login.call
|
35
|
-
response = client.get
|
33
|
+
response = client.get 'version'
|
36
34
|
expect(response.status_code).to eq(200)
|
37
35
|
expect(response.body).to match(/ArchivesSpace \(.*\)/)
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
41
38
|
end
|
42
|
-
|
43
|
-
end
|
39
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
describe ArchivesSpace::Configuration do
|
4
|
-
|
5
6
|
it 'uses the default profile for configuration settings' do
|
6
7
|
config = ArchivesSpace::Configuration.new
|
7
8
|
expect(config.base_uri).to eq DEFAULT_BASE_URI
|
@@ -9,8 +10,8 @@ describe ArchivesSpace::Configuration do
|
|
9
10
|
|
10
11
|
it 'allows configuration settings to be provided' do
|
11
12
|
config = ArchivesSpace::Configuration.new({
|
12
|
-
|
13
|
-
|
13
|
+
base_uri: CUSTOM_BASE_URI
|
14
|
+
})
|
14
15
|
expect(config.base_uri).to eq CUSTOM_BASE_URI
|
15
16
|
end
|
16
17
|
|
@@ -22,7 +23,6 @@ describe ArchivesSpace::Configuration do
|
|
22
23
|
|
23
24
|
it 'ignores unrecognized configuration properties' do
|
24
25
|
config = ArchivesSpace::Configuration.new({ xyz: 123 })
|
25
|
-
expect{ config.xyz }.to raise_error(NoMethodError)
|
26
|
+
expect { config.xyz }.to raise_error(NoMethodError)
|
26
27
|
end
|
27
|
-
|
28
|
-
end
|
28
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
2
4
|
require 'archivesspace/client'
|
3
5
|
require 'vcr'
|
4
6
|
require 'webmock/rspec'
|
5
7
|
|
6
8
|
# GLOBAL VALUES FOR SPECS
|
7
|
-
DEFAULT_BASE_URI =
|
8
|
-
CUSTOM_BASE_URI =
|
9
|
+
DEFAULT_BASE_URI = 'http://localhost:8089'
|
10
|
+
CUSTOM_BASE_URI = 'https://archives.university.edu/api'
|
9
11
|
|
10
12
|
VCR.configure do |c|
|
11
|
-
c.cassette_library_dir =
|
13
|
+
c.cassette_library_dir = 'spec/fixtures/cassettes'
|
12
14
|
c.hook_into :webmock
|
13
|
-
c.default_cassette_options = { :
|
14
|
-
end
|
15
|
+
c.default_cassette_options = { record: :once }
|
16
|
+
end
|
metadata
CHANGED
@@ -1,142 +1,142 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: archivesspace-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Cooper
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: awesome_print
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.8.0
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.8.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '10.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 3.6.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 3.6.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: vcr
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 3.0.3
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 3.0.3
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: webmock
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 3.0.1
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 3.0.1
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: httparty
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
103
|
+
version: '0.14'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
110
|
+
version: '0.14'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: json
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
117
|
+
version: '2.0'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
124
|
+
version: '2.0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: nokogiri
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '1.10'
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
139
|
-
description: Interact with ArchivesSpace via
|
138
|
+
version: '1.10'
|
139
|
+
description: Interact with ArchivesSpace via the API.
|
140
140
|
email:
|
141
141
|
- mark.c.cooper@outlook.com
|
142
142
|
executables: []
|
@@ -153,8 +153,8 @@ files:
|
|
153
153
|
- archivesspace-client.gemspec
|
154
154
|
- examples/export.rb
|
155
155
|
- examples/password_reset.rb
|
156
|
-
- examples/perms_and_groups.rb
|
157
156
|
- examples/repo_and_user.rb
|
157
|
+
- examples/test_connection.rb
|
158
158
|
- lib/archivesspace/client.rb
|
159
159
|
- lib/archivesspace/client/client.rb
|
160
160
|
- lib/archivesspace/client/configuration.rb
|
@@ -190,11 +190,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
190
|
- !ruby/object:Gem::Version
|
191
191
|
version: '0'
|
192
192
|
requirements: []
|
193
|
-
|
194
|
-
rubygems_version: 2.2.2
|
193
|
+
rubygems_version: 3.1.4
|
195
194
|
signing_key:
|
196
195
|
specification_version: 4
|
197
|
-
summary: Interact with ArchivesSpace via
|
196
|
+
summary: Interact with ArchivesSpace via the API.
|
198
197
|
test_files:
|
199
198
|
- spec/archivesspace/client_spec.rb
|
200
199
|
- spec/archivesspace/configuration_spec.rb
|
@@ -1,8 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
-
require 'awesome_print'
|
3
|
-
require 'archivesspace/client'
|
4
|
-
|
5
|
-
# default client connection: localhost:8089, admin, admin
|
6
|
-
client = ArchivesSpace::Client.new.login
|
7
|
-
|
8
|
-
# todo ... example of assignment using CSV
|