orcid 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|