orcid 0.0.1 → 0.0.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 +4 -4
- data/README.md +14 -3
- data/Rakefile +12 -1
- data/app/models/orcid/profile.rb +2 -2
- data/app/models/orcid/profile_connection.rb +27 -12
- data/app/models/orcid/profile_request.rb +10 -6
- data/app/runners/orcid/profile_lookup_runner.rb +29 -0
- data/app/runners/orcid/runner.rb +15 -0
- data/app/services/orcid/remote.rb +4 -0
- data/app/services/orcid/{profile_creation_service.rb → remote/profile_creation_service.rb} +15 -7
- data/app/services/orcid/{profile_lookup_service.rb → remote/profile_lookup_service.rb} +3 -15
- data/app/services/orcid/remote/profile_lookup_service/search_response.rb +23 -0
- data/app/services/orcid/remote/service.rb +19 -0
- data/app/services/orcid/{remote_work_service.rb → remote/work_service.rb} +4 -3
- data/lib/generators/orcid/install/install_generator.rb +47 -0
- data/lib/generators/orcid/install/templates/orcid_initializer.rb.erb +18 -0
- data/lib/orcid.rb +13 -11
- data/lib/orcid/configuration.rb +10 -7
- data/lib/orcid/configuration/provider.rb +40 -34
- data/lib/orcid/engine.rb +2 -6
- data/lib/orcid/exceptions.rb +3 -0
- data/lib/orcid/named_callbacks.rb +19 -0
- data/lib/orcid/version.rb +1 -1
- data/lib/tasks/orcid_tasks.rake +111 -4
- metadata +41 -6
- data/app/models/orcid/configuration.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6c934af18b7c7e4406bd1b4205e71dc44377838
|
4
|
+
data.tar.gz: c9c4b765a0ba649e91e1c79d6891158622c770ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c614efa5c8b7290fe4faf5ce20ed9f87a622dba3b2d54579c207aee34489985a2169c1d1e888217ded354d685842bb97512ddf621a008e6ddc824be82f9413c2
|
7
|
+
data.tar.gz: e95c8d1d8911a135eb334267b9796b9290a04af92a3ce96f3942af55df208c3ce1f6bf333d642872e39a4962cb8f28148547a664ff3b039d7b3cf7051f4578a0
|
data/README.md
CHANGED
@@ -1,7 +1,18 @@
|
|
1
|
-
# Orcid
|
1
|
+
# Orcid [](http://badge.fury.io/rb/orcid) [](https://travis-ci.org/jeremyf/orcid)
|
2
|
+
|
2
3
|
|
3
4
|
A Rails Engine for integrating with Orcid
|
4
5
|
|
5
|
-
##
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'orcid'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
And then install:
|
6
17
|
|
7
|
-
|
18
|
+
$ rails generate orcid:install
|
data/Rakefile
CHANGED
@@ -6,11 +6,21 @@ end
|
|
6
6
|
|
7
7
|
Bundler::GemHelper.install_tasks
|
8
8
|
|
9
|
-
require 'engine_cart/rake_task'
|
10
9
|
|
10
|
+
begin
|
11
|
+
APP_RAKEFILE = File.expand_path("../spec/internal/Rakefile", __FILE__)
|
12
|
+
load 'rails/tasks/engine.rake'
|
13
|
+
rescue LoadError
|
14
|
+
puts "Unable to load all app tasks for #{APP_RAKEFILE}"
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'engine_cart/rake_task'
|
11
18
|
require 'rspec/core/rake_task'
|
12
19
|
|
13
20
|
namespace :spec do
|
21
|
+
RSpec::Core::RakeTask.new(:all) do |t|
|
22
|
+
ENV['COVERAGE'] = 'true'
|
23
|
+
end
|
14
24
|
desc 'Only run specs that do not require net connect'
|
15
25
|
RSpec::Core::RakeTask.new(:offline) do |t|
|
16
26
|
t.rspec_opts = "--tag ~requires_net_connect"
|
@@ -34,3 +44,4 @@ Rake::Task["default"].clear rescue nil
|
|
34
44
|
Rake::Task["spec"].clear
|
35
45
|
|
36
46
|
task :spec => 'spec:offline'
|
47
|
+
task :default => :spec
|
data/app/models/orcid/profile.rb
CHANGED
@@ -5,8 +5,8 @@ module Orcid
|
|
5
5
|
private :mapper
|
6
6
|
def initialize(orcid_profile_id, config = {})
|
7
7
|
@orcid_profile_id = orcid_profile_id
|
8
|
-
@mapper = config.fetch(:mapper) {
|
9
|
-
@remote_service = config.fetch(:remote_service) { Orcid::
|
8
|
+
@mapper = config.fetch(:mapper) { Orcid.mapper }
|
9
|
+
@remote_service = config.fetch(:remote_service) { Orcid::Remote::WorkService }
|
10
10
|
@xml_renderer = config.fetch(:xml_renderer) { Orcid::Work::XmlRenderer }
|
11
11
|
@xml_parser = config.fetch(:xml_parser) { Orcid::Work::XmlParser }
|
12
12
|
end
|
@@ -12,29 +12,44 @@ module Orcid
|
|
12
12
|
validates :user, presence: true
|
13
13
|
validates :orcid_profile_id, presence: true
|
14
14
|
|
15
|
-
def persisted?; false; end
|
16
15
|
|
17
16
|
def save(config = {})
|
18
17
|
persister = config.fetch(:persister) { Orcid.method(:connect_user_and_orcid_profile) }
|
19
18
|
valid? ? persister.call(user, orcid_profile_id) : false
|
20
19
|
end
|
21
20
|
|
21
|
+
def persisted?; false; end
|
22
|
+
|
23
|
+
attr_writer :profile_lookup_service
|
24
|
+
def profile_lookup_service
|
25
|
+
@profile_lookup_service ||= default_profile_lookup_service
|
26
|
+
end
|
27
|
+
private :profile_lookup_service
|
28
|
+
|
29
|
+
def default_profile_lookup_service
|
30
|
+
ProfileLookupRunner.new {|on|
|
31
|
+
on.found {|results| self.orcid_profile_candidates = results }
|
32
|
+
on.not_found { self.orcid_profile_candidates = [] }
|
33
|
+
}
|
34
|
+
end
|
35
|
+
private :default_profile_lookup_service
|
36
|
+
|
22
37
|
def with_orcid_profile_candidates
|
23
|
-
if
|
24
|
-
yield(orcid_profile_candidates)
|
25
|
-
end
|
38
|
+
yield(orcid_profile_candidates) if email.present?
|
26
39
|
end
|
27
|
-
|
28
|
-
|
40
|
+
|
41
|
+
attr_writer :orcid_profile_candidates
|
42
|
+
private :orcid_profile_candidates=
|
29
43
|
def orcid_profile_candidates
|
30
|
-
@orcid_profile_candidates
|
31
|
-
end
|
32
|
-
def query_for_orcid_profile_candidates?
|
33
|
-
email.present?
|
44
|
+
@orcid_profile_candidates || lookup_profile_candidates
|
34
45
|
end
|
35
46
|
|
36
|
-
def
|
37
|
-
|
47
|
+
def lookup_profile_candidates
|
48
|
+
if email.present?
|
49
|
+
profile_lookup_service.call(email: email)
|
50
|
+
end
|
38
51
|
end
|
52
|
+
private :lookup_profile_candidates
|
53
|
+
|
39
54
|
end
|
40
55
|
end
|
@@ -11,6 +11,7 @@ module Orcid
|
|
11
11
|
|
12
12
|
self.table_name = :orcid_profile_requests
|
13
13
|
|
14
|
+
alias_attribute :email, :primary_email
|
14
15
|
validates :user_id, presence: true, uniqueness: true
|
15
16
|
validates :given_names, presence: true
|
16
17
|
validates :family_name, presence: true
|
@@ -21,15 +22,18 @@ module Orcid
|
|
21
22
|
def run(options = {})
|
22
23
|
# Why dependency injection? Because this is going to be a plugin, and things
|
23
24
|
# can't possibly be simple.
|
24
|
-
|
25
|
-
return false unless
|
25
|
+
validator = options.fetch(:validator) { method(:validate_before_run) }
|
26
|
+
return false unless validator.call(self)
|
26
27
|
|
27
28
|
payload_xml_builder = options.fetch(:payload_xml_builder) { method(:xml_payload) }
|
28
|
-
profile_creation_service = options.fetch(:profile_creation_service) {
|
29
|
-
|
29
|
+
profile_creation_service = options.fetch(:profile_creation_service) { default_profile_creation_service }
|
30
|
+
profile_creation_service.call(payload_xml_builder.call(attributes))
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
+
def default_profile_creation_service
|
34
|
+
@default_profile_creation_service ||= Orcid::Remote::ProfileCreationService.new do |on|
|
35
|
+
on.success {|orcid_profile_id| handle_profile_creation_response(orcid_profile_id) }
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
def validate_before_run(context = self)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_dependency './app/runners/orcid/runner'
|
2
|
+
module Orcid
|
3
|
+
class ProfileLookupRunner < Runner
|
4
|
+
|
5
|
+
def initialize(config = {}, &block)
|
6
|
+
super(&block)
|
7
|
+
@query_service = config.fetch(:query_service) { Remote::ProfileLookupService }
|
8
|
+
end
|
9
|
+
attr_reader :query_service
|
10
|
+
private :query_service
|
11
|
+
|
12
|
+
def call(parameters)
|
13
|
+
email = parameters.fetch(:email)
|
14
|
+
response = query_service.call({q: "email:#{email}"})
|
15
|
+
handle(response)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def handle(response)
|
20
|
+
if response.any?
|
21
|
+
callback(:found, response)
|
22
|
+
else
|
23
|
+
callback(:not_found)
|
24
|
+
end
|
25
|
+
response
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_dependency './lib/orcid/named_callbacks'
|
2
|
+
module Orcid
|
3
|
+
class Runner
|
4
|
+
def initialize
|
5
|
+
@callbacks = NamedCallbacks.new
|
6
|
+
yield(@callbacks) if block_given?
|
7
|
+
end
|
8
|
+
|
9
|
+
def callback(name, *args)
|
10
|
+
@callbacks.call(name, *args)
|
11
|
+
args
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
2
|
-
module Orcid
|
3
|
-
|
1
|
+
require_dependency './app/services/orcid/remote/service'
|
2
|
+
module Orcid::Remote
|
3
|
+
# Responsible for minting a new ORCID for the given payload.
|
4
|
+
class ProfileCreationService < Orcid::Remote::Service
|
4
5
|
|
5
|
-
def self.call(payload, config = {})
|
6
|
-
new(config).call(payload)
|
6
|
+
def self.call(payload, config = {}, &callback_config)
|
7
|
+
new(config, &callback_config).call(payload)
|
7
8
|
end
|
8
9
|
|
9
10
|
attr_reader :token, :path, :headers
|
10
|
-
def initialize(config = {})
|
11
|
+
def initialize(config = {}, &callback_config)
|
12
|
+
super(&callback_config)
|
11
13
|
@token = config.fetch(:token) { Orcid.client_credentials_token('/orcid-profile/create') }
|
12
14
|
@path = config.fetch(:path) { "v1.1/orcid-profile" }
|
13
15
|
@headers = config.fetch(:headers) { default_headers }
|
@@ -25,7 +27,13 @@ module Orcid
|
|
25
27
|
|
26
28
|
def parse(response)
|
27
29
|
uri = URI.parse(response.headers.fetch(:location))
|
28
|
-
uri.path.sub(/\A\//, "").split("/").first
|
30
|
+
if orcid_profile_id = uri.path.sub(/\A\//, "").split("/").first
|
31
|
+
callback(:success, orcid_profile_id)
|
32
|
+
orcid_profile_id
|
33
|
+
else
|
34
|
+
callback(:failure)
|
35
|
+
false
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
39
|
def default_headers
|
@@ -1,18 +1,6 @@
|
|
1
|
-
|
1
|
+
require_dependency 'json'
|
2
|
+
module Orcid::Remote
|
2
3
|
class ProfileLookupService
|
3
|
-
class SearchResponse
|
4
|
-
delegate :fetch, :has_key?, :[], to: :@attributes
|
5
|
-
def initialize(attributes = {})
|
6
|
-
@attributes = attributes.with_indifferent_access
|
7
|
-
end
|
8
|
-
def id
|
9
|
-
@attributes.fetch(:id)
|
10
|
-
end
|
11
|
-
|
12
|
-
def label
|
13
|
-
@attributes.fetch(:label)
|
14
|
-
end
|
15
|
-
end
|
16
4
|
|
17
5
|
def self.call(query, config = {})
|
18
6
|
new(config).call(query)
|
@@ -54,7 +42,7 @@ module Orcid
|
|
54
42
|
family_name = orcid_bio.fetch('personal-details').fetch('family-name').fetch('value')
|
55
43
|
emails = orcid_bio.fetch('contact-details').fetch('email').collect {|email| email.fetch('value') }
|
56
44
|
label = "#{given_names} #{family_name}"
|
57
|
-
label << " (" << emails.join(",") << ")" if emails.
|
45
|
+
label << " (" << emails.join(",") << ")" if emails.any?
|
58
46
|
label << " [ORCID: #{identifier}]"
|
59
47
|
|
60
48
|
returning_value << response_builder.new("id" => identifier, "label" => label)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module Orcid::Remote
|
3
|
+
class ProfileLookupService
|
4
|
+
class SearchResponse
|
5
|
+
delegate :[], :has_key?, :fetch, to: :@records
|
6
|
+
def initialize(attributes = {})
|
7
|
+
@attributes = attributes.with_indifferent_access
|
8
|
+
end
|
9
|
+
|
10
|
+
def id
|
11
|
+
@attributes.fetch(:id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def orcid_profile_id
|
15
|
+
@attributes.fetch(:id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def label
|
19
|
+
@attributes.fetch(:label)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_dependency './lib/orcid/named_callbacks'
|
2
|
+
module Orcid::Remote
|
3
|
+
class Service
|
4
|
+
def initialize
|
5
|
+
@callbacks = Orcid::NamedCallbacks.new
|
6
|
+
yield(@callbacks) if block_given?
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
raise NotImplementedError.new("Define #{self.class}#call")
|
11
|
+
end
|
12
|
+
|
13
|
+
def callback(name, *args)
|
14
|
+
@callbacks.call(name, *args)
|
15
|
+
args
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_dependency './lib/orcid/exceptions'
|
2
|
+
module Orcid::Remote
|
3
|
+
class WorkService
|
3
4
|
def self.call(orcid_profile_id, options = {})
|
4
5
|
new(orcid_profile_id, options).call
|
5
6
|
end
|
@@ -27,7 +28,7 @@ module Orcid
|
|
27
28
|
def deliver
|
28
29
|
token.request(request_method, path, body: body, headers: headers)
|
29
30
|
rescue OAuth2::Error => e
|
30
|
-
raise RemoteServiceError.new(
|
31
|
+
raise Orcid::RemoteServiceError.new(
|
31
32
|
response_body: e.response.body,
|
32
33
|
response_status: e.response.status,
|
33
34
|
client: token.client,
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Orcid
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
class_option :devise, default: false, type: :boolean
|
8
|
+
|
9
|
+
def install_devise_multi_auth
|
10
|
+
if options[:devise]
|
11
|
+
generate 'devise:multi_auth:install --install_devise'
|
12
|
+
else
|
13
|
+
generate 'devise:multi_auth:install'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def install_migrations
|
18
|
+
rake "orcid:install:migrations"
|
19
|
+
end
|
20
|
+
|
21
|
+
def install_omniauth_strategies
|
22
|
+
config_code = ", :omniauthable, :omniauth_providers => [:orcid]"
|
23
|
+
insert_into_file 'app/models/user.rb', config_code, { :after => /:validatable/, :verbose => false }
|
24
|
+
|
25
|
+
init_code = %(
|
26
|
+
config.omniauth(:orcid, Orcid.provider.id, Orcid.provider.secret,
|
27
|
+
scope: Orcid.provider.authentication_scope,
|
28
|
+
client_options: {
|
29
|
+
site: Orcid.provider.site_url,
|
30
|
+
authorize_url: Orcid.provider.authorize_url,
|
31
|
+
token_url: Orcid.provider.token_url
|
32
|
+
}
|
33
|
+
)
|
34
|
+
)
|
35
|
+
insert_into_file 'config/initializers/devise.rb', init_code, {after: /Devise\.setup.*$/, verbose: true}
|
36
|
+
end
|
37
|
+
|
38
|
+
def mount_orcid_engine
|
39
|
+
route 'mount Orcid::Engine => "/orcid"'
|
40
|
+
end
|
41
|
+
|
42
|
+
def install_initializer
|
43
|
+
template 'orcid_initializer.rb.erb', 'config/orcid_initializer.rb'
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Orcid.configure do |config|
|
2
|
+
# # Configure your Orcid Client Application. See URL below for more
|
3
|
+
# # information
|
4
|
+
# # http://support.orcid.org/knowledgebase/articles/116739-register-a-client-application
|
5
|
+
# config.provider.id = "Your app's Orcid Client ID"
|
6
|
+
# config.provider.secret = "Your app's Orcid Client Secret"
|
7
|
+
|
8
|
+
|
9
|
+
# # Configure how your applications models will be mapped to an Orcid Work so
|
10
|
+
# # that your application can append the work to an Orcid Profile.
|
11
|
+
# config.register_mapping_to_orcid_work(
|
12
|
+
# :article,
|
13
|
+
# [
|
14
|
+
# [:title, :title],
|
15
|
+
# [lambda{|article| article.publishers.join("; ")}, :publishers]
|
16
|
+
# ]
|
17
|
+
# )
|
18
|
+
end
|
data/lib/orcid.rb
CHANGED
@@ -12,40 +12,42 @@ require 'simple_form'
|
|
12
12
|
module Orcid
|
13
13
|
|
14
14
|
class << self
|
15
|
-
|
15
|
+
attr_writer :configuration
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
module_function
|
19
23
|
def configure
|
20
|
-
self.configuration ||= Configuration.new
|
21
24
|
yield(configuration)
|
22
25
|
end
|
23
26
|
|
24
|
-
def
|
25
|
-
|
27
|
+
def mapper
|
28
|
+
configuration.mapper
|
26
29
|
end
|
27
30
|
|
28
|
-
def
|
29
|
-
configuration.
|
31
|
+
def provider
|
32
|
+
configuration.provider
|
30
33
|
end
|
31
34
|
|
32
35
|
def authentication_model
|
33
36
|
configuration.authentication_model
|
34
37
|
end
|
35
38
|
|
36
|
-
|
37
39
|
def connect_user_and_orcid_profile(user, orcid_profile_id, options = {})
|
38
|
-
authentication_model.create!(provider:
|
40
|
+
authentication_model.create!(provider: 'orcid', uid: orcid_profile_id, user: user)
|
39
41
|
end
|
40
42
|
|
41
43
|
def access_token_for(orcid_profile_id, options = {})
|
42
44
|
client = options.fetch(:client) { oauth_client }
|
43
45
|
tokenizer = options.fetch(:tokenizer) { authentication_model }
|
44
|
-
tokenizer.to_access_token(uid: orcid_profile_id, provider:
|
46
|
+
tokenizer.to_access_token(uid: orcid_profile_id, provider: 'orcid', client: client)
|
45
47
|
end
|
46
48
|
|
47
49
|
def profile_for(user)
|
48
|
-
if auth = authentication_model.where(provider:
|
50
|
+
if auth = authentication_model.where(provider: 'orcid', user: user).first
|
49
51
|
Orcid::Profile.new(auth.uid)
|
50
52
|
else
|
51
53
|
nil
|
@@ -60,7 +62,7 @@ module Orcid
|
|
60
62
|
# passing the site: option as Orcid's Sandbox has an invalid certificate
|
61
63
|
# for the api.sandbox-1.orcid.org
|
62
64
|
@oauth_client ||= Devise::MultiAuth.oauth_client_for(
|
63
|
-
|
65
|
+
'orcid', options: { site: provider.site_url }
|
64
66
|
)
|
65
67
|
end
|
66
68
|
|
data/lib/orcid/configuration.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
1
|
module Orcid
|
2
2
|
class Configuration
|
3
|
-
attr_reader :
|
4
|
-
def initialize(
|
5
|
-
@
|
3
|
+
attr_reader :mapper
|
4
|
+
def initialize(options = {})
|
5
|
+
@mapper = options.fetch(:mapper) { ::Mappy }
|
6
|
+
@provider = Configuration::Provider.new
|
6
7
|
end
|
7
8
|
|
8
|
-
|
9
|
-
def provider_name
|
10
|
-
@provider_name ||= 'orcid'
|
11
|
-
end
|
9
|
+
attr_reader :provider
|
12
10
|
|
13
11
|
attr_writer :authentication_model
|
14
12
|
def authentication_model
|
15
13
|
@authentication_model ||= Devise::MultiAuth::Authentication
|
16
14
|
end
|
17
15
|
|
16
|
+
def register_mapping_to_orcid_work(source_type, legend)
|
17
|
+
mapper.configure do |config|
|
18
|
+
config.register(source: source_type, target: 'orcid/work', legend: legend)
|
19
|
+
end
|
20
|
+
end
|
18
21
|
end
|
19
22
|
end
|
20
23
|
require 'orcid/configuration/provider'
|
@@ -1,45 +1,51 @@
|
|
1
1
|
module Orcid
|
2
|
-
class Configuration
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
class Configuration
|
3
|
+
class Provider
|
4
|
+
attr_reader :store
|
5
|
+
def initialize(store = ::ENV)
|
6
|
+
@store = store
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
attr_writer :authentication_scope
|
10
|
+
def authentication_scope
|
11
|
+
@authentication_scope ||= store.fetch('ORCID_APP_AUTHENTICATION_SCOPE') {
|
12
|
+
"/authenticate,/orcid-works/create,/orcid-works/update,/read-public"
|
13
|
+
}
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
attr_writer :site_url
|
17
|
+
def site_url
|
18
|
+
@site_url ||= store.fetch('ORCID_SITE_URL') { "http://api.sandbox-1.orcid.org" }
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
attr_writer :token_url
|
22
|
+
def token_url
|
23
|
+
@token_url ||= store.fetch('ORCID_TOKEN_URL') { "https://api.sandbox-1.orcid.org/oauth/token" }
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
attr_writer :signin_via_json_url
|
27
|
+
def signin_via_json_url
|
28
|
+
@signin_via_json_url ||= store.fetch('ORCID_REMOTE_SIGNIN_URL') { "https://sandbox-1.orcid.org/signin/auth.json" }
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
attr_writer :authorize_url
|
32
|
+
def authorize_url
|
33
|
+
@authorize_url ||= store.fetch('ORCID_AUTHORIZE_URL') { "https://sandbox-1.orcid.org/oauth/authorize" }
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
attr_writer :id
|
37
|
+
def id
|
38
|
+
@id ||= store.fetch('ORCID_APP_ID') {
|
39
|
+
Rails.logger.error('Set your Orcid.provider.id')
|
40
|
+
}
|
41
|
+
end
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
attr_writer :secret
|
44
|
+
def secret
|
45
|
+
@secret ||= store.fetch('ORCID_APP_SECRET') {
|
46
|
+
Rails.logger.error('Set your Orcid.provider.secret')
|
47
|
+
}
|
48
|
+
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
data/lib/orcid/engine.rb
CHANGED
@@ -4,16 +4,12 @@ module Orcid
|
|
4
4
|
|
5
5
|
initializer 'orcid.initializers' do |app|
|
6
6
|
app.config.paths.add 'app/services', eager_load: true
|
7
|
+
app.config.paths.add 'app/runners', eager_load: true
|
7
8
|
app.config.autoload_paths += %W(
|
8
9
|
#{config.root}/app/services
|
10
|
+
#{config.root}/app/runners
|
9
11
|
)
|
10
12
|
end
|
11
13
|
|
12
|
-
config.before_initialize do |app|
|
13
|
-
Orcid.configure do |config|
|
14
|
-
config.provider_name = 'orcid'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
14
|
end
|
19
15
|
end
|
data/lib/orcid/exceptions.rb
CHANGED
@@ -9,6 +9,9 @@ module Orcid
|
|
9
9
|
text << "id:\n\t#{client.id.inspect}"
|
10
10
|
text << "site:\n\t#{client.site.inspect}"
|
11
11
|
text << "options:\n\t#{client.options.inspect}"
|
12
|
+
if defined?(Orcid.provider)
|
13
|
+
text << "scopes:\n\t#{Orcid.provider.authentication_scope}"
|
14
|
+
end
|
12
15
|
end
|
13
16
|
text << "\n-- Token --"
|
14
17
|
if token = options[:token]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Orcid
|
2
|
+
# Inspired by Jim Weirich's NamedCallbacks
|
3
|
+
# https://github.com/jimweirich/wyriki/blob/master/spec/runners/named_callbacks_spec.rb#L1-L28
|
4
|
+
class NamedCallbacks
|
5
|
+
def initialize
|
6
|
+
@callbacks = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(callback_name, *args, &block)
|
10
|
+
@callbacks[callback_name] = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(callback_name, *args)
|
14
|
+
name = callback_name.to_sym
|
15
|
+
cb = @callbacks[name]
|
16
|
+
cb ? cb.call(*args) : true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/orcid/version.rb
CHANGED
data/lib/tasks/orcid_tasks.rake
CHANGED
@@ -1,4 +1,111 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
namespace :orcid do
|
2
|
+
namespace :batch do
|
3
|
+
desc 'Given the input: CSV query for existing Orcids and report to output: CSV'
|
4
|
+
task :query => [:environment, :init, :query_runner, :run]
|
5
|
+
|
6
|
+
task :query_runner do
|
7
|
+
@runner = lambda { |person|
|
8
|
+
puts "Processing: #{person.email}"
|
9
|
+
Orcid::ProfileLookupRunner.new {|on|
|
10
|
+
on.found {|results|
|
11
|
+
person.found(results)
|
12
|
+
puts "\tfound" if verbose
|
13
|
+
}
|
14
|
+
on.not_found {
|
15
|
+
person.not_found
|
16
|
+
puts "\tnot found" if verbose
|
17
|
+
}
|
18
|
+
}.call(email: person.email)
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Given the input: CSV query for existing Orcids and if not found create new ones recording output: CSV"
|
23
|
+
task :create => [:environment, :init, :create_runner, :run]
|
24
|
+
|
25
|
+
task :create_runner do
|
26
|
+
@creation_service = lambda {|person|
|
27
|
+
puts "Creating Profile for: #{person.email}"
|
28
|
+
profile_creation_service = Orcid::Remote::ProfileCreationService.new do |on|
|
29
|
+
on.success {|orcid_profile_id|
|
30
|
+
person.orcid_profile_id = orcid_profile_id
|
31
|
+
puts "\tcreated #{orcid_profile_id}" if verbose
|
32
|
+
}
|
33
|
+
end
|
34
|
+
profile_request = Orcid::ProfileRequest.new(person.attributes)
|
35
|
+
profile_request.run(
|
36
|
+
validator: lambda{|*| true},
|
37
|
+
profile_creation_service: profile_creation_service
|
38
|
+
)
|
39
|
+
}
|
40
|
+
@runner = lambda { |person|
|
41
|
+
puts "Processing: #{person.email}"
|
42
|
+
Orcid::ProfileLookupRunner.new {|on|
|
43
|
+
on.found {|results|
|
44
|
+
person.found(results)
|
45
|
+
puts "\tfound" if verbose
|
46
|
+
}
|
47
|
+
on.not_found {
|
48
|
+
person.not_found
|
49
|
+
puts "\tnot found" if verbose
|
50
|
+
@creation_service.call(person)
|
51
|
+
}
|
52
|
+
}.call(email: person.email)
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
task :run do
|
58
|
+
if defined?(WebMock)
|
59
|
+
WebMock.allow_net_connect!
|
60
|
+
end
|
61
|
+
input_file = ENV.fetch('input') { './tmp/orcid_input.csv' }
|
62
|
+
output_file = ENV.fetch('output') { './tmp/orcid_output.csv' }
|
63
|
+
|
64
|
+
require 'csv'
|
65
|
+
CSV.open(output_file, 'wb+') do |output|
|
66
|
+
output << @person_builder.to_header_row
|
67
|
+
CSV.foreach(input_file, headers: true, header_converters: [lambda{|col| col.strip }]) do |input|
|
68
|
+
person = @person_builder.new(input.to_hash)
|
69
|
+
@runner.call(person)
|
70
|
+
output << person.to_output_row
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
task :init do
|
76
|
+
module Orcid::Batch
|
77
|
+
class PersonRecord
|
78
|
+
def self.to_header_row
|
79
|
+
['email', 'given_names', 'family_name', 'existing_orcids', 'created_orcid', 'queried_at']
|
80
|
+
end
|
81
|
+
attr_reader :email, :given_names, :family_name, :existing_orcids
|
82
|
+
attr_accessor :created_orcid
|
83
|
+
def initialize(row)
|
84
|
+
@email = row.fetch('email')
|
85
|
+
@given_names = row['given_names']
|
86
|
+
@family_name = row['family_name']
|
87
|
+
@existing_orcids = nil
|
88
|
+
end
|
89
|
+
|
90
|
+
def attributes
|
91
|
+
{ email: email, given_names: given_names, family_name: family_name }
|
92
|
+
end
|
93
|
+
|
94
|
+
def found(existing_orcids)
|
95
|
+
@existing_orcids = Array(existing_orcids).collect(&:orcid_profile_id).join("; ")
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_output_row
|
99
|
+
[email, given_names, family_name, existing_orcids, created_orcid, Time.now]
|
100
|
+
end
|
101
|
+
|
102
|
+
def not_found
|
103
|
+
@existing_orcids = 'null'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
@person_builder = Orcid::Batch::PersonRecord
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orcid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Friesen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -262,6 +262,20 @@ dependencies:
|
|
262
262
|
- - '>='
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: simplecov
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - '>='
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - '>='
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
265
279
|
- !ruby/object:Gem::Dependency
|
266
280
|
name: rest_client
|
267
281
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,6 +290,20 @@ dependencies:
|
|
276
290
|
- - '>='
|
277
291
|
- !ruby/object:Gem::Version
|
278
292
|
version: '0'
|
293
|
+
- !ruby/object:Gem::Dependency
|
294
|
+
name: rspec-given
|
295
|
+
requirement: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - '>='
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
type: :development
|
301
|
+
prerelease: false
|
302
|
+
version_requirements: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - '>='
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
279
307
|
description: A Rails engine for orcid.org integration.
|
280
308
|
email:
|
281
309
|
- jeremy.n.friesen@gmail.com
|
@@ -289,14 +317,18 @@ files:
|
|
289
317
|
- app/controllers/orcid/profile_connections_controller.rb
|
290
318
|
- app/controllers/orcid/profile_requests_controller.rb
|
291
319
|
- app/helpers/orcid/application_helper.rb
|
292
|
-
- app/models/orcid/configuration.rb
|
293
320
|
- app/models/orcid/profile.rb
|
294
321
|
- app/models/orcid/profile_connection.rb
|
295
322
|
- app/models/orcid/profile_request.rb
|
296
323
|
- app/models/orcid/work.rb
|
297
|
-
- app/
|
298
|
-
- app/
|
299
|
-
- app/services/orcid/
|
324
|
+
- app/runners/orcid/profile_lookup_runner.rb
|
325
|
+
- app/runners/orcid/runner.rb
|
326
|
+
- app/services/orcid/remote/profile_creation_service.rb
|
327
|
+
- app/services/orcid/remote/profile_lookup_service/search_response.rb
|
328
|
+
- app/services/orcid/remote/profile_lookup_service.rb
|
329
|
+
- app/services/orcid/remote/service.rb
|
330
|
+
- app/services/orcid/remote/work_service.rb
|
331
|
+
- app/services/orcid/remote.rb
|
300
332
|
- app/templates/orcid/work.template.v1.1.xml.erb
|
301
333
|
- app/views/layouts/orcid/application.html.erb
|
302
334
|
- app/views/orcid/profile_connections/new.html.erb
|
@@ -305,10 +337,13 @@ files:
|
|
305
337
|
- config/locales/orcid.en.yml
|
306
338
|
- config/routes.rb
|
307
339
|
- db/migrate/20140205185338_create_orcid_profile_requests.rb
|
340
|
+
- lib/generators/orcid/install/install_generator.rb
|
341
|
+
- lib/generators/orcid/install/templates/orcid_initializer.rb.erb
|
308
342
|
- lib/orcid/configuration/provider.rb
|
309
343
|
- lib/orcid/configuration.rb
|
310
344
|
- lib/orcid/engine.rb
|
311
345
|
- lib/orcid/exceptions.rb
|
346
|
+
- lib/orcid/named_callbacks.rb
|
312
347
|
- lib/orcid/spec_support.rb
|
313
348
|
- lib/orcid/version.rb
|
314
349
|
- lib/orcid.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Orcid
|
2
|
-
class Configuration
|
3
|
-
attr_reader :store
|
4
|
-
def initialize(store = ::ENV)
|
5
|
-
@store = store
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_writer :provider_name
|
9
|
-
def provider_name
|
10
|
-
@provider_name ||= 'orcid'
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_writer :authentication_model
|
14
|
-
def authentication_model
|
15
|
-
@authentication_model ||= Devise::MultiAuth::Authentication
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|