archivesspace-client 0.1.3 → 0.1.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1723d47efa6b10e5106ca28bfa6f247bf79603d2
4
- data.tar.gz: f6b404154c5c87ee9a74036d6501cc3304df01ea
2
+ SHA256:
3
+ metadata.gz: 6ea50bb167b4debf8781434efa1ff7b06d077a8ab869f02c30ea8d1cd66de3c9
4
+ data.tar.gz: 83f63ad1f11fc35ca89cdabe871a1e1fa91f935e2e6e284f038b6db2c0257065
5
5
  SHA512:
6
- metadata.gz: 7de5e06e6900dda657cfae615058c10859ba565aa27f16184ec7d44f23c7c2513a52c9717186f8ce04361adabc3097b562db785694bb38556a003177e92b4718
7
- data.tar.gz: 17a2e5174475986516c757f7b4f875352546555f0f3aee8539c7f3d2f090789dd1f7087614ca38ea3d0b554c50a351d7307ec8d29706bc816b4fcb328b2e60d9
6
+ metadata.gz: faa0086ae6ecd33700e3cf16c41b7457ebf094eb4a5e79109c3999ce0e916f8924450cb6ef8bcb4a761f0d6ed3a1c12a457dec4cd5738429a8f80fb249303fbe
7
+ data.tar.gz: '09a6fca39d7846875715216e8b10d5d29b776b433c37abef3490b5964e62deca9de5f01e69f868a476cceb11c7ceaa43032cfb906f9fff35da10b43e0b3582e7'
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in archivesspace-client.gemspec
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
- Archivesspace Client
2
- ===
1
+ # Archivesspace Client
3
2
 
4
- Interact with ArchivesSpace via its API.
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
- $ gem install archivesspace-client
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,36 @@ 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
+ ## Templates
91
+
92
+ Templates are an optional feature that can help simplify the effort of creating
93
+ json payloads for ArchivesSpace. Rather than construct the json programatically
94
+ according to the schemas a `.erb` template can be used to generate payloads
95
+ instead which are transformed to json automatically. There are a small number of
96
+ templates provided with the client, but you can create your own and access them
97
+ by setting the `ARCHIVESSPACE_CLIENT_TEMPLATES_PATH` envvar. A particularly simple
98
+ template might look like:
99
+
100
+ ```erb
101
+ {
102
+ "digital_object_id": "<%= data[:digital_object_id] %>",
103
+ "title": "<%= data[:title] %>"
104
+ }
105
+ ```
106
+
107
+ Practically speaking there isn't much benefit to this example, but in the case of
108
+ a more complex record structure where you want to populate deeply nested elements
109
+ using a flat file structure (like csv) this can be a very convenient way of
110
+ assembling the payload. To process a template:
111
+
112
+ ```ruby
113
+ data = { repo_code: 'ABC', name: 'ABC Archive', agent_contact_name: 'ABC Admin' }
114
+ json = ArchivesSpace::Template.process(:repository_with_agent, data)
115
+ response = client.post('/repositories/with_agent', json)
116
+ puts response.result.success? ? '=)' : '=('
117
+ ```
118
+
119
+ ## Development
95
120
 
96
121
  To run the examples start a local instance of ArchivesSpace then:
97
122
 
@@ -99,7 +124,9 @@ To run the examples start a local instance of ArchivesSpace then:
99
124
  bundle exec ruby examples/repo_and_user.rb
100
125
  ```
101
126
 
102
- Any script placed in the examples directory with a `my_` prefix are ignored by git. Follow the convention used by the existing scripts to bootstrap and experiment away.
127
+ Any script placed in the examples directory with a `my_` prefix are ignored by
128
+ git. Follow the convention used by the existing scripts to bootstrap and
129
+ experiment away.
103
130
 
104
131
  To run the tests:
105
132
 
@@ -107,13 +134,25 @@ To run the tests:
107
134
  bundle exec rake
108
135
  ```
109
136
 
110
- Contributing
111
- ---
137
+ ## Publishing
138
+
139
+ Bump version in `lib/archivesspace/client/version.rb` then:
140
+
141
+ ```bash
142
+ VERSION=0.1.8
143
+ gem build archivesspace-client
144
+ git add . && git commit -m "Bump to $VERSION"
145
+ git tag v$VERSION
146
+ git push origin master
147
+ git push --tags
148
+ gem push archivesspace-client-$VERSION.gem
149
+ ```
150
+
151
+ ## Contributing
112
152
 
113
153
  Bug reports and pull requests are welcome on GitHub at https://github.com/lyrasis/archivesspace-client.
114
154
 
115
- License
116
- ---
155
+ ## License
117
156
 
118
157
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
119
158
 
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -1,31 +1,32 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
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 = "archivesspace-client"
8
+ spec.name = 'archivesspace-client'
8
9
  spec.version = ArchivesSpace::Client::VERSION
9
- spec.authors = ["Mark Cooper"]
10
- spec.email = ["mark.c.cooper@outlook.com"]
11
- spec.summary = %q{Interact with ArchivesSpace via its RESTful API.}
12
- spec.description = %q{Interact with ArchivesSpace via its RESTful API.}
13
- spec.homepage = ""
14
- spec.license = "MIT"
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 = ["lib"]
20
+ spec.require_paths = ['lib']
20
21
 
21
- spec.add_development_dependency "bundler", "~> 1.10"
22
- spec.add_development_dependency "rake", "~> 10.0"
23
- spec.add_development_dependency "rspec", "3.6.0"
24
- spec.add_development_dependency "vcr", "3.0.3"
25
- spec.add_development_dependency "webmock", "3.0.1"
26
- spec.add_development_dependency "awesome_print", "~> 1.8.0"
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 "httparty", "0.14.0"
29
- spec.add_dependency "json", "2.0.3"
30
- spec.add_dependency "nokogiri", "1.6.8.1"
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,29 +1,36 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
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
7
  # official sandbox
6
- config = ArchivesSpace::Configuration.new({
7
- base_uri: "http://sandbox.archivesspace.org/api",
8
- base_repo: "",
9
- username: "admin",
10
- password: "admin",
11
- page_size: 50,
12
- throttle: 0,
13
- verify_ssl: false,
14
- })
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
+ )
15
19
 
16
20
  client = ArchivesSpace::Client.new(config).login
17
21
  client.config.throttle = 0.5
18
- client.config.base_repo = "repositories/2"
22
+ client.config.base_repo = 'repositories/2'
19
23
 
20
24
  begin
21
- # date -d '2015-07-01 00:00:00' +'%s' # 1435734000
22
- client.resources("ead", { query: { modified_since: "1435734000" } }) do |ead|
25
+ # date -d '2021-02-01 00:00:00' +'%s' # 1612166400
26
+ client.resources(query: { modified_since: '1612166400' }).each do |resource|
23
27
  # for now we are just printing ...
24
28
  # but you would actually write to a zip file or whatever
25
- ap ead
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
26
33
  end
27
- rescue ArchivesSpace::RequestError => ex
28
- puts ex.message
29
- end
34
+ rescue ArchivesSpace::RequestError => e
35
+ puts e.message
36
+ end
@@ -1,15 +1,16 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
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 = "mrx"
6
- password = "123456"
7
+ username = 'admin'
8
+ password = 'admin'
7
9
 
8
10
  # default client connection: localhost:8089, admin, admin
9
11
  client = ArchivesSpace::Client.new.login
10
12
  begin
11
- client.password_reset username, password
12
- puts "Successfully updated password for #{username}."
13
- rescue Exception => ex
14
- puts "Failed to update password for #{username},\n#{ex.message}"
13
+ puts client.password_reset(username, password).parsed
14
+ rescue StandardError => e
15
+ puts "Failed to update password for #{username},\n#{e.message}"
15
16
  end
@@ -1,46 +1,60 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
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
- # default client connection: localhost:8089, admin, admin
6
- client = ArchivesSpace::Client.new.login
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
7
21
 
8
22
  ap ArchivesSpace::Template.list # view available templates
9
23
 
10
24
  repo_data = {
11
- repo_code: "XYZ",
12
- name: "XYZ Archive",
13
- agent_contact_name: "John Doe",
25
+ repo_code: 'XYZ',
26
+ name: 'XYZ Archive',
27
+ agent_contact_name: 'XYZ Admin'
14
28
  }
15
29
 
16
30
  user_data = {
17
- username: "lmessi",
18
- name: "Lionel Messi",
19
- is_admin: true,
31
+ username: 'lmessi',
32
+ name: 'Lionel Messi',
33
+ is_admin: true
20
34
  }
21
- user_password = "123456"
35
+ user_password = '123456'
22
36
 
23
- repository = ArchivesSpace::Template.process_template(:repository_with_agent, repo_data)
37
+ repository = ArchivesSpace::Template.process(:repository_with_agent, repo_data)
24
38
 
25
39
  begin
26
40
  response = client.post('/repositories/with_agent', repository)
27
- if response.status_code == 201
28
- repository = client.repositories.find { |r| r["repo_code"] == "XYZ" }
41
+ if response.result.success?
42
+ repository = client.repositories.find { |r| r['repo_code'] == 'XYZ' }
29
43
  ap repository
30
- ap client.delete(repository["uri"])
44
+ ap client.delete(repository['uri'])
31
45
  else
32
46
  ap response.parsed
33
47
  end
34
48
 
35
- user = ArchivesSpace::Template.process_template(:user, user_data)
49
+ user = ArchivesSpace::Template.process(:user, user_data)
36
50
  response = client.post('users', user, { password: user_password })
37
- if response.status_code == 201
38
- user = client.users.find { |r| r["username"] == "lmessi" }
51
+ if response.result.success?
52
+ user = client.users.find { |r| r['username'] == 'lmessi' }
39
53
  ap user
40
- ap client.delete user["uri"]
54
+ ap client.delete user['uri']
41
55
  else
42
56
  ap response.parsed
43
57
  end
44
- rescue ArchivesSpace::RequestError => ex
45
- puts ex.message
58
+ rescue ArchivesSpace::RequestError => e
59
+ puts e.message
46
60
  end
@@ -1,17 +1,21 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
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
7
  # official sandbox
6
- config = ArchivesSpace::Configuration.new({
7
- base_uri: "http://sandbox.archivesspace.org/api",
8
- base_repo: "",
9
- username: "admin",
10
- password: "admin",
11
- page_size: 50,
12
- throttle: 0,
13
- verify_ssl: false,
14
- })
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
+ )
15
19
 
16
20
  client = ArchivesSpace::Client.new(config).login
17
- puts client.get("version").body
21
+ puts client.get('version').body
@@ -0,0 +1,44 @@
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
+
22
+ user_data = {
23
+ username: 'bde',
24
+ name: 'BDE',
25
+ is_admin: false
26
+ }
27
+
28
+ client.post(
29
+ 'users',
30
+ ArchivesSpace::Template.process(:user, user_data),
31
+ { password: '123456' }
32
+ )
33
+
34
+ users_with_roles = {
35
+ 'bde' => ['repository-basic-data-entry']
36
+ }
37
+
38
+ begin
39
+ client.config.base_repo = "repositories/2"
40
+ results = client.group_user_assignment users_with_roles
41
+ ap results.map(&:parsed)
42
+ rescue ArchivesSpace::RequestError => e
43
+ puts e.message
44
+ end
@@ -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 "archivesspace/client/helpers"
8
+ require 'archivesspace/client/helpers'
7
9
 
8
- require "archivesspace/client/client"
9
- require "archivesspace/client/configuration"
10
- require "archivesspace/client/request"
11
- require "archivesspace/client/response"
12
- require "archivesspace/client/template"
13
- require "archivesspace/client/version"
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 ConnectionError < Exception ; end
18
- class ContextError < Exception ; end
19
- class ParamsError < Exception ; end
20
- class RequestError < Exception ; end
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
- module ArchivesSpace
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 "Invalid configuration object" unless config.kind_of? ArchivesSpace::Configuration
10
+ raise 'Invalid configuration object' unless config.is_a? ArchivesSpace::Configuration
11
+
10
12
  @config = config
11
13
  @token = nil
12
14
  end
@@ -16,11 +18,11 @@ module ArchivesSpace
16
18
  end
17
19
 
18
20
  def post(path, payload, params = {})
19
- request 'POST', path, { body: payload.to_json, query: params }
21
+ request 'POST', path, { body: payload, query: params }
20
22
  end
21
23
 
22
24
  def put(path, payload, params = {})
23
- request 'PUT', path, { body: payload.to_json, query: params }
25
+ request 'PUT', path, { body: payload, query: params }
24
26
  end
25
27
 
26
28
  def delete(path)
@@ -31,11 +33,9 @@ module ArchivesSpace
31
33
 
32
34
  def request(method, path, options = {})
33
35
  sleep config.throttle
34
- options[:headers] = { "X-ArchivesSpace-Session" => token } if token
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
- module ArchivesSpace
1
+ # frozen_string_literal: true
2
2
 
3
+ module ArchivesSpace
3
4
  class Configuration
4
-
5
5
  def defaults
6
6
  {
7
- base_uri: "http://localhost:8089",
8
- base_repo: "",
9
- username: "admin",
10
- password: "admin",
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,133 @@
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 { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
5
- self.merge(second, &merger)
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
- def accessions(options = {}, &block)
14
- records = all('accessions', options) do |record|
15
- yield record if block_given?
16
- end
17
- records
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
- def all(path, options = {}, &block)
21
- all = []
22
- format = options.delete(:format)
23
- parse_id = options.delete(:parse_id)
24
- # options[:headers] -- add xml headers if format
25
-
26
- result = get(path, options.merge({ query: { all_ids: true } } ))
27
- raise RequestError.new(result.body) 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.body) 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 "version"
43
- end
44
-
45
- def batch_import(payload, params = {})
46
- # create "batch_import", payload, params
49
+ get 'version'
47
50
  end
48
51
 
49
- def digital_object_to_xml(digital_object, format = "dublin_core", options = {})
50
- id = digital_object["uri"].split("/")[-1]
51
- path = "digital_objects/#{format}/#{id}.xml"
52
- get_xml path, options
53
- end
52
+ # def batch_import(payload, params = {})
53
+ # # TODO: create "batch_import", payload, params
54
+ # end
54
55
 
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
- records = all('groups', { parse_id: true }) do |record|
66
- yield record if block_given?
67
- end
68
- records
60
+ def groups(options = {})
61
+ all('groups', options)
69
62
  end
70
63
 
71
- def group_user_assignment(users_with_roles, params = { with_members: true })
64
+ def group_user_assignment(users_with_roles)
72
65
  updated = []
73
- groups do |group|
74
- changed = false
66
+ groups.each do |group|
67
+ group = get("groups/#{uri_to_id(group['uri'])}").parsed
68
+ update = false
75
69
 
76
70
  users_with_roles.each do |user, roles|
77
- if roles.include? group["group_code"]
78
- unless group["member_usernames"].include? user
79
- group["member_usernames"] << user
80
- changed = true
81
- end
82
- else
83
- if group["member_usernames"].include? user
84
- group["member_usernames"].delete user
85
- changed = true
71
+ # should the user still belong to this group?
72
+ if group['member_usernames'].include?(user)
73
+ unless roles.include? group['group_code']
74
+ group['member_usernames'].delete user
75
+ update = true
86
76
  end
77
+ # should the user be added to this group?
78
+ elsif roles.include? group['group_code']
79
+ group['member_usernames'] << user
80
+ update = true
87
81
  end
88
82
  end
89
83
 
90
- if changed
91
- id = group["uri"].split("/")[-1]
92
- response = post( "/groups/#{id}", group, params )
93
- updated << response.parsed
94
- end
84
+ next unless update
85
+
86
+ response = post("/groups/#{uri_to_id(group['uri'])}", group.to_json)
87
+ updated << response
95
88
  end
96
89
  updated
97
90
  end
98
91
 
99
92
  def login
100
- username, password = config.username, config.password
93
+ username = config.username
94
+ password = config.password
101
95
  result = request('POST', "/users/#{username}/login", { query: { password: password } })
102
- raise ConnectionError.new "Failed to connect to ArchivesSpace backend as #{username} #{password}" unless result.parsed["session"]
103
- @token = result.parsed["session"]
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["username"] == username }
109
- raise RequestError.new(user.status) unless user
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
- def repositories
114
- records = get('repositories').parsed.each do |record|
115
- yield record if block_given?
116
- end
117
- records
108
+ post(user['uri'], user.to_json, { password: password })
118
109
  end
119
110
 
120
- def repositories_with_agent
121
- #
111
+ def repositories(options = {})
112
+ all('repositories', options)
122
113
  end
123
114
 
124
- def resource_to_xml(resource, format = "ead", options = {})
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(format = nil, options = {}, &block)
131
- path = 'resources'
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
- def search(params)
147
- # get "search", params
148
- end
121
+ # def search(params)
122
+ # # TODO: get "search", params
123
+ # end
149
124
 
150
- def users
151
- records = all('users') do |record|
152
- yield record if block_given?
153
- end
154
- records
125
+ def uri_to_id(uri)
126
+ uri.split('/').last
155
127
  end
156
128
 
157
- private
158
-
159
- def get_xml(path, options = {})
160
- # add xml headers
161
- response = get(path, options)
162
- raise RequestError.new(response.body) unless response.status_code == 200
163
- Nokogiri::XML(response.body).to_xml
129
+ def users(options = {})
130
+ all('users', options)
164
131
  end
165
-
166
132
  end
167
-
168
- end
133
+ end
@@ -1,5 +1,6 @@
1
- module ArchivesSpace
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
- "Content-Type" => "application/json",
13
- "Content-Length" => "nnnn",
13
+ 'Content-Type' => 'application/json',
14
+ 'Content-Length' => 'nnnn'
14
15
  },
15
16
  put: {
16
- "Content-Type" => "application/json",
17
- "Content-Length" => "nnnn",
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 = "GET", path = "", options = {})
24
- @config = config
25
- @method = method.downcase.to_sym
26
- @path = 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
- @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.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
42
  end
@@ -1,10 +1,10 @@
1
- module ArchivesSpace
1
+ # frozen_string_literal: true
2
2
 
3
+ module ArchivesSpace
3
4
  class Response
4
- attr_reader :result, :parsed, :body, :headers, :status, :status_code, :xml
5
+ attr_reader :result, :parsed, :body, :headers, :status, :status_code
5
6
 
6
7
  def initialize(result)
7
- # throw error
8
8
  @result = result
9
9
  @parsed = result.parsed_response
10
10
  @body = result.body
@@ -12,7 +12,5 @@ module ArchivesSpace
12
12
  @status = result.response
13
13
  @status_code = result.code.to_i
14
14
  end
15
-
16
15
  end
17
-
18
- end
16
+ end
@@ -1,25 +1,26 @@
1
- module ArchivesSpace
1
+ # frozen_string_literal: true
2
2
 
3
+ module ArchivesSpace
3
4
  module Template
4
-
5
5
  def self.list
6
- []
6
+ Dir.glob File.join(templates_path, '*.erb')
7
7
  end
8
8
 
9
- def self.process_template(template, data)
10
- t = ERB.new(self.read_template(template))
11
- r = t.result(binding).gsub(/\n+/,"\n")
12
- JSON.parse(r)
9
+ def self.process(template, data)
10
+ t = ERB.new(read(template))
11
+ r = t.result(binding).gsub(/\n+/, "\n")
12
+ JSON.parse(r).to_json
13
13
  end
14
14
 
15
- def self.read_template(file)
16
- File.read("#{self.templates_path}/#{file.to_s}.json.erb")
15
+ def self.read(file)
16
+ File.read("#{templates_path}/#{file}.json.erb")
17
17
  end
18
18
 
19
19
  def self.templates_path
20
- File.join(File.dirname(File.expand_path(__FILE__)), 'templates')
20
+ ENV.fetch(
21
+ 'ARCHIVESSPACE_CLIENT_TEMPLATES_PATH',
22
+ File.join(File.dirname(File.expand_path(__FILE__)), 'templates')
23
+ )
21
24
  end
22
-
23
25
  end
24
-
25
- end
26
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ArchivesSpace
2
4
  class Client
3
- VERSION = "0.1.3"
5
+ VERSION = '0.1.8'
4
6
  end
5
7
  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 "Configuration" do
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 "Version information" do
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 "can retrieve the backend version info" do
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 "version"
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
- base_uri: CUSTOM_BASE_URI,
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
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ArchivesSpace::Template do
6
+ it 'can list the default templates' do
7
+ templates = ArchivesSpace::Template.list
8
+ expect(templates).to_not be_empty
9
+ expect(templates).to include(/repository_with_agent.*erb/)
10
+ end
11
+
12
+ it 'can change the path when template envvar is set' do
13
+ expect(ArchivesSpace::Template.templates_path).to match(
14
+ /#{File.join('lib', 'archivesspace', 'client', 'templates')}/
15
+ )
16
+ ENV['ARCHIVESSPACE_CLIENT_TEMPLATES_PATH'] = '/path/to/nowhere'
17
+ expect(ArchivesSpace::Template.templates_path).to eq '/path/to/nowhere'
18
+ ENV.delete('ARCHIVESSPACE_CLIENT_TEMPLATES_PATH')
19
+ end
20
+
21
+ it 'can process a template' do
22
+ data = { repo_code: 'ABC', name: 'ABC Archive', agent_contact_name: 'ABC Admin' }
23
+ json = JSON.parse(ArchivesSpace::Template.process(:repository_with_agent, data))
24
+ expect(json['repository']['repo_code']).to eq data[:repo_code]
25
+ end
26
+ end
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: http://localhost:8089//users/admin/login?password=admin
5
+ uri: http://localhost:8089/users/admin/login?password=admin
6
6
  body:
7
7
  encoding: UTF-8
8
8
  string: ''
data/spec/spec_helper.rb CHANGED
@@ -1,14 +1,16 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
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 = "http://localhost:8089"
8
- CUSTOM_BASE_URI = "https://archives.university.edu/api"
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 = "spec/fixtures/cassettes"
13
+ c.cassette_library_dir = 'spec/fixtures/cassettes'
12
14
  c.hook_into :webmock
13
- c.default_cassette_options = { :record => :once }
14
- end
15
+ c.default_cassette_options = { record: :once }
16
+ end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: archivesspace-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Cooper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-01 00:00:00.000000000 Z
11
+ date: 2021-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: awesome_print
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.10'
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: '1.10'
26
+ version: 1.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,63 +94,49 @@ dependencies:
80
94
  - - '='
81
95
  - !ruby/object:Gem::Version
82
96
  version: 3.0.1
83
- - !ruby/object:Gem::Dependency
84
- name: awesome_print
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 1.8.0
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 1.8.0
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.14.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.14.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: 2.0.3
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: 2.0.3
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: 1.6.8.1
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: 1.6.8.1
139
- description: Interact with ArchivesSpace via its RESTful API.
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: []
@@ -155,6 +155,7 @@ files:
155
155
  - examples/password_reset.rb
156
156
  - examples/repo_and_user.rb
157
157
  - examples/test_connection.rb
158
+ - examples/user_groups.rb
158
159
  - lib/archivesspace/client.rb
159
160
  - lib/archivesspace/client/client.rb
160
161
  - lib/archivesspace/client/configuration.rb
@@ -169,6 +170,7 @@ files:
169
170
  - lib/archivesspace/client/version.rb
170
171
  - spec/archivesspace/client_spec.rb
171
172
  - spec/archivesspace/configuration_spec.rb
173
+ - spec/archivesspace/templates_spec.rb
172
174
  - spec/fixtures/cassettes/backend_version.yml
173
175
  - spec/spec_helper.rb
174
176
  homepage: ''
@@ -190,13 +192,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
192
  - !ruby/object:Gem::Version
191
193
  version: '0'
192
194
  requirements: []
193
- rubyforge_project:
194
- rubygems_version: 2.6.10
195
+ rubygems_version: 3.1.6
195
196
  signing_key:
196
197
  specification_version: 4
197
- summary: Interact with ArchivesSpace via its RESTful API.
198
+ summary: Interact with ArchivesSpace via the API.
198
199
  test_files:
199
200
  - spec/archivesspace/client_spec.rb
200
201
  - spec/archivesspace/configuration_spec.rb
202
+ - spec/archivesspace/templates_spec.rb
201
203
  - spec/fixtures/cassettes/backend_version.yml
202
204
  - spec/spec_helper.rb