archivesspace-client 0.1.8 → 0.1.12
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 +4 -4
- data/.github/workflows/ci.yml +22 -0
- data/.github/workflows/publish.yml +42 -0
- data/README.md +31 -15
- data/Rakefile +12 -2
- data/archivesspace-client.gemspec +6 -0
- data/examples/user_groups.rb +1 -1
- data/exe/asclient +7 -0
- data/features/exec.feature +4 -0
- data/features/support/setup.rb +9 -0
- data/features/version.feature +12 -0
- data/lib/archivesspace/client/cli/exec.rb +44 -0
- data/lib/archivesspace/client/cli/version.rb +16 -0
- data/lib/archivesspace/client/cli.rb +24 -0
- data/lib/archivesspace/client/client.rb +26 -1
- data/lib/archivesspace/client/configuration.rb +1 -0
- data/lib/archivesspace/client/pagination.rb +60 -0
- data/lib/archivesspace/client/request.rb +4 -2
- data/lib/archivesspace/client/task.rb +70 -0
- data/lib/archivesspace/client/version.rb +1 -1
- data/lib/archivesspace/client.rb +13 -1
- data/spec/archivesspace/client_spec.rb +51 -0
- data/spec/archivesspace/templates_spec.rb +1 -1
- metadata +101 -4
- data/lib/archivesspace/client/helpers.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c009f995726401b9fd781b18796903276b19c2aabb3d6ec8722d60a36ea86600
|
4
|
+
data.tar.gz: 3985545e091850851567ebc1706252da34922120222dd491ca7ae58928e30b19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef5a03e03271cb24133b3f82e2304162a5ede929453bb4af99edc8f011f260f204b390960b30ed691bd569af15813f0a0ee9e8063d4599d78e69eb833aad5b17
|
7
|
+
data.tar.gz: ef541e1ebd699335e4333d195a7ac3e5a554b96543c2f1432e26c056751d584b7a7f1db0c4c0369cbc881e9c6b626286414103b728f778b69a81af1511678eb9
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: CI
|
2
|
+
on: [pull_request]
|
3
|
+
|
4
|
+
# TODO: add linters (rubocop)
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
tests:
|
8
|
+
name: Tests
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- name: Checkout code
|
12
|
+
uses: actions/checkout@v3
|
13
|
+
|
14
|
+
- name: Setup Ruby and install gems
|
15
|
+
uses: ruby/setup-ruby@v1
|
16
|
+
with:
|
17
|
+
bundler-cache: true
|
18
|
+
ruby-version: 2.7
|
19
|
+
|
20
|
+
- name: Run tests
|
21
|
+
run: |
|
22
|
+
bundle exec rake
|
@@ -0,0 +1,42 @@
|
|
1
|
+
name: Publish Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
- master
|
8
|
+
jobs:
|
9
|
+
publish:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
permissions:
|
12
|
+
contents: write
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v3
|
16
|
+
|
17
|
+
- name: Setup Ruby and install gems
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
bundler-cache: true
|
21
|
+
ruby-version: 2.7
|
22
|
+
rubygems: latest
|
23
|
+
|
24
|
+
- name: Release Gem
|
25
|
+
run: |
|
26
|
+
VERSION=$(ruby -e "puts eval(File.read('$GEM_NAME.gemspec')).version")
|
27
|
+
GEM_VERSION=$(gem list --exact --remote $GEM_NAME)
|
28
|
+
|
29
|
+
# Publish to RubyGems.org
|
30
|
+
if [ "${GEM_VERSION}" != "$GEM_NAME (${VERSION})" ]; then
|
31
|
+
gem build $GEM_NAME.gemspec
|
32
|
+
gem push "$GEM_NAME-${VERSION}.gem"
|
33
|
+
fi
|
34
|
+
|
35
|
+
# Create a release tag
|
36
|
+
if ! git ls-remote --tags --exit-code origin v${VERSION}; then
|
37
|
+
git tag v${VERSION}
|
38
|
+
git push --tags
|
39
|
+
fi
|
40
|
+
env:
|
41
|
+
GEM_HOST_API_KEY: "${{ secrets.RUBYGEMS_AUTH_TOKEN }}"
|
42
|
+
GEM_NAME: archivesspace-client
|
data/README.md
CHANGED
@@ -77,14 +77,16 @@ See `helpers.rb` for more convenience methods such as `client.digital_objects` e
|
|
77
77
|
|
78
78
|
**Setting a repository context**
|
79
79
|
|
80
|
-
|
80
|
+
Use the `repository` method to add a repository scope to requests (this is optional).
|
81
81
|
|
82
82
|
```ruby
|
83
|
-
client.
|
84
|
-
client.get('digital_objects') # instead of "repositories/2/digital_objects" etc.
|
83
|
+
client.repository(2)
|
84
|
+
client.get('digital_objects', query: {page: 1}) # instead of "repositories/2/digital_objects" etc.
|
85
85
|
|
86
86
|
# to reset
|
87
|
-
client.
|
87
|
+
client.repository(nil)
|
88
|
+
# or
|
89
|
+
client.use_global_repository
|
88
90
|
```
|
89
91
|
|
90
92
|
## Templates
|
@@ -116,6 +118,29 @@ response = client.post('/repositories/with_agent', json)
|
|
116
118
|
puts response.result.success? ? '=)' : '=('
|
117
119
|
```
|
118
120
|
|
121
|
+
## CLI
|
122
|
+
|
123
|
+
Create an `~/.asclientrc` file with a json version of the client configuration:
|
124
|
+
|
125
|
+
```json
|
126
|
+
{
|
127
|
+
"base_uri": "https://archives.university.edu/api",
|
128
|
+
"base_repo": "",
|
129
|
+
"username": "admin",
|
130
|
+
"password": "123456",
|
131
|
+
"page_size": 50,
|
132
|
+
"throttle": 0,
|
133
|
+
"verify_ssl": false
|
134
|
+
}
|
135
|
+
```
|
136
|
+
|
137
|
+
Run commands:
|
138
|
+
|
139
|
+
```bash
|
140
|
+
# when using locally via the repo prefix commands with ./exe/ i.e. ./exe/asclient -v
|
141
|
+
asclient -v
|
142
|
+
```
|
143
|
+
|
119
144
|
## Development
|
120
145
|
|
121
146
|
To run the examples start a local instance of ArchivesSpace then:
|
@@ -136,17 +161,8 @@ bundle exec rake
|
|
136
161
|
|
137
162
|
## Publishing
|
138
163
|
|
139
|
-
|
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
|
-
```
|
164
|
+
When an updated version (`lib/archivesspace/client/version.rb`) is merged into the
|
165
|
+
main/master branch a new release will be built and published.
|
150
166
|
|
151
167
|
## Contributing
|
152
168
|
|
data/Rakefile
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
|
-
require 'rspec/core/rake_task'
|
5
4
|
|
5
|
+
require 'rspec/core/rake_task'
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
|
8
|
-
|
8
|
+
# require 'rubocop/rake_task'
|
9
|
+
# RuboCop::RakeTask.new
|
10
|
+
|
11
|
+
require 'cucumber/rake/task'
|
12
|
+
Cucumber::Rake::Task.new
|
13
|
+
|
14
|
+
task default: %i[spec cucumber]
|
15
|
+
|
16
|
+
task :version do
|
17
|
+
puts ArchivesSpace::Client::VERSION
|
18
|
+
end
|
@@ -19,13 +19,19 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
+
spec.add_development_dependency 'aruba'
|
22
23
|
spec.add_development_dependency 'awesome_print', '~> 1.8.0'
|
23
24
|
spec.add_development_dependency 'bundler'
|
25
|
+
spec.add_development_dependency 'capybara_discoball'
|
26
|
+
spec.add_development_dependency 'cucumber'
|
27
|
+
spec.add_development_dependency 'json_spec'
|
24
28
|
spec.add_development_dependency 'rake', '~> 10.0'
|
25
29
|
spec.add_development_dependency 'rspec', '3.6.0'
|
30
|
+
spec.add_development_dependency 'rubocop'
|
26
31
|
spec.add_development_dependency 'vcr', '3.0.3'
|
27
32
|
spec.add_development_dependency 'webmock', '3.0.1'
|
28
33
|
|
34
|
+
spec.add_dependency 'dry-cli', '~> 0.7'
|
29
35
|
spec.add_dependency 'httparty', '~> 0.14'
|
30
36
|
spec.add_dependency 'json', '~> 2.0'
|
31
37
|
spec.add_dependency 'nokogiri', '~> 1.10'
|
data/examples/user_groups.rb
CHANGED
data/exe/asclient
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Feature: Version
|
2
|
+
Scenario: Output with 'v'
|
3
|
+
When I run `asclient v`
|
4
|
+
Then the output should match /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/
|
5
|
+
|
6
|
+
Scenario: Output with -v
|
7
|
+
When I run `asclient -v`
|
8
|
+
Then the output should match /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/
|
9
|
+
|
10
|
+
Scenario: Output with --version
|
11
|
+
When I run `asclient --version`
|
12
|
+
Then the output should match /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArchivesSpace
|
4
|
+
class Client
|
5
|
+
module CLI
|
6
|
+
# ArchivesSpace::Client::CLI::Exec executes an API request
|
7
|
+
class Exec < Dry::CLI::Command
|
8
|
+
desc 'Execute an API request'
|
9
|
+
|
10
|
+
argument :type, required: true, values: %i[get post put delete], desc: 'API request type'
|
11
|
+
argument :path, required: true, desc: 'API request path'
|
12
|
+
|
13
|
+
option :rid, type: :integer, default: nil, desc: 'Repository id'
|
14
|
+
option :payload, type: :string, default: '{}', desc: 'Data payload (json)'
|
15
|
+
option :params, type: :string, default: '{}', desc: 'Params (json)'
|
16
|
+
|
17
|
+
example [
|
18
|
+
'exec get --rid 2 "resources/1"',
|
19
|
+
'exec get users --params \'{"query": {"page": 1}}\''
|
20
|
+
]
|
21
|
+
|
22
|
+
def call(type:, path:, rid: nil, payload: '{}', params: '{}', **)
|
23
|
+
client = ArchivesSpace::Client::CLI.client
|
24
|
+
client.repository(rid) if rid
|
25
|
+
type = type.to_sym
|
26
|
+
payload = JSON.parse(payload, symbolize_names: true)
|
27
|
+
params = JSON.parse(params, symbolize_names: true)
|
28
|
+
|
29
|
+
response = case type
|
30
|
+
when :get
|
31
|
+
client.get(path, params)
|
32
|
+
when :post
|
33
|
+
client.post(path, payload, params)
|
34
|
+
when :put
|
35
|
+
client.put(path, payload, params)
|
36
|
+
when :delete
|
37
|
+
client.delete(path)
|
38
|
+
end
|
39
|
+
puts JSON.generate(response.parsed)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArchivesSpace
|
4
|
+
class Client
|
5
|
+
module CLI
|
6
|
+
# ArchivesSpace::Client::CLI::Version prints version
|
7
|
+
class Version < Dry::CLI::Command
|
8
|
+
desc 'Print ArchivesSpace Client version'
|
9
|
+
|
10
|
+
def call(*)
|
11
|
+
puts ArchivesSpace::Client::VERSION
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArchivesSpace
|
4
|
+
class Client
|
5
|
+
module CLI
|
6
|
+
extend Dry::CLI::Registry
|
7
|
+
|
8
|
+
def self.client
|
9
|
+
cfg = ArchivesSpace::Configuration.new(ArchivesSpace::Client::CLI.find_config)
|
10
|
+
ArchivesSpace::Client.new(cfg).login
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.find_config
|
14
|
+
config = ENV.fetch('ASCLIENT_CFG', File.join(ENV['HOME'], '.asclientrc'))
|
15
|
+
raise "Unable to find asclient configuration file at: #{config}" unless File.file?(config)
|
16
|
+
|
17
|
+
JSON.parse(File.read(config), symbolize_names: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
register 'exec', Exec, aliases: ['e', '-e']
|
21
|
+
register 'version', Version, aliases: ['v', '-v', '--version']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
module ArchivesSpace
|
4
4
|
class Client
|
5
|
-
include
|
5
|
+
include Pagination
|
6
|
+
include Task
|
6
7
|
attr_accessor :token
|
7
8
|
attr_reader :config
|
8
9
|
|
@@ -13,6 +14,10 @@ module ArchivesSpace
|
|
13
14
|
@token = nil
|
14
15
|
end
|
15
16
|
|
17
|
+
def backend_version
|
18
|
+
get 'version'
|
19
|
+
end
|
20
|
+
|
16
21
|
def get(path, options = {})
|
17
22
|
request 'GET', path, options
|
18
23
|
end
|
@@ -29,6 +34,26 @@ module ArchivesSpace
|
|
29
34
|
request 'DELETE', path
|
30
35
|
end
|
31
36
|
|
37
|
+
# Scoping requests
|
38
|
+
def repository(id)
|
39
|
+
if id.nil?
|
40
|
+
use_global_repository
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
begin
|
45
|
+
Integer(id)
|
46
|
+
rescue StandardError
|
47
|
+
raise RepositoryIdError, "Invalid Repository id: #{id}"
|
48
|
+
end
|
49
|
+
|
50
|
+
@config.base_repo = "repositories/#{id}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def use_global_repository
|
54
|
+
@config.base_repo = ''
|
55
|
+
end
|
56
|
+
|
32
57
|
private
|
33
58
|
|
34
59
|
def request(method, path, options = {})
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArchivesSpace
|
4
|
+
# Handle API Pagination using enumerator
|
5
|
+
module Pagination
|
6
|
+
# TODO: get via lookup of endpoints that support pagination? (nice-to-have)
|
7
|
+
ENDPOINTS = %w[
|
8
|
+
accessions
|
9
|
+
agents/corporate_entities
|
10
|
+
agents/families
|
11
|
+
agents/people
|
12
|
+
agents/software
|
13
|
+
archival_objects
|
14
|
+
digital_objects
|
15
|
+
groups
|
16
|
+
repositories
|
17
|
+
resources
|
18
|
+
subjects
|
19
|
+
users
|
20
|
+
]
|
21
|
+
|
22
|
+
ENDPOINTS.each do |endpoint|
|
23
|
+
method_name = endpoint.split('/').last # remove prefix
|
24
|
+
define_method(method_name) do |options = {}|
|
25
|
+
all(endpoint, options)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def all(path, options = {})
|
30
|
+
Enumerator.new do |yielder|
|
31
|
+
page = 1
|
32
|
+
unlimited_listing = false
|
33
|
+
loop do
|
34
|
+
options[:query] ||= {}
|
35
|
+
options[:query][:page] = page
|
36
|
+
result = get(path, options)
|
37
|
+
results = []
|
38
|
+
|
39
|
+
if result.parsed.respond_to?(:key) && result.parsed.key?('results')
|
40
|
+
results = result.parsed['results']
|
41
|
+
else
|
42
|
+
results = result.parsed
|
43
|
+
unlimited_listing = true
|
44
|
+
end
|
45
|
+
|
46
|
+
if results.any?
|
47
|
+
results.each do |i|
|
48
|
+
yielder << i
|
49
|
+
end
|
50
|
+
raise StopIteration if unlimited_listing
|
51
|
+
|
52
|
+
page += 1
|
53
|
+
else
|
54
|
+
raise StopIteration
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end.lazy
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -26,12 +26,14 @@ module ArchivesSpace
|
|
26
26
|
@method = method.downcase.to_sym
|
27
27
|
@path = path.gsub(%r{^/+}, '')
|
28
28
|
@options = options
|
29
|
-
@options[:headers] =
|
29
|
+
@options[:headers] =
|
30
|
+
options[:headers] ? default_headers(@method).merge(options[:headers]) : default_headers(@method)
|
30
31
|
@options[:verify] = config.verify_ssl
|
31
32
|
@options[:query] = {} unless options.key? :query
|
32
33
|
|
33
|
-
|
34
|
+
self.class.debug_output($stdout) if @config.debug
|
34
35
|
|
36
|
+
base_uri = config.base_repo&.length&.positive? ? File.join(config.base_uri, config.base_repo) : config.base_uri
|
35
37
|
self.class.base_uri base_uri
|
36
38
|
end
|
37
39
|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArchivesSpace
|
4
|
+
# Perform specific API tasks
|
5
|
+
module Task
|
6
|
+
# def batch_import(payload, params = {})
|
7
|
+
# # TODO: create "batch_import", payload, params
|
8
|
+
# end
|
9
|
+
|
10
|
+
def group_user_assignment(users_with_roles)
|
11
|
+
updated = []
|
12
|
+
groups.each do |group|
|
13
|
+
group = get("groups/#{uri_to_id(group['uri'])}").parsed
|
14
|
+
update = false
|
15
|
+
|
16
|
+
users_with_roles.each do |user, roles|
|
17
|
+
# should the user still belong to this group?
|
18
|
+
if group['member_usernames'].include?(user)
|
19
|
+
unless roles.include? group['group_code']
|
20
|
+
group['member_usernames'].delete user
|
21
|
+
update = true
|
22
|
+
end
|
23
|
+
# should the user be added to this group?
|
24
|
+
elsif roles.include? group['group_code']
|
25
|
+
group['member_usernames'] << user
|
26
|
+
update = true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
next unless update
|
31
|
+
|
32
|
+
response = post("/groups/#{uri_to_id(group['uri'])}", group.to_json)
|
33
|
+
updated << response
|
34
|
+
end
|
35
|
+
updated
|
36
|
+
end
|
37
|
+
|
38
|
+
def login
|
39
|
+
username = config.username
|
40
|
+
password = config.password
|
41
|
+
base_repo = config.base_repo
|
42
|
+
use_global_repository # ensure we're in the global scope to login
|
43
|
+
result = request('POST', "/users/#{username}/login", { query: { password: password } })
|
44
|
+
unless result.parsed['session']
|
45
|
+
raise ConnectionError, "API client login failed as user [#{username}], check username and password are correct"
|
46
|
+
end
|
47
|
+
|
48
|
+
config.base_repo = base_repo # reset repo as set by the cfg
|
49
|
+
@token = result.parsed['session']
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def password_reset(username, password)
|
54
|
+
user = all('users').find { |u| u['username'] == username }
|
55
|
+
raise RequestError, user.status unless user
|
56
|
+
|
57
|
+
post(user['uri'], user.to_json, { password: password })
|
58
|
+
end
|
59
|
+
|
60
|
+
# def search(params)
|
61
|
+
# # TODO: get "search", params
|
62
|
+
# end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def uri_to_id(uri)
|
67
|
+
uri.split('/').last
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/archivesspace/client.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'dry/cli'
|
3
4
|
require 'httparty'
|
4
5
|
require 'json'
|
5
6
|
require 'nokogiri'
|
6
7
|
|
7
8
|
# mixins required first
|
8
|
-
require 'archivesspace/client/
|
9
|
+
require 'archivesspace/client/pagination'
|
10
|
+
require 'archivesspace/client/task'
|
9
11
|
|
10
12
|
require 'archivesspace/client/client'
|
11
13
|
require 'archivesspace/client/configuration'
|
@@ -14,9 +16,19 @@ require 'archivesspace/client/response'
|
|
14
16
|
require 'archivesspace/client/template'
|
15
17
|
require 'archivesspace/client/version'
|
16
18
|
|
19
|
+
# cli
|
20
|
+
require 'archivesspace/client/cli/exec'
|
21
|
+
require 'archivesspace/client/cli/version'
|
22
|
+
require 'archivesspace/client/cli' # load the registry last
|
23
|
+
|
17
24
|
module ArchivesSpace
|
18
25
|
class ConnectionError < RuntimeError; end
|
26
|
+
|
19
27
|
class ContextError < RuntimeError; end
|
28
|
+
|
29
|
+
class RepositoryIdError < RuntimeError; end
|
30
|
+
|
20
31
|
class ParamsError < RuntimeError; end
|
32
|
+
|
21
33
|
class RequestError < RuntimeError; end
|
22
34
|
end
|
@@ -22,6 +22,57 @@ describe ArchivesSpace::Client do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
describe 'Repository scoping' do
|
26
|
+
it 'will set the repository with an integer id' do
|
27
|
+
client = ArchivesSpace::Client.new
|
28
|
+
client.repository 2
|
29
|
+
expect(client.config.base_repo).to eq 'repositories/2'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'will set the repository with a string id cast to integer' do
|
33
|
+
client = ArchivesSpace::Client.new
|
34
|
+
client.repository '2'
|
35
|
+
expect(client.config.base_repo).to eq 'repositories/2'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'will fail if the id cannot be cast to integer' do
|
39
|
+
client = ArchivesSpace::Client.new
|
40
|
+
expect { client.repository('xyz') }.to raise_error(
|
41
|
+
ArchivesSpace::RepositoryIdError
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'will use the global repo if repository is passed nil' do
|
46
|
+
client = ArchivesSpace::Client.new
|
47
|
+
client.repository 2
|
48
|
+
client.repository nil
|
49
|
+
expect(client.config.base_repo).to eq ''
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'will use the global repo when the method is called' do
|
53
|
+
client = ArchivesSpace::Client.new
|
54
|
+
client.repository 2
|
55
|
+
client.use_global_repository
|
56
|
+
expect(client.config.base_repo).to eq ''
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'Pagination' do
|
61
|
+
it 'will have a method for defined paginated record types' do
|
62
|
+
client = ArchivesSpace::Client.new
|
63
|
+
ArchivesSpace::Pagination::ENDPOINTS.each do |e|
|
64
|
+
next if e.match?('/')
|
65
|
+
|
66
|
+
expect(client.respond_to?(e.to_sym)).to be true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'will have a method for defined paginated record types with multipart path' do
|
71
|
+
client = ArchivesSpace::Client.new
|
72
|
+
expect(client.respond_to?(:people)).to be true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
25
76
|
describe 'Version information' do
|
26
77
|
it 'has a version number' do
|
27
78
|
expect(ArchivesSpace::Client::VERSION).not_to be nil
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
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.12
|
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: 2022-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aruba
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: awesome_print
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,48 @@ dependencies:
|
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: capybara_discoball
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: cucumber
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: json_spec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
41
97
|
- !ruby/object:Gem::Dependency
|
42
98
|
name: rake
|
43
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +122,20 @@ dependencies:
|
|
66
122
|
- - '='
|
67
123
|
- !ruby/object:Gem::Version
|
68
124
|
version: 3.6.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
69
139
|
- !ruby/object:Gem::Dependency
|
70
140
|
name: vcr
|
71
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +164,20 @@ dependencies:
|
|
94
164
|
- - '='
|
95
165
|
- !ruby/object:Gem::Version
|
96
166
|
version: 3.0.1
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: dry-cli
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.7'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.7'
|
97
181
|
- !ruby/object:Gem::Dependency
|
98
182
|
name: httparty
|
99
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -143,6 +227,8 @@ executables: []
|
|
143
227
|
extensions: []
|
144
228
|
extra_rdoc_files: []
|
145
229
|
files:
|
230
|
+
- ".github/workflows/ci.yml"
|
231
|
+
- ".github/workflows/publish.yml"
|
146
232
|
- ".gitignore"
|
147
233
|
- ".rspec"
|
148
234
|
- ".travis.yml"
|
@@ -156,12 +242,20 @@ files:
|
|
156
242
|
- examples/repo_and_user.rb
|
157
243
|
- examples/test_connection.rb
|
158
244
|
- examples/user_groups.rb
|
245
|
+
- exe/asclient
|
246
|
+
- features/exec.feature
|
247
|
+
- features/support/setup.rb
|
248
|
+
- features/version.feature
|
159
249
|
- lib/archivesspace/client.rb
|
250
|
+
- lib/archivesspace/client/cli.rb
|
251
|
+
- lib/archivesspace/client/cli/exec.rb
|
252
|
+
- lib/archivesspace/client/cli/version.rb
|
160
253
|
- lib/archivesspace/client/client.rb
|
161
254
|
- lib/archivesspace/client/configuration.rb
|
162
|
-
- lib/archivesspace/client/
|
255
|
+
- lib/archivesspace/client/pagination.rb
|
163
256
|
- lib/archivesspace/client/request.rb
|
164
257
|
- lib/archivesspace/client/response.rb
|
258
|
+
- lib/archivesspace/client/task.rb
|
165
259
|
- lib/archivesspace/client/template.rb
|
166
260
|
- lib/archivesspace/client/templates/digital_object.json.erb
|
167
261
|
- lib/archivesspace/client/templates/repository.json.erb
|
@@ -192,11 +286,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
286
|
- !ruby/object:Gem::Version
|
193
287
|
version: '0'
|
194
288
|
requirements: []
|
195
|
-
rubygems_version: 3.
|
289
|
+
rubygems_version: 3.3.16
|
196
290
|
signing_key:
|
197
291
|
specification_version: 4
|
198
292
|
summary: Interact with ArchivesSpace via the API.
|
199
293
|
test_files:
|
294
|
+
- features/exec.feature
|
295
|
+
- features/support/setup.rb
|
296
|
+
- features/version.feature
|
200
297
|
- spec/archivesspace/client_spec.rb
|
201
298
|
- spec/archivesspace/configuration_spec.rb
|
202
299
|
- spec/archivesspace/templates_spec.rb
|
@@ -1,133 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# needed for roundtrip hash merging
|
4
|
-
class ::Hash
|
5
|
-
def deep_merge(second)
|
6
|
-
merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
|
7
|
-
merge(second, &merger)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
module ArchivesSpace
|
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
|
33
|
-
|
34
|
-
if results.any?
|
35
|
-
results.each do |i|
|
36
|
-
yielder << i
|
37
|
-
end
|
38
|
-
raise StopIteration if unlimited_listing
|
39
|
-
|
40
|
-
page += 1
|
41
|
-
else
|
42
|
-
raise StopIteration
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end.lazy
|
46
|
-
end
|
47
|
-
|
48
|
-
def backend_version
|
49
|
-
get 'version'
|
50
|
-
end
|
51
|
-
|
52
|
-
# def batch_import(payload, params = {})
|
53
|
-
# # TODO: create "batch_import", payload, params
|
54
|
-
# end
|
55
|
-
|
56
|
-
def digital_objects(options = {})
|
57
|
-
all('digital_objects', options)
|
58
|
-
end
|
59
|
-
|
60
|
-
def groups(options = {})
|
61
|
-
all('groups', options)
|
62
|
-
end
|
63
|
-
|
64
|
-
def group_user_assignment(users_with_roles)
|
65
|
-
updated = []
|
66
|
-
groups.each do |group|
|
67
|
-
group = get("groups/#{uri_to_id(group['uri'])}").parsed
|
68
|
-
update = false
|
69
|
-
|
70
|
-
users_with_roles.each do |user, roles|
|
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
|
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
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
next unless update
|
85
|
-
|
86
|
-
response = post("/groups/#{uri_to_id(group['uri'])}", group.to_json)
|
87
|
-
updated << response
|
88
|
-
end
|
89
|
-
updated
|
90
|
-
end
|
91
|
-
|
92
|
-
def login
|
93
|
-
username = config.username
|
94
|
-
password = config.password
|
95
|
-
result = request('POST', "/users/#{username}/login", { query: { password: password } })
|
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']
|
101
|
-
self
|
102
|
-
end
|
103
|
-
|
104
|
-
def password_reset(username, password)
|
105
|
-
user = all('users').find { |u| u['username'] == username }
|
106
|
-
raise RequestError, user.status unless user
|
107
|
-
|
108
|
-
post(user['uri'], user.to_json, { password: password })
|
109
|
-
end
|
110
|
-
|
111
|
-
def repositories(options = {})
|
112
|
-
all('repositories', options)
|
113
|
-
end
|
114
|
-
|
115
|
-
def repositories_with_agent; end
|
116
|
-
|
117
|
-
def resources(options = {})
|
118
|
-
all('resources', options)
|
119
|
-
end
|
120
|
-
|
121
|
-
# def search(params)
|
122
|
-
# # TODO: get "search", params
|
123
|
-
# end
|
124
|
-
|
125
|
-
def uri_to_id(uri)
|
126
|
-
uri.split('/').last
|
127
|
-
end
|
128
|
-
|
129
|
-
def users(options = {})
|
130
|
-
all('users', options)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|