archivesspace-client 0.1.12 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,23 +4,24 @@ module ArchivesSpace
4
4
  class Configuration
5
5
  def defaults
6
6
  {
7
- base_uri: 'http://localhost:8089',
8
- base_repo: '',
7
+ base_uri: "http://localhost:8089",
8
+ base_repo: "",
9
9
  debug: false,
10
- username: 'admin',
11
- password: 'admin',
10
+ username: "admin",
11
+ password: "admin",
12
12
  page_size: 50,
13
13
  throttle: 0,
14
- verify_ssl: true
14
+ verify_ssl: true,
15
+ timeout: 60
15
16
  }
16
17
  end
17
18
 
18
19
  def initialize(settings = {})
19
20
  settings = defaults.merge(settings)
20
21
  settings.each do |property, value|
21
- next unless defaults.keys.include? property
22
+ next unless defaults.key?(property)
22
23
 
23
- instance_variable_set("@#{property}", value)
24
+ instance_variable_set(:"@#{property}", value)
24
25
  self.class.send(:attr_accessor, property)
25
26
  end
26
27
  end
@@ -20,7 +20,7 @@ module ArchivesSpace
20
20
  ]
21
21
 
22
22
  ENDPOINTS.each do |endpoint|
23
- method_name = endpoint.split('/').last # remove prefix
23
+ method_name = endpoint.split("/").last # remove prefix
24
24
  define_method(method_name) do |options = {}|
25
25
  all(endpoint, options)
26
26
  end
@@ -36,8 +36,8 @@ module ArchivesSpace
36
36
  result = get(path, options)
37
37
  results = []
38
38
 
39
- if result.parsed.respond_to?(:key) && result.parsed.key?('results')
40
- results = result.parsed['results']
39
+ if result.parsed.respond_to?(:key) && result.parsed.key?("results")
40
+ results = result.parsed["results"]
41
41
  else
42
42
  results = result.parsed
43
43
  unlimited_listing = true
@@ -10,26 +10,28 @@ module ArchivesSpace
10
10
  delete: {},
11
11
  get: {},
12
12
  post: {
13
- 'Content-Type' => 'application/json',
14
- 'Content-Length' => 'nnnn'
13
+ "Content-Type" => "application/json",
14
+ "Content-Length" => "nnnn"
15
15
  },
16
16
  put: {
17
- 'Content-Type' => 'application/json',
18
- 'Content-Length' => 'nnnn'
17
+ "Content-Type" => "application/json",
18
+ "Content-Length" => "nnnn"
19
19
  }
20
20
  }
21
21
  headers[method]
22
22
  end
23
23
 
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
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
29
  @options[:headers] =
30
30
  options[:headers] ? default_headers(@method).merge(options[:headers]) : default_headers(@method)
31
- @options[:verify] = config.verify_ssl
32
- @options[:query] = {} unless options.key? :query
31
+ @options[:headers]["User-Agent"] = "#{Client::NAME}/#{Client::VERSION}"
32
+ @options[:verify] = config.verify_ssl
33
+ @options[:timeout] = config.timeout
34
+ @options[:query] = {} unless options.key? :query
33
35
 
34
36
  self.class.debug_output($stdout) if @config.debug
35
37
 
@@ -5,11 +5,11 @@ module ArchivesSpace
5
5
  attr_reader :result, :parsed, :body, :headers, :status, :status_code
6
6
 
7
7
  def initialize(result)
8
- @result = result
9
- @parsed = result.parsed_response
10
- @body = result.body
11
- @headers = result.headers
12
- @status = result.response
8
+ @result = result
9
+ @parsed = result.parsed_response
10
+ @body = result.body
11
+ @headers = result.headers
12
+ @status = result.response
13
13
  @status_code = result.code.to_i
14
14
  end
15
15
  end
@@ -10,51 +10,51 @@ module ArchivesSpace
10
10
  def group_user_assignment(users_with_roles)
11
11
  updated = []
12
12
  groups.each do |group|
13
- group = get("groups/#{uri_to_id(group['uri'])}").parsed
13
+ group = get("groups/#{uri_to_id(group["uri"])}").parsed
14
14
  update = false
15
15
 
16
16
  users_with_roles.each do |user, roles|
17
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
18
+ if group["member_usernames"].include?(user)
19
+ unless roles.include? group["group_code"]
20
+ group["member_usernames"].delete user
21
21
  update = true
22
22
  end
23
23
  # should the user be added to this group?
24
- elsif roles.include? group['group_code']
25
- group['member_usernames'] << user
24
+ elsif roles.include? group["group_code"]
25
+ group["member_usernames"] << user
26
26
  update = true
27
27
  end
28
28
  end
29
29
 
30
30
  next unless update
31
31
 
32
- response = post("/groups/#{uri_to_id(group['uri'])}", group.to_json)
32
+ response = post("/groups/#{uri_to_id(group["uri"])}", group.to_json)
33
33
  updated << response
34
34
  end
35
35
  updated
36
36
  end
37
37
 
38
38
  def login
39
- username = config.username
40
- password = config.password
39
+ username = config.username
40
+ password = config.password
41
41
  base_repo = config.base_repo
42
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']
43
+ result = request("POST", "/users/#{username}/login", {query: {password: password}})
44
+ unless result.parsed["session"]
45
45
  raise ConnectionError, "API client login failed as user [#{username}], check username and password are correct"
46
46
  end
47
47
 
48
48
  config.base_repo = base_repo # reset repo as set by the cfg
49
- @token = result.parsed['session']
49
+ @token = result.parsed["session"]
50
50
  self
51
51
  end
52
52
 
53
53
  def password_reset(username, password)
54
- user = all('users').find { |u| u['username'] == username }
54
+ user = all("users").find { |u| u["username"] == username }
55
55
  raise RequestError, user.status unless user
56
56
 
57
- post(user['uri'], user.to_json, { password: password })
57
+ post(user["uri"], user.to_json, {password: password})
58
58
  end
59
59
 
60
60
  # def search(params)
@@ -64,7 +64,7 @@ module ArchivesSpace
64
64
  private
65
65
 
66
66
  def uri_to_id(uri)
67
- uri.split('/').last
67
+ uri.split("/").last
68
68
  end
69
69
  end
70
70
  end
@@ -3,24 +3,67 @@
3
3
  module ArchivesSpace
4
4
  module Template
5
5
  def self.list
6
- Dir.glob File.join(templates_path, '*.erb')
6
+ Dir.glob ["*"], base: File.join(templates_path)
7
7
  end
8
8
 
9
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
- end
14
-
15
- def self.read(file)
16
- File.read("#{templates_path}/#{file}.json.erb")
10
+ processor = File.extname(template).delete(".").camelize
11
+ processor = Object.const_get("ArchivesSpace::Template::#{processor}")
12
+ processor.new(template, data).process
17
13
  end
18
14
 
19
15
  def self.templates_path
20
16
  ENV.fetch(
21
- 'ARCHIVESSPACE_CLIENT_TEMPLATES_PATH',
22
- File.join(File.dirname(File.expand_path(__FILE__)), 'templates')
17
+ "ARCHIVESSPACE_CLIENT_TEMPLATES_PATH",
18
+ File.join(File.dirname(File.expand_path(__FILE__)), "templates")
23
19
  )
24
20
  end
21
+
22
+ class Processor
23
+ attr_reader :template, :data
24
+
25
+ def initialize(template, data)
26
+ @template = template
27
+ @data = data
28
+
29
+ validate_template
30
+ end
31
+
32
+ def extension
33
+ raise "Not implemented"
34
+ end
35
+
36
+ def read_template
37
+ File.read(File.join(ArchivesSpace::Template.templates_path, template))
38
+ end
39
+
40
+ def validate_template
41
+ raise "Invalid template" unless File.extname(template).end_with? extension
42
+ end
43
+ end
44
+
45
+ class Erb < Processor
46
+ def extension
47
+ ".erb"
48
+ end
49
+
50
+ def process
51
+ t = ERB.new(read_template)
52
+ r = t.result(binding).squeeze("\n")
53
+ JSON.parse(r).to_json
54
+ end
55
+ end
56
+
57
+ class Jbuilder < Processor
58
+ def extension
59
+ ".jbuilder"
60
+ end
61
+
62
+ def process
63
+ ::Jbuilder.encode do |json|
64
+ eval(read_template, binding) # standard:disable Security/Eval
65
+ end
66
+ end
67
+ end
25
68
  end
26
69
  end
@@ -0,0 +1,7 @@
1
+ json.id_0 data["object_number"]
2
+ json.title data["title"]
3
+ json.level data["description_level"]
4
+
5
+ # json.id_0 "001.001"
6
+ # json.title "Title"
7
+ # json.level "collection"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ArchivesSpace
4
4
  class Client
5
- VERSION = '0.1.12'
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
@@ -1,34 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/cli'
4
- require 'httparty'
5
- require 'json'
6
- require 'nokogiri'
3
+ require "dry/cli"
4
+ require "httparty"
5
+ require "json"
6
+ require "nokogiri"
7
+ require "jbuilder"
7
8
 
8
9
  # mixins required first
9
- require 'archivesspace/client/pagination'
10
- require 'archivesspace/client/task'
10
+ require "archivesspace/client/pagination"
11
+ require "archivesspace/client/task"
11
12
 
12
- require 'archivesspace/client/client'
13
- require 'archivesspace/client/configuration'
14
- require 'archivesspace/client/request'
15
- require 'archivesspace/client/response'
16
- require 'archivesspace/client/template'
17
- require 'archivesspace/client/version'
13
+ require "archivesspace/client/client"
14
+ require "archivesspace/client/configuration"
15
+ require "archivesspace/client/request"
16
+ require "archivesspace/client/response"
17
+ require "archivesspace/client/template"
18
+ require "archivesspace/client/version"
18
19
 
19
20
  # cli
20
- require 'archivesspace/client/cli/exec'
21
- require 'archivesspace/client/cli/version'
22
- require 'archivesspace/client/cli' # load the registry last
21
+ require "archivesspace/client/cli/exec"
22
+ require "archivesspace/client/cli/version"
23
+ require "archivesspace/client/cli" # load the registry last
23
24
 
24
25
  module ArchivesSpace
25
26
  class ConnectionError < RuntimeError; end
26
27
 
27
- class ContextError < RuntimeError; end
28
+ class ContextError < RuntimeError; end
28
29
 
29
30
  class RepositoryIdError < RuntimeError; end
30
31
 
31
- class ParamsError < RuntimeError; end
32
+ class ParamsError < RuntimeError; end
32
33
 
33
- class RequestError < RuntimeError; end
34
+ class RequestError < RuntimeError; end
34
35
  end
@@ -1,87 +1,85 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe ArchivesSpace::Client do
6
6
  let(:client) { ArchivesSpace::Client.new }
7
- let(:login) { -> { client.login } }
8
7
 
9
- describe 'Configuration' do
10
- it 'will use the default configuration if none is provided' do
11
- client = ArchivesSpace::Client.new
8
+ describe "Configuration" do
9
+ it "will use the default configuration if none is provided" do
12
10
  expect(client.config.base_uri).to eq DEFAULT_BASE_URI
13
11
  end
14
12
 
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)
13
+ it "will raise an error if supplied configuration is of invalid type" do
14
+ expect { ArchivesSpace::Client.new({base_uri: CUSTOM_BASE_URI}) }.to raise_error(RuntimeError)
17
15
  end
18
16
 
19
- it 'will allow a configuration object to be provided' do
20
- client = ArchivesSpace::Client.new(ArchivesSpace::Configuration.new({ base_uri: CUSTOM_BASE_URI }))
17
+ it "will allow a configuration object to be provided" do
18
+ client = ArchivesSpace::Client.new(ArchivesSpace::Configuration.new({base_uri: CUSTOM_BASE_URI}))
21
19
  expect(client.config.base_uri).to eq CUSTOM_BASE_URI
22
20
  end
23
21
  end
24
22
 
25
- describe 'Repository scoping' do
26
- it 'will set the repository with an integer id' do
27
- client = ArchivesSpace::Client.new
23
+ describe "Repository scoping" do
24
+ it "will set the repository with an integer id" do
28
25
  client.repository 2
29
- expect(client.config.base_repo).to eq 'repositories/2'
26
+ expect(client.config.base_repo).to eq "repositories/2"
30
27
  end
31
28
 
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'
29
+ it "will set the repository with a string id cast to integer" do
30
+ client.repository "2"
31
+ expect(client.config.base_repo).to eq "repositories/2"
36
32
  end
37
33
 
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(
34
+ it "will fail if the id cannot be cast to integer" do
35
+ expect { client.repository("xyz") }.to raise_error(
41
36
  ArchivesSpace::RepositoryIdError
42
37
  )
43
38
  end
44
39
 
45
- it 'will use the global repo if repository is passed nil' do
46
- client = ArchivesSpace::Client.new
40
+ it "will use the global repo if repository is passed nil" do
47
41
  client.repository 2
48
42
  client.repository nil
49
- expect(client.config.base_repo).to eq ''
43
+ expect(client.config.base_repo).to eq ""
50
44
  end
51
45
 
52
- it 'will use the global repo when the method is called' do
53
- client = ArchivesSpace::Client.new
46
+ it "will use the global repo when the method is called" do
54
47
  client.repository 2
55
48
  client.use_global_repository
56
- expect(client.config.base_repo).to eq ''
49
+ expect(client.config.base_repo).to eq ""
57
50
  end
58
51
  end
59
52
 
60
- describe 'Pagination' do
61
- it 'will have a method for defined paginated record types' do
62
- client = ArchivesSpace::Client.new
53
+ describe "Requests" do
54
+ it "will have an identifiable user agent" do
55
+ request = ArchivesSpace::Request.new(client.config)
56
+ expect(request.options[:headers]["User-Agent"]).to eq "#{ArchivesSpace::Client::NAME}/#{ArchivesSpace::Client::VERSION}"
57
+ end
58
+ end
59
+
60
+ describe "Pagination" do
61
+ it "will have a method for defined paginated record types" do
63
62
  ArchivesSpace::Pagination::ENDPOINTS.each do |e|
64
- next if e.match?('/')
63
+ next if e.match?("/")
65
64
 
66
65
  expect(client.respond_to?(e.to_sym)).to be true
67
66
  end
68
67
  end
69
68
 
70
- it 'will have a method for defined paginated record types with multipart path' do
71
- client = ArchivesSpace::Client.new
69
+ it "will have a method for defined paginated record types with multipart path" do
72
70
  expect(client.respond_to?(:people)).to be true
73
71
  end
74
72
  end
75
73
 
76
- describe 'Version information' do
77
- it 'has a version number' do
74
+ describe "Version information" do
75
+ it "has a version number" do
78
76
  expect(ArchivesSpace::Client::VERSION).not_to be nil
79
77
  end
80
78
 
81
- it 'can retrieve the backend version info' do
82
- VCR.use_cassette('backend_version') do
83
- login.call
84
- response = client.get 'version'
79
+ it "can retrieve the backend version info" do
80
+ VCR.use_cassette("backend_version") do
81
+ client.login
82
+ response = client.get "version"
85
83
  expect(response.status_code).to eq(200)
86
84
  expect(response.body).to match(/ArchivesSpace \(.*\)/)
87
85
  end
@@ -1,28 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe ArchivesSpace::Configuration do
6
- it 'uses the default profile for configuration settings' do
6
+ it "uses the default profile for configuration settings" do
7
7
  config = ArchivesSpace::Configuration.new
8
8
  expect(config.base_uri).to eq DEFAULT_BASE_URI
9
9
  end
10
10
 
11
- it 'allows configuration settings to be provided' do
11
+ it "allows configuration settings to be provided" do
12
12
  config = ArchivesSpace::Configuration.new({
13
- base_uri: CUSTOM_BASE_URI
14
- })
13
+ base_uri: CUSTOM_BASE_URI
14
+ })
15
15
  expect(config.base_uri).to eq CUSTOM_BASE_URI
16
16
  end
17
17
 
18
- it 'allows the configuration properties to be updated' do
18
+ it "allows the configuration properties to be updated" do
19
19
  config = ArchivesSpace::Configuration.new
20
20
  config.base_uri = CUSTOM_BASE_URI
21
21
  expect(config.base_uri).to eq CUSTOM_BASE_URI
22
22
  end
23
23
 
24
- it 'ignores unrecognized configuration properties' do
25
- config = ArchivesSpace::Configuration.new({ xyz: 123 })
24
+ it "ignores unrecognized configuration properties" do
25
+ config = ArchivesSpace::Configuration.new({xyz: 123})
26
26
  expect { config.xyz }.to raise_error(NoMethodError)
27
27
  end
28
28
  end
@@ -1,26 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
5
  describe ArchivesSpace::Template do
6
- it 'can list the default templates' do
6
+ it "can list the default templates" do
7
7
  templates = ArchivesSpace::Template.list
8
8
  expect(templates).to_not be_empty
9
9
  expect(templates).to include(/repository_with_agent.*erb/)
10
+ expect(templates).to include(/resource.*jbuilder/)
10
11
  end
11
12
 
12
- it 'can change the path when template envvar is set' do
13
+ it "can change the path when template envvar is set" do
13
14
  expect(ArchivesSpace::Template.templates_path).to match(
14
- /#{File.join('lib', 'archivesspace', 'client', 'templates')}/
15
+ /#{File.join("lib", "archivesspace", "client", "templates")}/
15
16
  )
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')
17
+ ENV["ARCHIVESSPACE_CLIENT_TEMPLATES_PATH"] = "/path/to/nowhere"
18
+ expect(ArchivesSpace::Template.templates_path).to eq "/path/to/nowhere"
19
+ ENV.delete("ARCHIVESSPACE_CLIENT_TEMPLATES_PATH")
19
20
  end
20
21
 
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]
22
+ it "can process an erb template" do
23
+ data = {repo_code: "ABC", name: "ABC Archive", agent_contact_name: "ABC Admin"}
24
+ json = JSON.parse(ArchivesSpace::Template.process("repository_with_agent.json.erb", data))
25
+ expect(json["repository"]["repo_code"]).to eq data[:repo_code]
26
+ end
27
+
28
+ it "can process a jbuilder template" do
29
+ data = {"title" => "Title", "object_number" => "001.001", "description_level" => "collection"}
30
+ json = JSON.parse(ArchivesSpace::Template.process("resource.json.jbuilder", data))
31
+ expect(json["id_0"]).to eq data["object_number"]
32
+ end
33
+
34
+ it "rejects a template that does not match by extension" do
35
+ data = {"title" => "Title"}
36
+ expect {
37
+ JSON.parse(ArchivesSpace::Template::Erb.new("resource.json.jbuilder", data).process)
38
+ }.to raise_error "Invalid template"
25
39
  end
26
40
  end