orcid 0.8.0 → 0.8.1
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/.coveralls.yml +0 -0
- data/.hound.yml +10 -0
- data/.mailmap +3 -0
- data/.travis.yml +1 -1
- data/Gemfile +1 -0
- data/README.md +39 -2
- data/app/controllers/orcid/profile_connections_controller.rb +4 -0
- data/app/controllers/orcid/profile_requests_controller.rb +5 -1
- data/app/models/orcid/profile.rb +26 -11
- data/app/models/orcid/profile_connection.rb +14 -4
- data/app/models/orcid/profile_request.rb +6 -80
- data/app/models/orcid/profile_status.rb +7 -1
- data/app/models/orcid/work/xml_renderer.rb +6 -4
- data/app/services/orcid/profile_request_coordinator.rb +112 -0
- data/app/services/orcid/remote/profile_creation_service.rb +6 -7
- data/app/services/orcid/remote/profile_query_service.rb +2 -5
- data/app/services/orcid/remote/profile_query_service/response_parser.rb +13 -7
- data/db/migrate/20140205185339_update_orcid_profile_requests.rb +6 -0
- data/lib/orcid.rb +15 -1
- data/lib/orcid/engine.rb +0 -15
- data/lib/orcid/exceptions.rb +24 -2
- data/lib/orcid/version.rb +1 -1
- data/orcid.gemspec +5 -1
- data/spec/controllers/orcid/profile_requests_controller_spec.rb +2 -2
- data/spec/features/non_ui_based_interactions_spec.rb +3 -1
- data/spec/features/orcid_work_query_spec.rb +17 -0
- data/spec/lib/orcid/exceptions_spec.rb +33 -0
- data/spec/lib/orcid_spec.rb +1 -0
- data/spec/models/orcid/profile_connection_spec.rb +8 -6
- data/spec/models/orcid/profile_request_spec.rb +9 -91
- data/spec/models/orcid/work_spec.rb +21 -0
- data/spec/services/orcid/profile_request_coordinator_spec.rb +111 -0
- data/spec/services/orcid/remote/profile_creation_service_spec.rb +17 -0
- data/spec/services/orcid/remote/profile_query_service/query_parameter_builder_spec.rb +11 -16
- data/spec/services/orcid/remote/profile_query_service_spec.rb +21 -9
- data/spec/services/orcid/remote/service_spec.rb +9 -4
- data/spec/spec_helper.rb +4 -0
- metadata +16 -5
- data/rubocop.txt +0 -1164
@@ -12,9 +12,7 @@ module Orcid
|
|
12
12
|
attr_reader :token, :path, :headers
|
13
13
|
def initialize(config = {}, &callback_config)
|
14
14
|
super(&callback_config)
|
15
|
-
@token = config.fetch(:token)
|
16
|
-
Orcid.client_credentials_token('/orcid-profile/create')
|
17
|
-
end
|
15
|
+
@token = config.fetch(:token) { default_token }
|
18
16
|
@path = config.fetch(:path) { 'v1.1/orcid-profile' }
|
19
17
|
@headers = config.fetch(:headers) { default_headers }
|
20
18
|
end
|
@@ -56,10 +54,11 @@ module Orcid
|
|
56
54
|
end
|
57
55
|
|
58
56
|
def default_headers
|
59
|
-
{
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
{ 'Accept' => 'application/xml', 'Content-Type' => 'application/vdn.orcid+xml' }
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_token
|
61
|
+
Orcid.client_credentials_token('/orcid-profile/create')
|
63
62
|
end
|
64
63
|
end
|
65
64
|
end
|
@@ -35,14 +35,11 @@ module Orcid
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def default_headers
|
38
|
-
{
|
39
|
-
:accept => 'application/orcid+json',
|
40
|
-
'Content-Type' => 'application/orcid+xml'
|
41
|
-
}
|
38
|
+
{ :accept => 'application/orcid+json', 'Content-Type' => 'application/orcid+xml' }
|
42
39
|
end
|
43
40
|
|
44
41
|
def issue_callbacks(search_results)
|
45
|
-
if Array(search_results).
|
42
|
+
if Array.wrap(search_results).any?(&:present?)
|
46
43
|
callback(:found, search_results)
|
47
44
|
else
|
48
45
|
callback(:not_found)
|
@@ -2,6 +2,7 @@ require_dependency 'orcid/remote/profile_query_service'
|
|
2
2
|
module Orcid
|
3
3
|
module Remote
|
4
4
|
class ProfileQueryService
|
5
|
+
# Responsible for parsing a response document
|
5
6
|
class ResponseParser
|
6
7
|
|
7
8
|
# A convenience method to expose entry into the ResponseParser function
|
@@ -10,14 +11,10 @@ module Orcid
|
|
10
11
|
end
|
11
12
|
|
12
13
|
attr_reader :response_builder, :logger
|
13
|
-
|
14
|
+
private :response_builder, :logger
|
14
15
|
def initialize(collaborators = {})
|
15
|
-
@response_builder = collaborators.fetch(:response_builder)
|
16
|
-
|
17
|
-
end
|
18
|
-
@logger = collaborators.fetch(:logger) do
|
19
|
-
Rails.logger
|
20
|
-
end
|
16
|
+
@response_builder = collaborators.fetch(:response_builder) { default_response_builder }
|
17
|
+
@logger = collaborators.fetch(:logger) { default_logger }
|
21
18
|
end
|
22
19
|
|
23
20
|
def call(document)
|
@@ -47,6 +44,15 @@ module Orcid
|
|
47
44
|
returning_value
|
48
45
|
end
|
49
46
|
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def default_logger
|
50
|
+
Rails.logger
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_response_builder
|
54
|
+
SearchResponse
|
55
|
+
end
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
data/lib/orcid.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'orcid/engine'
|
1
|
+
require 'orcid/engine' if defined?(Rails)
|
2
2
|
require 'orcid/configuration'
|
3
3
|
require 'orcid/exceptions'
|
4
4
|
require 'figaro'
|
@@ -87,4 +87,18 @@ module Orcid
|
|
87
87
|
tokenizer = options.fetch(:tokenizer) { oauth_client.client_credentials }
|
88
88
|
tokenizer.get_token(scope: scope)
|
89
89
|
end
|
90
|
+
|
91
|
+
# As per an isolated_namespace Rails engine.
|
92
|
+
# But the isolated namespace creates issues.
|
93
|
+
# @api private
|
94
|
+
def table_name_prefix
|
95
|
+
'orcid_'
|
96
|
+
end
|
97
|
+
|
98
|
+
# Because I am not using isolate_namespace for Orcid::Engine
|
99
|
+
# I need this for the application router to find the appropriate routes.
|
100
|
+
# @api private
|
101
|
+
def use_relative_model_naming?
|
102
|
+
true
|
103
|
+
end
|
90
104
|
end
|
data/lib/orcid/engine.rb
CHANGED
@@ -1,20 +1,5 @@
|
|
1
1
|
# The namespace for all things related to Orcid integration
|
2
2
|
module Orcid
|
3
|
-
module_function
|
4
|
-
|
5
|
-
# As per an isolated_namespace Rails engine.
|
6
|
-
# But the isolated namespace creates issues.
|
7
|
-
# @api private
|
8
|
-
def table_name_prefix
|
9
|
-
'orcid_'
|
10
|
-
end
|
11
|
-
|
12
|
-
# Because I am not using isolate_namespace for Orcid::Engine
|
13
|
-
# I need this for the application router to find the appropriate routes.
|
14
|
-
# @api private
|
15
|
-
def use_relative_model_naming?
|
16
|
-
true
|
17
|
-
end
|
18
3
|
|
19
4
|
# While not an isolated namespace engine
|
20
5
|
# @See http://guides.rubyonrails.org/engines.html
|
data/lib/orcid/exceptions.rb
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
module Orcid
|
2
2
|
|
3
|
-
|
3
|
+
# Intended to be the base for all exceptions raised by the Orcid gem.
|
4
|
+
class BaseError < RuntimeError
|
5
|
+
end
|
6
|
+
|
7
|
+
class ProfileRequestStateError < BaseError
|
8
|
+
def initialize(user)
|
9
|
+
super("Unexpected Orcid::ProfileRequest state for #{user.class} ID=#{user.to_param}.")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ProfileRequestMethodExpectedError < BaseError
|
14
|
+
def initialize(request, method_name)
|
15
|
+
super("Expected #{request.inspect} to respond to :#{method_name}.")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class MissingUserForProfileRequest < BaseError
|
20
|
+
def initialize(request)
|
21
|
+
super("#{request.class} ID=#{request.to_param} is not associated with a :user.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ConfigurationError < BaseError
|
4
26
|
def initialize(key_name)
|
5
27
|
super("Unable to find #{key_name.inspect} in configuration storage.")
|
6
28
|
end
|
@@ -8,7 +30,7 @@ module Orcid
|
|
8
30
|
|
9
31
|
# Because in trouble shooting what all goes into this remote call,
|
10
32
|
# you may very well want all of this.
|
11
|
-
class RemoteServiceError <
|
33
|
+
class RemoteServiceError < BaseError
|
12
34
|
def initialize(options)
|
13
35
|
text = []
|
14
36
|
text << "-- Client --"
|
data/lib/orcid/version.rb
CHANGED
data/orcid.gemspec
CHANGED
@@ -13,7 +13,11 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.email = [
|
14
14
|
'jeremy.n.friesen@gmail.com'
|
15
15
|
]
|
16
|
-
s.homepage = 'https://github.com/
|
16
|
+
s.homepage = 'https://github.com/projecthydra-labs/orcid'
|
17
|
+
s.metadata = {
|
18
|
+
'source' => 'https://github.com/projecthydra-labs/orcid',
|
19
|
+
'issue_tracker' => 'https://github.com/projecthydra-labs/orcid/issues'
|
20
|
+
}
|
17
21
|
s.summary = 'A Rails engine for orcid.org integration.'
|
18
22
|
s.description = 'A Rails engine for orcid.org integration.'
|
19
23
|
|
@@ -96,7 +96,7 @@ module Orcid
|
|
96
96
|
|
97
97
|
it 'should render a profile request form' do
|
98
98
|
Orcid::ProfileRequest.should_receive(:find_by_user).with(user).and_return(nil)
|
99
|
-
Orcid.should_receive(:
|
99
|
+
Orcid::ProfileRequestCoordinator.should_receive(:call).with(an_instance_of(Orcid::ProfileRequest))
|
100
100
|
|
101
101
|
expect do
|
102
102
|
post :create, profile_request: profile_request_attributes, use_route: :orcid
|
@@ -106,7 +106,7 @@ module Orcid
|
|
106
106
|
|
107
107
|
it 'should handle invalid data' do
|
108
108
|
Orcid::ProfileRequest.should_receive(:find_by_user).with(user).and_return(nil)
|
109
|
-
Orcid.should_not_receive(:
|
109
|
+
Orcid::ProfileRequestCoordinator.should_not_receive(:call)
|
110
110
|
|
111
111
|
expect do
|
112
112
|
post :create, profile_request: {}, use_route: :orcid
|
@@ -21,6 +21,7 @@ describe 'non-UI based interactions' , requires_net_connect: true do
|
|
21
21
|
let(:profile_request) {
|
22
22
|
FactoryGirl.create(:orcid_profile_request, user: user, primary_email: email, primary_email_confirmation: email)
|
23
23
|
}
|
24
|
+
let(:profile_request_coordinator) { Orcid::ProfileRequestCoordinator.new(profile_request)}
|
24
25
|
|
25
26
|
before(:each) do
|
26
27
|
# Making sure things are properly setup
|
@@ -28,7 +29,8 @@ describe 'non-UI based interactions' , requires_net_connect: true do
|
|
28
29
|
end
|
29
30
|
|
30
31
|
it 'creates a profile' do
|
31
|
-
|
32
|
+
profile_request_coordinator.call
|
33
|
+
profile_request.reload
|
32
34
|
|
33
35
|
orcid_profile_id = profile_request.orcid_profile_id
|
34
36
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'orcid work query', requires_net_connect: true do
|
4
|
+
around(:each) do |example|
|
5
|
+
WebMock.allow_net_connect!
|
6
|
+
example.run
|
7
|
+
WebMock.disable_net_connect!
|
8
|
+
end
|
9
|
+
Given(:token) { Orcid.client_credentials_token('/read-public') }
|
10
|
+
|
11
|
+
# This profile exists on the Sandbox. But for how long? Who knows.
|
12
|
+
Given(:orcid_profile_id) { '0000-0002-1117-8571' }
|
13
|
+
Given(:remote_work_service) { Orcid::Remote::WorkService.new(orcid_profile_id, method: :get, token: token) }
|
14
|
+
Given(:remote_work_document) { remote_work_service.call }
|
15
|
+
When(:works) { Orcid::Work::XmlParser.call(remote_work_document) }
|
16
|
+
Then { expect(works.size).to_not be 0 }
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'fast_helper'
|
2
|
+
require 'orcid/exceptions'
|
3
|
+
|
4
|
+
module Orcid
|
5
|
+
describe BaseError do
|
6
|
+
it { should be_a_kind_of RuntimeError }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ProfileRequestStateError do
|
10
|
+
subject { described_class }
|
11
|
+
its(:superclass) { should be BaseError }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe MissingUserForProfileRequest do
|
15
|
+
subject { described_class }
|
16
|
+
its(:superclass) { should be BaseError }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ConfigurationError do
|
20
|
+
subject { described_class }
|
21
|
+
its(:superclass) { should be BaseError }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe RemoteServiceError do
|
25
|
+
subject { described_class }
|
26
|
+
its(:superclass) { should be BaseError }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ProfileRequestMethodExpectedError do
|
30
|
+
subject { described_class }
|
31
|
+
its(:superclass) { should be BaseError }
|
32
|
+
end
|
33
|
+
end
|
data/spec/lib/orcid_spec.rb
CHANGED
@@ -8,6 +8,7 @@ describe Orcid do
|
|
8
8
|
its(:provider) { should respond_to :secret }
|
9
9
|
its(:mapper) { should respond_to :map }
|
10
10
|
its(:use_relative_model_naming?) { should eq true }
|
11
|
+
its(:table_name_prefix) { should be_an_instance_of String }
|
11
12
|
|
12
13
|
context '.authentication_model' do
|
13
14
|
subject { Orcid.authentication_model }
|
@@ -1,19 +1,23 @@
|
|
1
|
-
require '
|
1
|
+
require 'fast_helper'
|
2
|
+
require 'orcid/profile_connection'
|
2
3
|
|
3
4
|
# :nodoc:
|
4
5
|
module Orcid
|
5
6
|
describe ProfileConnection do
|
6
7
|
let(:email) { 'test@hello.com' }
|
7
8
|
let(:dois) { '123' }
|
8
|
-
let(:user) {
|
9
|
+
let(:user) { double('User') }
|
9
10
|
let(:profile_query_service) { double('Profile Lookup Service') }
|
11
|
+
let(:persister) { double('Persister') }
|
10
12
|
|
11
13
|
subject do
|
12
14
|
Orcid::ProfileConnection.new(email: email, user: user).tap do |pc|
|
15
|
+
pc.persister = persister
|
13
16
|
pc.profile_query_service = profile_query_service
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
20
|
+
its(:default_persister) { should respond_to(:call) }
|
17
21
|
its(:email) { should eq email }
|
18
22
|
its(:to_model) { should eq subject }
|
19
23
|
its(:user) { should eq user }
|
@@ -53,7 +57,6 @@ module Orcid
|
|
53
57
|
|
54
58
|
context '#save' do
|
55
59
|
let(:orcid_profile_id) { '1234-5678' }
|
56
|
-
let(:persister) { double('Persister') }
|
57
60
|
|
58
61
|
it 'should call the persister when valid' do
|
59
62
|
subject.orcid_profile_id = orcid_profile_id
|
@@ -61,15 +64,14 @@ module Orcid
|
|
61
64
|
with(user, orcid_profile_id).
|
62
65
|
and_return(:persisted)
|
63
66
|
|
64
|
-
expect(subject.save
|
67
|
+
expect(subject.save).to eq(:persisted)
|
65
68
|
end
|
66
69
|
|
67
70
|
it 'should NOT call the persister and add errors when not valid' do
|
68
71
|
subject.user = nil
|
69
72
|
subject.orcid_profile_id = nil
|
70
73
|
|
71
|
-
expect { subject.save
|
72
|
-
to change { subject.errors.count }.by(2)
|
74
|
+
expect { subject.save }.to change { subject.errors.count }.by(2)
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
@@ -27,104 +27,22 @@ module Orcid
|
|
27
27
|
|
28
28
|
end
|
29
29
|
|
30
|
-
context '#
|
31
|
-
it 'should update
|
30
|
+
context '#successful_profile_creation' do
|
31
|
+
it 'should update profile request' do
|
32
32
|
# Don't want to hit the database
|
33
33
|
subject.should_receive(:update_column).with(:orcid_profile_id, orcid_profile_id)
|
34
34
|
Orcid.should_receive(:connect_user_and_orcid_profile).with(user, orcid_profile_id)
|
35
35
|
|
36
|
-
subject.
|
36
|
+
subject.successful_profile_creation(orcid_profile_id)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
context '#
|
41
|
-
it 'should
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
context '#validate_before_run' do
|
49
|
-
let(:orcid_profile) { double('Orcid Profile', to_param: orcid_profile_id) }
|
50
|
-
|
51
|
-
context 'when no orcid profile has been assigned' do
|
52
|
-
before { Orcid.should_receive(:profile_for).with(user).and_return(nil) }
|
53
|
-
it 'should return true' do
|
54
|
-
expect(subject.validate_before_run).to eq(true)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'orcid_profile_id is set' do
|
59
|
-
before { subject.orcid_profile_id = orcid_profile_id }
|
60
|
-
|
61
|
-
it 'should return false' do
|
62
|
-
expect(subject.validate_before_run).to eq(false)
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'should set an error' do
|
66
|
-
expect {
|
67
|
-
subject.validate_before_run
|
68
|
-
}.to change { subject.errors.full_messages.count }.by(1)
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'user has an orcid_profile' do
|
74
|
-
before { Orcid.should_receive(:profile_for).with(user).and_return(orcid_profile) }
|
75
|
-
|
76
|
-
it 'should return false' do
|
77
|
-
expect(subject.validate_before_run).to eq(false)
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should set an error' do
|
81
|
-
expect {
|
82
|
-
subject.validate_before_run
|
83
|
-
}.to change { subject.errors.full_messages.count }.by(1)
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context '#run' do
|
90
|
-
let(:profile_creation_service) { double('Profile Creation Service') }
|
91
|
-
let(:payload_xml_builder) { double('Payload Xml Builder') }
|
92
|
-
let(:validator) { double('Submission Guardian') }
|
93
|
-
let(:xml_payload) { double('Xml Payload') }
|
94
|
-
|
95
|
-
context 'with the submission guardian permitting the request' do
|
96
|
-
before(:each) do
|
97
|
-
validator.should_receive(:call).with(subject).
|
98
|
-
and_return(true)
|
99
|
-
payload_xml_builder.should_receive(:call).with(subject.attributes).
|
100
|
-
and_return(xml_payload)
|
101
|
-
profile_creation_service.should_receive(:call).with(xml_payload).
|
102
|
-
and_return(orcid_profile_id)
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should run a request and handle the response' do
|
106
|
-
subject.run(
|
107
|
-
payload_xml_builder: payload_xml_builder,
|
108
|
-
profile_creation_service: profile_creation_service,
|
109
|
-
validator: validator
|
110
|
-
)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
context 'with the submission guardian returning false' do
|
115
|
-
before(:each) do
|
116
|
-
validator.should_receive(:call).with(subject).
|
117
|
-
and_return(false)
|
118
|
-
payload_xml_builder.should_not_receive(:call)
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'should raise an exception' do
|
122
|
-
subject.run(
|
123
|
-
payload_xml_builder: payload_xml_builder,
|
124
|
-
profile_creation_service: profile_creation_service,
|
125
|
-
validator: validator
|
126
|
-
)
|
127
|
-
end
|
40
|
+
context '#validation_error_on_profile_creation' do
|
41
|
+
it 'should update profile request' do
|
42
|
+
error_message = '123'
|
43
|
+
# Don't want to hit the database
|
44
|
+
subject.should_receive(:update_column).with(:response_text, error_message)
|
45
|
+
subject.validation_error_on_profile_creation(error_message)
|
128
46
|
end
|
129
47
|
end
|
130
48
|
end
|