orcid 0.0.1.pre → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/Rakefile +24 -9
- data/app/controllers/orcid/application_controller.rb +10 -0
- data/app/controllers/orcid/profile_connections_controller.rb +46 -0
- data/app/controllers/orcid/profile_requests_controller.rb +67 -0
- data/app/models/orcid/configuration.rb +19 -0
- data/app/models/orcid/profile.rb +44 -0
- data/app/models/orcid/profile_connection.rb +40 -0
- data/app/models/orcid/profile_request.rb +84 -0
- data/app/models/orcid/work.rb +90 -0
- data/app/services/orcid/profile_creation_service.rb +35 -0
- data/app/services/orcid/profile_lookup_service.rb +65 -0
- data/app/services/orcid/remote_work_service.rb +51 -0
- data/app/templates/orcid/work.template.v1.1.xml.erb +18 -0
- data/app/views/orcid/profile_connections/new.html.erb +17 -0
- data/app/views/orcid/profile_requests/new.html.erb +9 -0
- data/app/views/orcid/profile_requests/show.html.erb +5 -0
- data/config/locales/orcid.en.yml +28 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20140205185338_create_orcid_profile_requests.rb +12 -0
- data/lib/orcid.rb +69 -1
- data/lib/orcid/configuration.rb +20 -0
- data/lib/orcid/configuration/provider.rb +45 -0
- data/lib/orcid/engine.rb +14 -0
- data/lib/orcid/exceptions.rb +28 -0
- data/lib/orcid/spec_support.rb +54 -0
- data/lib/orcid/version.rb +1 -1
- metadata +261 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 148909130b9d10ade4c7e2e6b32d07321dcac06f
|
4
|
+
data.tar.gz: 0fb6c0784ef0a0000bda7e737fe7604519c7afe3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d8b914e980f40cb79f6d19942c56ba5f3a5d27330b05d3ef3cb3b3f2c809b829e5c566803b1b5ac1b5025a52da4163e1ee495c232142e2ee1a63fa69575d34c
|
7
|
+
data.tar.gz: 9bc94eba6a209de41c0fefa4719d511eb9528ff9c2fc02882bb3be065a0e80a1af06cef5d4afc7f2a23b77a731e76ce4460652536dd4eae7c9c2ebde71db0cd6
|
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -4,18 +4,33 @@ rescue LoadError
|
|
4
4
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
5
|
end
|
6
6
|
|
7
|
-
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
8
|
|
9
|
-
|
10
|
-
rdoc.rdoc_dir = 'rdoc'
|
11
|
-
rdoc.title = 'Orcid'
|
12
|
-
rdoc.options << '--line-numbers'
|
13
|
-
rdoc.rdoc_files.include('README.rdoc')
|
14
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
-
end
|
9
|
+
require 'engine_cart/rake_task'
|
16
10
|
|
11
|
+
require 'rspec/core/rake_task'
|
17
12
|
|
13
|
+
namespace :spec do
|
14
|
+
desc 'Only run specs that do not require net connect'
|
15
|
+
RSpec::Core::RakeTask.new(:offline) do |t|
|
16
|
+
t.rspec_opts = "--tag ~requires_net_connect"
|
17
|
+
end
|
18
18
|
|
19
|
+
desc 'Only run specs that require net connect'
|
20
|
+
RSpec::Core::RakeTask.new(:online) do |t|
|
21
|
+
t.rspec_opts = "--tag requires_net_connect"
|
22
|
+
end
|
19
23
|
|
20
|
-
|
24
|
+
desc 'Run the Travis CI specs'
|
25
|
+
task :travis do
|
26
|
+
ENV['RAILS_ENV'] = 'test'
|
27
|
+
ENV['SPEC_OPTS'] = "--profile 20"
|
28
|
+
Rake::Task['engine_cart:clean'].invoke
|
29
|
+
Rake::Task['engine_cart:generate'].invoke
|
30
|
+
Rake::Task['spec:offline'].invoke
|
31
|
+
end
|
32
|
+
end
|
33
|
+
Rake::Task["default"].clear rescue nil
|
34
|
+
Rake::Task["spec"].clear
|
21
35
|
|
36
|
+
task :spec => 'spec:offline'
|
@@ -1,4 +1,14 @@
|
|
1
1
|
module Orcid
|
2
2
|
class ApplicationController < ActionController::Base
|
3
|
+
private
|
4
|
+
def redirecting_because_user_already_has_a_connected_orcid_profile
|
5
|
+
if orcid_profile = Orcid.profile_for(current_user)
|
6
|
+
flash[:notice] = I18n.t("orcid.requests.messages.previously_connected_profile", orcid_profile_id: orcid_profile.orcid_profile_id)
|
7
|
+
redirect_to main_app.root_path
|
8
|
+
return true
|
9
|
+
else
|
10
|
+
return false
|
11
|
+
end
|
12
|
+
end
|
3
13
|
end
|
4
14
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Orcid
|
2
|
+
class ProfileConnectionsController < Orcid::ApplicationController
|
3
|
+
respond_to :html
|
4
|
+
before_filter :authenticate_user!
|
5
|
+
|
6
|
+
def index
|
7
|
+
render text: 'Not yet implemented!'
|
8
|
+
end
|
9
|
+
|
10
|
+
def new
|
11
|
+
return false if redirecting_because_user_already_has_a_connected_orcid_profile
|
12
|
+
assign_attributes(new_profile_connection)
|
13
|
+
respond_with(new_profile_connection)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
return false if redirecting_because_user_already_has_a_connected_orcid_profile
|
18
|
+
assign_attributes(new_profile_connection)
|
19
|
+
create_profile_connection(new_profile_connection)
|
20
|
+
respond_with(new_profile_connection)
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
attr_reader :profile_connection
|
26
|
+
helper_method :profile_connection
|
27
|
+
|
28
|
+
def assign_attributes(profile_connection)
|
29
|
+
profile_connection.attributes = profile_connection_params
|
30
|
+
profile_connection.user = current_user
|
31
|
+
end
|
32
|
+
|
33
|
+
def profile_connection_params
|
34
|
+
params[:profile_connection] || {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_profile_connection(profile_connection)
|
38
|
+
profile_connection.save
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_profile_connection
|
42
|
+
@profile_connection ||= Orcid::ProfileConnection.new(params[:profile_connection])
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Orcid
|
2
|
+
class ProfileRequestsController < Orcid::ApplicationController
|
3
|
+
respond_to :html
|
4
|
+
before_filter :authenticate_user!
|
5
|
+
|
6
|
+
attr_reader :profile_request
|
7
|
+
helper_method :profile_request
|
8
|
+
|
9
|
+
def show
|
10
|
+
return false if redirecting_because_user_already_has_a_connected_orcid_profile
|
11
|
+
return false if redirecting_because_no_profile_request_was_found
|
12
|
+
respond_with(existing_profile_request)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new
|
16
|
+
return false if redirecting_because_user_already_has_a_connected_orcid_profile
|
17
|
+
return false if redirecting_because_user_has_existing_profile_request
|
18
|
+
assign_attributes(new_profile_request)
|
19
|
+
respond_with(new_profile_request)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
return false if redirecting_because_user_already_has_a_connected_orcid_profile
|
24
|
+
return false if redirecting_because_user_has_existing_profile_request
|
25
|
+
assign_attributes(new_profile_request)
|
26
|
+
create_profile_request(new_profile_request)
|
27
|
+
respond_with(new_profile_request)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def redirecting_because_no_profile_request_was_found
|
33
|
+
return false if existing_profile_request
|
34
|
+
flash[:notice] = I18n.t("orcid.requests.messages.existing_request_not_found")
|
35
|
+
redirect_to new_profile_request_path
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def redirecting_because_user_has_existing_profile_request
|
40
|
+
return false if ! existing_profile_request
|
41
|
+
flash[:notice] = I18n.t("orcid.requests.messages.existing_request")
|
42
|
+
redirect_to profile_request_path
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def existing_profile_request
|
47
|
+
@profile_request ||= Orcid::ProfileRequest.find_by_user(current_user)
|
48
|
+
end
|
49
|
+
|
50
|
+
def new_profile_request
|
51
|
+
@profile_request ||= Orcid::ProfileRequest.new(user: current_user)
|
52
|
+
end
|
53
|
+
|
54
|
+
def assign_attributes(profile_request)
|
55
|
+
profile_request.attributes = profile_request_params
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_profile_request(profile_request)
|
59
|
+
profile_request.save && Orcid.enqueue(profile_request)
|
60
|
+
end
|
61
|
+
|
62
|
+
def profile_request_params
|
63
|
+
return {} unless params.has_key?(:profile_request)
|
64
|
+
params[:profile_request].permit(:given_names, :family_name, :primary_email, :primary_email_confirmation)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,19 @@
|
|
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
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Orcid
|
2
|
+
class Profile
|
3
|
+
|
4
|
+
attr_reader :orcid_profile_id, :mapper, :remote_service, :xml_renderer, :xml_parser
|
5
|
+
private :mapper
|
6
|
+
def initialize(orcid_profile_id, config = {})
|
7
|
+
@orcid_profile_id = orcid_profile_id
|
8
|
+
@mapper = config.fetch(:mapper) { ::Mappy }
|
9
|
+
@remote_service = config.fetch(:remote_service) { Orcid::RemoteWorkService }
|
10
|
+
@xml_renderer = config.fetch(:xml_renderer) { Orcid::Work::XmlRenderer }
|
11
|
+
@xml_parser = config.fetch(:xml_parser) { Orcid::Work::XmlParser }
|
12
|
+
end
|
13
|
+
|
14
|
+
def remote_works(options = {})
|
15
|
+
@remote_works = nil if options.fetch(:force, false)
|
16
|
+
@remote_works ||= begin
|
17
|
+
response = remote_service.call(orcid_profile_id, request_method: :get)
|
18
|
+
xml_parser.call(response)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def append_new_work(*works)
|
23
|
+
orcid_works = normalize_work(*works)
|
24
|
+
xml = xml_renderer.call(orcid_works)
|
25
|
+
remote_service.call(orcid_profile_id, request_method: :post, body: xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def replace_works_with(*works)
|
29
|
+
orcid_works = normalize_work(*works)
|
30
|
+
xml = xml_renderer.call(orcid_works)
|
31
|
+
remote_service.call(orcid_profile_id, request_method: :put, body: xml)
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
# Note: We can handle
|
37
|
+
def normalize_work(*works)
|
38
|
+
Array(works).flatten.compact.collect do |work|
|
39
|
+
mapper.map(work, target: 'orcid/work')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Orcid
|
2
|
+
# Responsible for connecting an authenticated user to the ORCID profile that
|
3
|
+
# the user searched for and selected.
|
4
|
+
class ProfileConnection
|
5
|
+
include Virtus.model
|
6
|
+
include ActiveModel::Validations
|
7
|
+
extend ActiveModel::Naming
|
8
|
+
attribute :email
|
9
|
+
attribute :orcid_profile_id
|
10
|
+
attribute :user
|
11
|
+
|
12
|
+
validates :user, presence: true
|
13
|
+
validates :orcid_profile_id, presence: true
|
14
|
+
|
15
|
+
def persisted?; false; end
|
16
|
+
|
17
|
+
def save(config = {})
|
18
|
+
persister = config.fetch(:persister) { Orcid.method(:connect_user_and_orcid_profile) }
|
19
|
+
valid? ? persister.call(user, orcid_profile_id) : false
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_orcid_profile_candidates
|
23
|
+
if query_for_orcid_profile_candidates?
|
24
|
+
yield(orcid_profile_candidates)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
attr_writer :orcid_profile_querier
|
28
|
+
protected
|
29
|
+
def orcid_profile_candidates
|
30
|
+
@orcid_profile_candidates ||= orcid_profile_querier.call({q: "email:#{email}"})
|
31
|
+
end
|
32
|
+
def query_for_orcid_profile_candidates?
|
33
|
+
email.present?
|
34
|
+
end
|
35
|
+
|
36
|
+
def orcid_profile_querier
|
37
|
+
@orcid_profile_querier ||= ProfileLookupService
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Orcid
|
2
|
+
# Responsible for:
|
3
|
+
# * acknowledging that an ORCID Profile was requested
|
4
|
+
# * submitting a request for an ORCID Profile
|
5
|
+
# * handling the response for the ORCID Profile creation
|
6
|
+
class ProfileRequest < ActiveRecord::Base
|
7
|
+
|
8
|
+
def self.find_by_user(user)
|
9
|
+
where(user: user).first
|
10
|
+
end
|
11
|
+
|
12
|
+
self.table_name = :orcid_profile_requests
|
13
|
+
|
14
|
+
validates :user_id, presence: true, uniqueness: true
|
15
|
+
validates :given_names, presence: true
|
16
|
+
validates :family_name, presence: true
|
17
|
+
validates :primary_email, presence: true, email: true, confirmation: true
|
18
|
+
|
19
|
+
belongs_to :user
|
20
|
+
|
21
|
+
def run(options = {})
|
22
|
+
# Why dependency injection? Because this is going to be a plugin, and things
|
23
|
+
# can't possibly be simple.
|
24
|
+
before_run_validator = options.fetch(:before_run_validator) { method(:validate_before_run) }
|
25
|
+
return false unless before_run_validator.call(self)
|
26
|
+
|
27
|
+
payload_xml_builder = options.fetch(:payload_xml_builder) { method(:xml_payload) }
|
28
|
+
profile_creation_service = options.fetch(:profile_creation_service) { Orcid::ProfileCreationService }
|
29
|
+
profile_creation_responder = options.fetch(:profile_creation_responder) { method(:handle_profile_creation_response) }
|
30
|
+
|
31
|
+
orcid_profile_id = profile_creation_service.call(payload_xml_builder.call(attributes))
|
32
|
+
profile_creation_responder.call(orcid_profile_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_before_run(context = self)
|
36
|
+
|
37
|
+
if context.orcid_profile_id?
|
38
|
+
context.errors.add(:base, "#{context.class} ID=#{context.to_param} already has an assigned :orcid_profile_id #{context.orcid_profile_id.inspect}")
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
|
42
|
+
if user_orcid_profile = Orcid.profile_for(context.user)
|
43
|
+
context.errors.add(:base, "#{context.class} ID=#{context.to_param}'s associated user #{context.user.to_param} already has an assigned :orcid_profile_id #{user_orcid_profile.to_param}")
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
# NOTE: This one lies -> http://support.orcid.org/knowledgebase/articles/177522-create-an-id-technical-developer
|
51
|
+
# NOTE: This one was true at 2014-02-06:14:55 -> http://support.orcid.org/knowledgebase/articles/162412-tutorial-create-a-new-record-using-curl
|
52
|
+
def xml_payload(input = attributes)
|
53
|
+
attrs = input.with_indifferent_access
|
54
|
+
returning_value = <<-XML_TEMPLATE
|
55
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
56
|
+
<orcid-message
|
57
|
+
xmlns:xsi="http://www.orcid.org/ns/orcid https://raw.github.com/ORCID/ORCID-Source/master/orcid-model/src/main/resources/orcid-message-1.1.xsd"
|
58
|
+
xmlns="http://www.orcid.org/ns/orcid">
|
59
|
+
<message-version>1.1</message-version>
|
60
|
+
<orcid-profile>
|
61
|
+
<orcid-bio>
|
62
|
+
<personal-details>
|
63
|
+
<given-names>#{attrs.fetch('given_names')}</given-names>
|
64
|
+
<family-name>#{attrs.fetch('family_name')}</family-name>
|
65
|
+
</personal-details>
|
66
|
+
<contact-details>
|
67
|
+
<email primary="true">#{attrs.fetch('primary_email')}</email>
|
68
|
+
</contact-details>
|
69
|
+
</orcid-bio>
|
70
|
+
</orcid-profile>
|
71
|
+
</orcid-message>
|
72
|
+
XML_TEMPLATE
|
73
|
+
returning_value.strip
|
74
|
+
end
|
75
|
+
|
76
|
+
def handle_profile_creation_response(orcid_profile_id)
|
77
|
+
self.class.transaction do
|
78
|
+
update_column(:orcid_profile_id, orcid_profile_id)
|
79
|
+
Orcid.connect_user_and_orcid_profile(user, orcid_profile_id)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Orcid
|
2
|
+
# A well-defined data structure that coordinates with its :template in order
|
3
|
+
# to generate XML that can be POSTed/PUT as an Orcid Work.
|
4
|
+
class Work
|
5
|
+
VALID_WORK_TYPES = [
|
6
|
+
"artistic-performance","book-chapter","book-review","book","conference-abstract","conference-paper","conference-poster","data-set","dictionary-entry","disclosure","dissertation","edited-book","encyclopedia-entry","invention","journal-article","journal-issue","lecture-speech","license","magazine-article","manual","newsletter-article","newspaper-article","online-resource","other","patent","registered-copyright","report","research-technique","research-tool","spin-off-company","standards-and-policy","supervised-student-publication","technical-standard","test","translation","trademark","website","working-paper",
|
7
|
+
].freeze
|
8
|
+
|
9
|
+
include Virtus.model
|
10
|
+
include ActiveModel::Validations
|
11
|
+
extend ActiveModel::Naming
|
12
|
+
|
13
|
+
attribute :title, String
|
14
|
+
validates :title, presence: true
|
15
|
+
|
16
|
+
attribute :work_type, String
|
17
|
+
validates :work_type, presence: true, inclusion: { in: VALID_WORK_TYPES }
|
18
|
+
|
19
|
+
attribute :put_code, String
|
20
|
+
|
21
|
+
def to_xml
|
22
|
+
XmlRenderer.call(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
def ==(comparison_object)
|
26
|
+
super || comparison_object.instance_of?(self.class) &&
|
27
|
+
id.present? &&
|
28
|
+
comparison_object.id == id
|
29
|
+
end
|
30
|
+
|
31
|
+
def id
|
32
|
+
if put_code.present?
|
33
|
+
put_code
|
34
|
+
elsif title.present? && work_type.present?
|
35
|
+
[title, work_type]
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class XmlRenderer
|
42
|
+
def self.call(works, options = {})
|
43
|
+
new(works, options).call
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :works, :template
|
47
|
+
def initialize(works, options = {})
|
48
|
+
self.works = works
|
49
|
+
@template = options.fetch(:template_path) { Orcid::Engine.root.join('app/templates/orcid/work.template.v1.1.xml.erb').read }
|
50
|
+
end
|
51
|
+
|
52
|
+
def call
|
53
|
+
ERB.new(template).result(binding)
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def works=(thing)
|
58
|
+
@works = Array(thing)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class XmlParser
|
64
|
+
def self.call(xml)
|
65
|
+
new(xml).call
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_reader :xml
|
69
|
+
def initialize(xml)
|
70
|
+
@xml = xml
|
71
|
+
end
|
72
|
+
|
73
|
+
def call
|
74
|
+
document = Nokogiri::XML.parse(xml)
|
75
|
+
document.css('orcid-works orcid-work').collect do |node|
|
76
|
+
transform(node)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
def transform(node)
|
82
|
+
Orcid::Work.new.tap do |work|
|
83
|
+
work.put_code = node.attributes.fetch("put-code").value
|
84
|
+
work.title = node.css('work-title title').text
|
85
|
+
work.work_type = node.css('work-type').text
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Responsible for minting a new ORCID for the given payload.
|
2
|
+
module Orcid
|
3
|
+
class ProfileCreationService
|
4
|
+
|
5
|
+
def self.call(payload, config = {})
|
6
|
+
new(config).call(payload)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :token, :path, :headers
|
10
|
+
def initialize(config = {})
|
11
|
+
@token = config.fetch(:token) { Orcid.client_credentials_token('/orcid-profile/create') }
|
12
|
+
@path = config.fetch(:path) { "v1.1/orcid-profile" }
|
13
|
+
@headers = config.fetch(:headers) { default_headers }
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(payload)
|
17
|
+
response = deliver(payload)
|
18
|
+
parse(response)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def deliver(body)
|
23
|
+
token.post(path, body: body, headers: headers)
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(response)
|
27
|
+
uri = URI.parse(response.headers.fetch(:location))
|
28
|
+
uri.path.sub(/\A\//, "").split("/").first
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_headers
|
32
|
+
{ "Accept" => 'application/xml', 'Content-Type'=>'application/vdn.orcid+xml' }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Orcid
|
2
|
+
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
|
+
|
17
|
+
def self.call(query, config = {})
|
18
|
+
new(config).call(query)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :token, :path, :headers, :response_builder
|
22
|
+
def initialize(config = {})
|
23
|
+
@token = config.fetch(:token) { Orcid.client_credentials_token('/read-public') }
|
24
|
+
@response_builder = config.fetch(:response_builder) { SearchResponse }
|
25
|
+
@path = config.fetch(:path) { "v1.1/search/orcid-bio/" }
|
26
|
+
@headers = config.fetch(:headers) {
|
27
|
+
{
|
28
|
+
:accept => 'application/orcid+json',
|
29
|
+
'Content-Type'=>'application/orcid+xml'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(parameters)
|
35
|
+
response = deliver(parameters)
|
36
|
+
parse(response.body)
|
37
|
+
end
|
38
|
+
alias_method :search, :call
|
39
|
+
|
40
|
+
protected
|
41
|
+
attr_reader :host, :access_token
|
42
|
+
def deliver(parameters)
|
43
|
+
token.get(path, headers: headers, params: parameters)
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse(document)
|
47
|
+
json = JSON.parse(document)
|
48
|
+
|
49
|
+
json.fetch('orcid-search-results').fetch('orcid-search-result').each_with_object([]) do |result, returning_value|
|
50
|
+
profile = result.fetch('orcid-profile')
|
51
|
+
identifier = profile.fetch('orcid-identifier').fetch('path')
|
52
|
+
orcid_bio = profile.fetch('orcid-bio')
|
53
|
+
given_names = orcid_bio.fetch('personal-details').fetch('given-names').fetch('value')
|
54
|
+
family_name = orcid_bio.fetch('personal-details').fetch('family-name').fetch('value')
|
55
|
+
emails = orcid_bio.fetch('contact-details').fetch('email').collect {|email| email.fetch('value') }
|
56
|
+
label = "#{given_names} #{family_name}"
|
57
|
+
label << " (" << emails.join(",") << ")" if emails.present?
|
58
|
+
label << " [ORCID: #{identifier}]"
|
59
|
+
|
60
|
+
returning_value << response_builder.new("id" => identifier, "label" => label)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Orcid
|
2
|
+
class RemoteWorkService
|
3
|
+
def self.call(orcid_profile_id, options = {})
|
4
|
+
new(orcid_profile_id, options).call
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :headers, :token, :orcid_profile_id, :body, :request_method, :path
|
8
|
+
def initialize(orcid_profile_id, options = {})
|
9
|
+
@orcid_profile_id = orcid_profile_id
|
10
|
+
@request_method = options.fetch(:request_method) { :get }
|
11
|
+
@body = options.fetch(:body) { "" }
|
12
|
+
@token = options.fetch(:token) { Orcid.access_token_for(orcid_profile_id) }
|
13
|
+
@headers = options.fetch(:headers) { default_headers }
|
14
|
+
@path = options.fetch(:path) { default_path }
|
15
|
+
end
|
16
|
+
|
17
|
+
# :post will append works to the Orcid Profile
|
18
|
+
# :put will replace the existing Orcid Profile works with the payload
|
19
|
+
# :get will retrieve the Orcid Profile
|
20
|
+
# http://support.orcid.org/knowledgebase/articles/177528-add-works-technical-developer
|
21
|
+
def call
|
22
|
+
response = deliver
|
23
|
+
response.body
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def deliver
|
28
|
+
token.request(request_method, path, body: body, headers: headers)
|
29
|
+
rescue OAuth2::Error => e
|
30
|
+
raise RemoteServiceError.new(
|
31
|
+
response_body: e.response.body,
|
32
|
+
response_status: e.response.status,
|
33
|
+
client: token.client,
|
34
|
+
token: token,
|
35
|
+
request_method: request_method,
|
36
|
+
request_path: path,
|
37
|
+
request_body: body,
|
38
|
+
request_headers: headers
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_headers
|
43
|
+
{ 'Accept' => 'application/xml', 'Content-Type'=>'application/orcid+xml' }
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_path
|
47
|
+
"v1.1/#{orcid_profile_id}/orcid-works/"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<orcid-message xmlns="http://www.orcid.org/ns/orcid"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xsi:schemaLocation="https://raw.github.com/ORCID/ORCID-Source/master/orcid-model/src/main/resources/orcid-message-1.1.xsd">
|
5
|
+
<message-version>1.1</message-version>
|
6
|
+
<orcid-profile>
|
7
|
+
<orcid-activities>
|
8
|
+
<orcid-works><% works.each do |work| %>
|
9
|
+
<orcid-work>
|
10
|
+
<work-title>
|
11
|
+
<title><%= work.title %></title>
|
12
|
+
</work-title>
|
13
|
+
<work-type><%= work.work_type %></work-type>
|
14
|
+
</orcid-work>
|
15
|
+
<% end %></orcid-works>
|
16
|
+
</orcid-activities>
|
17
|
+
</orcid-profile>
|
18
|
+
</orcid-message>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= simple_form_for(profile_connection, as: :profile_connection, url: orcid.new_profile_connection_path, method: :get, html: {class: 'search-form'}) do |f| %>
|
2
|
+
<%= field_set_tag("Search ORCID Profiles", class: 'accessible-hidden') do %>
|
3
|
+
<%= f.input :email, type: :search %>
|
4
|
+
<% end %>
|
5
|
+
<button type="submit" class="search-submit btn btn-primary" id="keyword-search-submit" tabindex="2">
|
6
|
+
<i class="icon-search icon-white"></i><span class="accessible-hidden">Search</span>
|
7
|
+
</button>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% profile_connection.with_orcid_profile_candidates do |candidates| %>
|
11
|
+
<%= simple_form_for(profile_connection, as: :profile_connection, url: orcid.profile_connections_path,) do |f| %>
|
12
|
+
<%= field_set_tag("Select an ORCID Profile", class: 'accessible-hidden') do %>
|
13
|
+
<%= f.collection_radio_buttons :orcid_profile_id, candidates, :id, :label %>
|
14
|
+
<% end %>
|
15
|
+
<%= f.submit %>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<%= simple_form_for profile_request, as: :profile_request, url: orcid.profile_request_path do |f| %>
|
2
|
+
<%= field_set_tag do%>
|
3
|
+
<%= f.input :given_names %>
|
4
|
+
<%= f.input :family_name %>
|
5
|
+
<%= f.input :primary_email %>
|
6
|
+
<%= f.input :primary_email_confirmation %>
|
7
|
+
<% end %>
|
8
|
+
<%= f.submit %>
|
9
|
+
<% end %>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
<p><strong>Requestor:</strong> <%= profile_request.user %></p>
|
2
|
+
<p><strong>Given names:</strong> <%= profile_request.given_names %></p>
|
3
|
+
<p><strong>Family name:</strong> <%= profile_request.family_name %></p>
|
4
|
+
<p><strong>Primary email:</strong> <%= profile_request.primary_email %></p>
|
5
|
+
<p><strong>ORCID Profile ID:</strong> <%= profile_request.orcid_profile_id %></p>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
3
|
+
# than English, add the necessary files in this directory.
|
4
|
+
#
|
5
|
+
# To use the locales, use `I18n.t`:
|
6
|
+
#
|
7
|
+
# I18n.t 'hello'
|
8
|
+
#
|
9
|
+
# In views, this is aliased to just `t`:
|
10
|
+
#
|
11
|
+
# <%= t('hello') %>
|
12
|
+
#
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
14
|
+
#
|
15
|
+
# I18n.locale = :es
|
16
|
+
#
|
17
|
+
# This would use the information in config/locales/es.yml.
|
18
|
+
#
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
21
|
+
|
22
|
+
en:
|
23
|
+
orcid:
|
24
|
+
requests:
|
25
|
+
messages:
|
26
|
+
existing_request_not_found: "Unable to find an existing Orcid Profile request. Go ahead and create one."
|
27
|
+
existing_request: "You have already submitted an Orcid Profile request."
|
28
|
+
previously_connected_profile: "You have already connected to an Orcid Profile (%{orcid_profile_id})."
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateOrcidProfileRequests < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :orcid_profile_requests do |t|
|
4
|
+
t.integer :user_id, unique: true, index: true, null: false
|
5
|
+
t.string :given_names, null: false
|
6
|
+
t.string :family_name, null: false
|
7
|
+
t.string :primary_email, null: false
|
8
|
+
t.string :orcid_profile_id, unique: true, index: true
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/orcid.rb
CHANGED
@@ -1,4 +1,72 @@
|
|
1
|
-
require
|
1
|
+
require 'orcid/engine'
|
2
|
+
require 'orcid/configuration'
|
3
|
+
require 'orcid/exceptions'
|
4
|
+
|
5
|
+
require 'mappy'
|
6
|
+
require 'devise_multi_auth'
|
7
|
+
require 'virtus'
|
8
|
+
require 'omniauth-orcid'
|
9
|
+
require 'email_validator'
|
10
|
+
require 'simple_form'
|
2
11
|
|
3
12
|
module Orcid
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_accessor :configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
module_function
|
19
|
+
def configure
|
20
|
+
self.configuration ||= Configuration.new
|
21
|
+
yield(configuration)
|
22
|
+
end
|
23
|
+
|
24
|
+
def provider
|
25
|
+
@provider ||= Configuration::Provider.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def provider_name
|
29
|
+
configuration.provider_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def authentication_model
|
33
|
+
configuration.authentication_model
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def connect_user_and_orcid_profile(user, orcid_profile_id, options = {})
|
38
|
+
authentication_model.create!(provider: provider_name, uid: orcid_profile_id, user: user)
|
39
|
+
end
|
40
|
+
|
41
|
+
def access_token_for(orcid_profile_id, options = {})
|
42
|
+
client = options.fetch(:client) { oauth_client }
|
43
|
+
tokenizer = options.fetch(:tokenizer) { authentication_model }
|
44
|
+
tokenizer.to_access_token(uid: orcid_profile_id, provider: provider_name, client: client)
|
45
|
+
end
|
46
|
+
|
47
|
+
def profile_for(user)
|
48
|
+
if auth = authentication_model.where(provider: provider_name, user: user).first
|
49
|
+
Orcid::Profile.new(auth.uid)
|
50
|
+
else
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def enqueue(object)
|
56
|
+
object.run
|
57
|
+
end
|
58
|
+
|
59
|
+
def oauth_client
|
60
|
+
# passing the site: option as Orcid's Sandbox has an invalid certificate
|
61
|
+
# for the api.sandbox-1.orcid.org
|
62
|
+
@oauth_client ||= Devise::MultiAuth.oauth_client_for(
|
63
|
+
provider_name, options: { site: provider.site_url }
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def client_credentials_token(scope, options = {})
|
68
|
+
tokenizer = options.fetch(:tokenizer) { oauth_client.client_credentials }
|
69
|
+
tokenizer.get_token(scope: scope)
|
70
|
+
end
|
71
|
+
|
4
72
|
end
|
@@ -0,0 +1,20 @@
|
|
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
|
20
|
+
require 'orcid/configuration/provider'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Orcid
|
2
|
+
class Configuration::Provider
|
3
|
+
attr_reader :store
|
4
|
+
def initialize(store = ::ENV)
|
5
|
+
@store = store
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_writer :authentication_scope
|
9
|
+
def authentication_scope
|
10
|
+
@authentication_scope ||= store.fetch('ORCID_APP_AUTHENTICATION_SCOPE') {
|
11
|
+
"/authenticate,/orcid-works/create,/orcid-works/update,/read-public,/orcid-grants/create"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_writer :site_url
|
16
|
+
def site_url
|
17
|
+
@site_url ||= store.fetch('ORCID_SITE_URL') { "http://api.sandbox-1.orcid.org" }
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_writer :token_url
|
21
|
+
def token_url
|
22
|
+
@token_url ||= store.fetch('ORCID_TOKEN_URL') { "https://api.sandbox-1.orcid.org/oauth/token" }
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_writer :signin_via_json_url
|
26
|
+
def signin_via_json_url
|
27
|
+
@signin_via_json_url ||= store.fetch('ORCID_REMOTE_SIGNIN_URL') { "https://sandbox-1.orcid.org/signin/auth.json" }
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_writer :authorize_url
|
31
|
+
def authorize_url
|
32
|
+
@authorize_url ||= store.fetch('ORCID_AUTHORIZE_URL') { "https://sandbox-1.orcid.org/oauth/authorize" }
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_writer :id
|
36
|
+
def id
|
37
|
+
@id ||= store.fetch('ORCID_APP_ID')
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_writer :secret
|
41
|
+
def secret
|
42
|
+
@secret ||= store.fetch('ORCID_APP_SECRET')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/orcid/engine.rb
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
module Orcid
|
2
2
|
class Engine < ::Rails::Engine
|
3
3
|
isolate_namespace Orcid
|
4
|
+
|
5
|
+
initializer 'orcid.initializers' do |app|
|
6
|
+
app.config.paths.add 'app/services', eager_load: true
|
7
|
+
app.config.autoload_paths += %W(
|
8
|
+
#{config.root}/app/services
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
config.before_initialize do |app|
|
13
|
+
Orcid.configure do |config|
|
14
|
+
config.provider_name = 'orcid'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
4
18
|
end
|
5
19
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Orcid
|
2
|
+
# Because in trouble shooting what all goes into this remote call,
|
3
|
+
# you may very well want all of this.
|
4
|
+
class RemoteServiceError < RuntimeError
|
5
|
+
def initialize(options)
|
6
|
+
text = []
|
7
|
+
text << "-- Client --"
|
8
|
+
if client = options[:client]
|
9
|
+
text << "id:\n\t#{client.id.inspect}"
|
10
|
+
text << "site:\n\t#{client.site.inspect}"
|
11
|
+
text << "options:\n\t#{client.options.inspect}"
|
12
|
+
end
|
13
|
+
text << "\n-- Token --"
|
14
|
+
if token = options[:token]
|
15
|
+
text << "access_token:\n\t#{token.token.inspect}"
|
16
|
+
text << "refresh_token:\n\t#{token.refresh_token.inspect}"
|
17
|
+
end
|
18
|
+
text << "\n-- Request --"
|
19
|
+
text << "path:\n\t#{options[:request_path].inspect}" if options[:request_path]
|
20
|
+
text << "headers:\n\t#{options[:request_headers].inspect}" if options[:request_headers]
|
21
|
+
text << "body:\n\t#{options[:request_body]}" if options[:request_body]
|
22
|
+
text << "\n-- Response --"
|
23
|
+
text << "status:\n\t#{options[:response_status].inspect}" if options[:response_status]
|
24
|
+
text << "body:\n\t#{options[:response_body]}" if options[:response_body]
|
25
|
+
super(text.join("\n"))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
class RequestSandboxAuthorizationCode
|
3
|
+
|
4
|
+
def self.call(options = {}, config = {})
|
5
|
+
new(config).call(options)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :cookies, :access_scope, :authorize_url, :login_url
|
9
|
+
attr_reader :oauth_redirect_uri, :orcid_client_id, :authorization_code, :orcid_client_secret
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@orcid_client_id = options.fetch(:orcid_client_id) { Orcid.provider.id }
|
13
|
+
@orcid_client_secret = options.fetch(:orcid_client_secret) { Orcid.provider.secret }
|
14
|
+
@login_url = options.fetch(:login_url) { Orcid.provider.signin_via_json_url }
|
15
|
+
@authorize_url = options.fetch(:authorize_url) { Orcid.provider.authorize_url }
|
16
|
+
@oauth_redirect_uri = options.fetch(:oauth_redirect_uri) { 'https://developers.google.com/oauthplayground' }
|
17
|
+
@access_scope = options.fetch(:scope) { Orcid.provider.authentication_scope }
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(options = {})
|
21
|
+
orcid_profile_id = options.fetch(:orcid_profile_id) { ENV['ORCID_CLAIMED_PROFILE_ID'] }
|
22
|
+
password = options.fetch(:password) { ENV['ORCID_CLAIMED_PROFILE_PASSWORD']}
|
23
|
+
|
24
|
+
login_to_orcid(orcid_profile_id, password)
|
25
|
+
request_authorization
|
26
|
+
request_authorization_code
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_writer :cookies
|
30
|
+
private :cookies
|
31
|
+
|
32
|
+
private
|
33
|
+
def login_to_orcid(orcid_profile_id, password)
|
34
|
+
response = RestClient.post(login_url, userId: orcid_profile_id, password: password )
|
35
|
+
if ! JSON.parse(response)["success"]
|
36
|
+
raise "Response not successful: \n#{response}"
|
37
|
+
else
|
38
|
+
self.cookies = response.cookies
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def request_authorization
|
43
|
+
parameters = { client_id: orcid_client_id, response_type: 'code', scope: access_scope, redirect_uri: oauth_redirect_uri }
|
44
|
+
RestClient.get(authorize_url, {params: parameters, cookies: cookies})
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_authorization_code
|
48
|
+
RestClient.post(authorize_url, {user_oauth_approval: true}, {cookies: cookies})
|
49
|
+
rescue RestClient::Found => e
|
50
|
+
uri = URI.parse(e.response.headers.fetch(:location))
|
51
|
+
CGI::parse(uri.query).fetch('code').first
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/lib/orcid/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orcid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Friesen
|
@@ -24,6 +24,104 @@ dependencies:
|
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mappy
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: devise-multi_auth
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: omniauth-orcid
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: virtus
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: email_validator
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simple_form
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
27
125
|
- !ruby/object:Gem::Dependency
|
28
126
|
name: sqlite3
|
29
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +136,146 @@ dependencies:
|
|
38
136
|
- - '>='
|
39
137
|
- !ruby/object:Gem::Version
|
40
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: engine_cart
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rspec-rails
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: database_cleaner
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: factory_girl
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rspec-html-matchers
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - '>='
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: capybara
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - '>='
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - '>='
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: capybara-webkit
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - '>='
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - '>='
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: webmock
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - '>='
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - '>='
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: figaro
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - '>='
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - '>='
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: rest_client
|
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'
|
41
279
|
description: A Rails engine for orcid.org integration.
|
42
280
|
email:
|
43
281
|
- jeremy.n.friesen@gmail.com
|
@@ -48,10 +286,30 @@ files:
|
|
48
286
|
- app/assets/javascripts/orcid/application.js
|
49
287
|
- app/assets/stylesheets/orcid/application.css
|
50
288
|
- app/controllers/orcid/application_controller.rb
|
289
|
+
- app/controllers/orcid/profile_connections_controller.rb
|
290
|
+
- app/controllers/orcid/profile_requests_controller.rb
|
51
291
|
- app/helpers/orcid/application_helper.rb
|
292
|
+
- app/models/orcid/configuration.rb
|
293
|
+
- app/models/orcid/profile.rb
|
294
|
+
- app/models/orcid/profile_connection.rb
|
295
|
+
- app/models/orcid/profile_request.rb
|
296
|
+
- app/models/orcid/work.rb
|
297
|
+
- app/services/orcid/profile_creation_service.rb
|
298
|
+
- app/services/orcid/profile_lookup_service.rb
|
299
|
+
- app/services/orcid/remote_work_service.rb
|
300
|
+
- app/templates/orcid/work.template.v1.1.xml.erb
|
52
301
|
- app/views/layouts/orcid/application.html.erb
|
302
|
+
- app/views/orcid/profile_connections/new.html.erb
|
303
|
+
- app/views/orcid/profile_requests/new.html.erb
|
304
|
+
- app/views/orcid/profile_requests/show.html.erb
|
305
|
+
- config/locales/orcid.en.yml
|
53
306
|
- config/routes.rb
|
307
|
+
- db/migrate/20140205185338_create_orcid_profile_requests.rb
|
308
|
+
- lib/orcid/configuration/provider.rb
|
309
|
+
- lib/orcid/configuration.rb
|
54
310
|
- lib/orcid/engine.rb
|
311
|
+
- lib/orcid/exceptions.rb
|
312
|
+
- lib/orcid/spec_support.rb
|
55
313
|
- lib/orcid/version.rb
|
56
314
|
- lib/orcid.rb
|
57
315
|
- lib/tasks/orcid_tasks.rake
|
@@ -72,9 +330,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
330
|
version: '0'
|
73
331
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
332
|
requirements:
|
75
|
-
- - '
|
333
|
+
- - '>='
|
76
334
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
335
|
+
version: '0'
|
78
336
|
requirements: []
|
79
337
|
rubyforge_project:
|
80
338
|
rubygems_version: 2.0.14
|