handle-system-rest 0.1.1 → 0.1.2

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
2
  SHA256:
3
- metadata.gz: 80560da22c69f15df93fe8e75c12627751d4a67d2737d872677d7e6acca7eb3c
4
- data.tar.gz: fc09852264bb245a026acfa8efe66fed8c6e85d71140064e120bda81a54326b8
3
+ metadata.gz: ed36556bd087f406808b48bfe9b178baf67601df43e0217edd92d82048248d95
4
+ data.tar.gz: 1a7720a452974ac4be21b59ef237f753e0b06b3a5f2c73bba6dff158e8a45c8f
5
5
  SHA512:
6
- metadata.gz: 518f266900d680dcc2b826042187109fc7addd8f73a5395500e854be76619ec04d6e0c987737b322b0f4dd083ecc029cc7ce438141f0ae011d1d39cf1842884f
7
- data.tar.gz: f29c169459e00f9374b8172f82337b9d1f5a6b220a4238ae1d384be2d72b1bf3c6e1d7097502adab74989ce82c84a9e15cc83bf88fa4c443521aa192a909b0ed
6
+ metadata.gz: a4658e4ce5b7cf369ae604ae99eb2ccee86eeba41cc2a88ea8b2fada1ae0b973ebcdf57c3d5100978abc08196c728b330ace29b7a04f1db01dd355e1ba9f1fe9
7
+ data.tar.gz: c4a250a09db5ce4a183b13ca90e8efaadf7db4ceb02647d95d1275c25e5c0b7ef317c6bc69af49bc338453b92f902b673a58ff6590787723b632f380724d8cfe
data/README.md CHANGED
@@ -10,7 +10,7 @@ This library works with Handle System version 8 or higher. For older versions o
10
10
 
11
11
  Before you start using the library, you need to convert your Handle server's private key into PEM format. The Handle Server distribution directory (e.g., `/hs/handle-9.2.0`) has a utility, `hdl-convert-key`, for doing this. Your private key (`admpriv.bin`) is in the server directory (e.g., `/hs/svr_1`).
12
12
 
13
- On the Handle server, Run this command to convert the file:
13
+ On the Handle server, run this command to convert the file:
14
14
 
15
15
  ```
16
16
  /hs/handle-9.2.0/bin/hdl-convert-key /hs/svr_1/admpriv.bin -o /hs/svr_1/admpriv.pem
@@ -9,12 +9,12 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ['dwalker@calstate.edu']
10
10
 
11
11
  spec.summary = 'A library for interfacing with the Handle System JSON REST API.'
12
- spec.description = spec.summary + ' This gem works with Handle System ' +
13
- 'version 8 or higher. For older versions of the ' +
14
- "Handle System, which didn't have a JSON API, " +
15
- 'consider using the handle-system gem'
12
+ spec.description = spec.summary + ' This gem works with Handle System ' +
13
+ 'version 8 or higher. For older versions of the ' +
14
+ "Handle System, which didn't have a JSON API, " +
15
+ 'consider using the handle-system gem.'
16
16
  spec.homepage = 'https://github.com/csuscholarworks/handle-system'
17
- spec.license = 'APACHE'
17
+ spec.license = 'Apache-2.0'
18
18
  spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
19
19
 
20
20
  spec.metadata['homepage_uri'] = spec.homepage
@@ -13,9 +13,10 @@ module HandleSystem
13
13
  # @param [String] server ip_address:port, e.g., 123.456.78.9:8000
14
14
  # @param [String] hs_admin handle administrator
15
15
  # @param [String] priv_key_path file path to private key
16
+ # @param [String] pass_phrase [optional] pass phrase for private key
16
17
  #
17
- def initialize(server, hs_admin, priv_key_path)
18
- @http_client = HttpClient.new(server, hs_admin, priv_key_path)
18
+ def initialize(server, hs_admin, priv_key_path, pass_phrase = nil)
19
+ @http_client = HttpClient.new(server, hs_admin, priv_key_path, pass_phrase)
19
20
  @handle_base = 'http://hdl.handle.net/'
20
21
  end
21
22
 
@@ -24,29 +25,40 @@ module HandleSystem
24
25
  #
25
26
  # @param [String] handle e.g., 20.500.12345/876
26
27
  # @param [String] url the url we want to register
27
- # @param [String] email [optional] email address to add to record
28
- # @param [String] hs_admin [optional] handle administrator to add to record
28
+ # @param [String] email [optional] email address
29
+ # @param [String] hs_admin [optional] handle administrator
29
30
  #
30
31
  # @return [string] the new handle url at hdl.handle.net
31
32
  #
32
33
  def create(handle, url, email = nil, hs_admin = nil)
33
- body = Record.new.from_values(handle, url, email, hs_admin).json
34
- json = @http_client.put_it('/handles/' + handle, body)
35
- @handle_base + json['handle']
34
+ set_record(handle, url, email, hs_admin, false)
36
35
  end
37
36
 
38
- # creating and updating handle records is the same thing
39
- alias update create
37
+ #
38
+ # Update an existing handle
39
+ #
40
+ # Will create a new handle if no record already exists
41
+ #
42
+ # @param [String] handle e.g., 20.500.12345/876
43
+ # @param [String] url the url we want to register
44
+ # @param [String] email [optional] email address
45
+ # @param [String] hs_admin [optional] handle administrator
46
+ #
47
+ # @return [string] the new handle url at hdl.handle.net
48
+ #
49
+ def update(handle, url, email = nil, hs_admin = nil)
50
+ set_record(handle, url, email, hs_admin, true)
51
+ end
40
52
 
41
53
  #
42
54
  # Return the full record for a handle
43
55
  #
44
56
  # @param [String] handle handle identifier
45
57
  #
46
- # @return [<JSON>] the handle record
58
+ # @return [HandleSystem::Record] the handle record
47
59
  #
48
60
  def get(handle)
49
- json = @http_client.get_it('/handles/' + handle)
61
+ json = @http_client.get('/handles/' + handle)
50
62
  Record.new.from_json(json)
51
63
  end
52
64
 
@@ -58,8 +70,29 @@ module HandleSystem
58
70
  # @return [Boolean] true if we deleted the record
59
71
  #
60
72
  def delete(handle)
61
- json = @http_client.delete_it('/handles/' + handle)
73
+ json = @http_client.delete('/handles/' + handle)
62
74
  return true if json['responseCode'] == 1
63
75
  end
76
+
77
+ protected
78
+
79
+ #
80
+ # Create or update a handle
81
+ #
82
+ # @param [String] handle e.g., 20.500.12345/876
83
+ # @param [String] url the url we want to register
84
+ # @param [String] email [optional] email address to add to record
85
+ # @param [String] hs_admin [optional] handle administrator
86
+ # @param [Boolean] overwrite [optional] overwrite any existing record?
87
+ # default: false
88
+ #
89
+ # @return [string] the new handle url at hdl.handle.net
90
+ #
91
+ def set_record(handle, url, email = nil, hs_admin = nil, overwrite = false)
92
+ body = Record.new.from_values(handle, url, email, hs_admin).json
93
+ url = '/handles/' + handle + '?overwrite=' + overwrite.to_s
94
+ json = @http_client.put(url, body)
95
+ @handle_base + json['handle']
96
+ end
64
97
  end
65
98
  end
@@ -11,20 +11,40 @@ module HandleSystem
11
11
  attr_reader :response_code
12
12
 
13
13
  # @return [String] the handle specified in the request
14
- attr_reader :handle
14
+ attr_accessor :handle
15
+
16
+ # @return [String] the URL we sent that produced the error
17
+ attr_accessor :url
15
18
 
16
19
  #
17
20
  # New Handle server Error
18
21
  #
19
- # @param [Integer] code handle protocol response code for the message
20
- # @param [String] handle the handle specified in the request
21
- # @param [String] message error message
22
+ # @param [Integer] response_code handle protocol response code for the message
23
+ # @param [String] message error message
22
24
  #
23
- def initialize(code, handle, message)
24
- @response_code = code.to_int unless code.nil?
25
- @handle = handle
25
+ def initialize(response_code, message)
26
+ @response_code = response_code.to_int unless response_code.nil?
26
27
  super(message)
27
28
  end
29
+
30
+ #
31
+ # Handle server response codes / description
32
+ #
33
+ # @return [Hash] in the form of code => description
34
+ #
35
+ def self.response_codes
36
+ {
37
+ 2 => 'An unexpected error on the server',
38
+ 100 => 'Handle not found',
39
+ 101 => 'Handle already exists',
40
+ 102 => 'Invalid handle',
41
+ 200 => 'Values not found',
42
+ 201 => 'Value already exists',
43
+ 202 => 'Invalid value',
44
+ 301 => 'Server not responsible for handle',
45
+ 402 => 'Authentication needed'
46
+ }
47
+ end
28
48
  end
29
49
 
30
50
  #
@@ -23,10 +23,12 @@ module HandleSystem
23
23
  # @param [String] server ip_address:port, e.g., 123.456.78.9:8000
24
24
  # @param [String] hs_admin handle administrator
25
25
  # @param [String] priv_key_path file path to private key
26
+ # @param [String] pass_phrase [optional] pass phrase for private key
26
27
  #
27
- def initialize(server, hs_admin, priv_key_path)
28
+ def initialize(server, hs_admin, priv_key_path, pass_phrase = nil)
28
29
  @hs_admin = hs_admin
29
30
  @private_key_path = priv_key_path
31
+ @pass_phrase = pass_phrase
30
32
  @base_url = 'https://' + server + '/api'
31
33
  @session_id = initialize_session
32
34
  end
@@ -39,11 +41,10 @@ module HandleSystem
39
41
  # @raise HandleSystem::Error if we got an error from the server
40
42
  # @return [JSON] parsed json response from handle server
41
43
  #
42
- def get_it(path)
44
+ def get(path)
43
45
  url = @base_url + path
44
- json = self.class.get(url, options).parsed_response
45
- check_errors(json)
46
- json
46
+ response = self.class.get(url, options)
47
+ process_response(url, response)
47
48
  end
48
49
 
49
50
  #
@@ -55,11 +56,10 @@ module HandleSystem
55
56
  # @raise HandleSystem::Error if we got an error from the server
56
57
  # @return [JSON] parsed json response from handle server
57
58
  #
58
- def put_it(path, body)
59
+ def put(path, body)
59
60
  url = @base_url + path
60
- json = self.class.put(url, body: body, **options).parsed_response
61
- check_errors(json)
62
- json
61
+ response = self.class.put(url, body: body, **options)
62
+ process_response(url, response)
63
63
  end
64
64
 
65
65
  #
@@ -70,19 +70,47 @@ module HandleSystem
70
70
  # @raise HandleSystem::Error if we got an error from the server
71
71
  # @return [JSON] parsed json response from handle server
72
72
  #
73
- def delete_it(path)
73
+ def delete(path)
74
74
  url = @base_url + path
75
- json = self.class.delete(url, options).parsed_response
76
- check_errors(json)
77
- json
75
+ response = self.class.delete(url, options)
76
+ process_response(url, response)
78
77
  end
79
78
 
80
79
  private
81
80
 
81
+ #
82
+ # Extract JSON from response, throw any errors we found
83
+ #
84
+ # @param [String] url the URL we sent
85
+ # @param [HttParty::Response] response
86
+ #
87
+ # @return [JSON] the json response from the server
88
+ #
89
+ def process_response(url, response)
90
+ json = response.parsed_response
91
+ response_code = json['responseCode']
92
+ return json unless response_code != 1
93
+
94
+ # we got an error response from the handle server, so convert it into
95
+ # an actual exception and throw it here
96
+
97
+ message = if json['message']
98
+ json['message']
99
+ elsif Error.response_codes.include? response_code
100
+ Error.response_codes[response_code]
101
+ else
102
+ 'Unexpected error'
103
+ end
104
+
105
+ error = Error.new(response_code, message)
106
+ error.handle = json['handle']
107
+ error.url = url
108
+ raise error
109
+ end
110
+
82
111
  #
83
112
  # Header and connection options
84
113
  #
85
- # @raise HandleSystem::Error
86
114
  # @return [Hash]
87
115
  #
88
116
  def options
@@ -95,19 +123,6 @@ module HandleSystem
95
123
  }
96
124
  end
97
125
 
98
- #
99
- # If we got an error message from the handle server, convert it into
100
- # an actual exception and throw it here
101
- #
102
- # @param [JSON] json handle server json response
103
- # @raise HandleSystem::Error
104
- #
105
- def check_errors(json)
106
- return unless json['message']
107
-
108
- raise Error.new(json['responseCode'], json['handle'], json['message'])
109
- end
110
-
111
126
  #
112
127
  # Initialize a new session with the handle server using its
113
128
  # challenge-response framework
@@ -152,16 +167,17 @@ module HandleSystem
152
167
  combined_nonce = server_nonce + client_nonce
153
168
 
154
169
  # create combined nonce digest and sign with private key
155
- private_key = OpenSSL::PKey::RSA.new(File.read(@private_key_path))
170
+ key_file = File.read(@private_key_path)
171
+ private_key = OpenSSL::PKey::RSA.new(key_file, @pass_phrase)
156
172
  signature = private_key.sign(OpenSSL::Digest::SHA256.new, combined_nonce)
157
173
 
158
174
  # build the authorization header
159
175
  header = 'Handle sessionId="' + session_id + '", ' \
160
- 'id="' + CGI.escape(@hs_admin) + '", ' \
161
- 'type="HS_PUBKEY", ' \
162
- 'cnonce="' + Base64.encode64(client_nonce) + '", ' \
163
- 'alg="SHA256", ' \
164
- 'signature="' + Base64.encode64(signature) + '"'
176
+ 'id="' + CGI.escape(@hs_admin) + '", ' \
177
+ 'type="HS_PUBKEY", ' \
178
+ 'cnonce="' + Base64.encode64(client_nonce) + '", ' \
179
+ 'alg="SHA256", ' \
180
+ 'signature="' + Base64.encode64(signature) + '"'
165
181
  header.gsub("\n", '')
166
182
  end
167
183
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HandleSystem
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: handle-system-rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Walker
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-18 00:00:00.000000000 Z
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -40,7 +40,7 @@ dependencies:
40
40
  version: '0'
41
41
  description: A library for interfacing with the Handle System JSON REST API. This
42
42
  gem works with Handle System version 8 or higher. For older versions of the Handle
43
- System, which didn't have a JSON API, consider using the handle-system gem
43
+ System, which didn't have a JSON API, consider using the handle-system gem.
44
44
  email:
45
45
  - dwalker@calstate.edu
46
46
  executables: []
@@ -65,7 +65,7 @@ files:
65
65
  - lib/handle_system/version.rb
66
66
  homepage: https://github.com/csuscholarworks/handle-system
67
67
  licenses:
68
- - APACHE
68
+ - Apache-2.0
69
69
  metadata:
70
70
  homepage_uri: https://github.com/csuscholarworks/handle-system
71
71
  source_code_uri: https://github.com/csuscholarworks/handle-system