orcid 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: be9ad04a8c327b62e782d442e012920e824e3054
4
- data.tar.gz: fad8d6daf69492a8cf851257e8879562f6219876
3
+ metadata.gz: c138546f55044cf0a5a24bc027071c4a825f9aa5
4
+ data.tar.gz: e376ae1a6e011f2c74ef68c12c4aceede22240e4
5
5
  SHA512:
6
- metadata.gz: 8ddfbeef40f5ec7c9a810f4ecea25b6d8b968e6e36c7a70b2454728e40c6d13e312e8eb12136b9b3dcfa769a91d3302e66b4a3015b2ec6da6ae19666897428e1
7
- data.tar.gz: c734a55b50001f919d674b2f70c9f7dd7e2f12b413b1b6c44c00f27f3507296a5ef9c6a6319d8fb94508d9d76996287ca4ac9e9cac0223c6ba27149d811d6b38
6
+ metadata.gz: d8ca33ed888b474c53ca7d36ec9a9b73e3449fbe285ca19ac2a1fd92a2b10255c7eb108231b130b6970ceeffde234880d39fb78756641acb10f6a28c36c74bf8
7
+ data.tar.gz: 2e690ffa69dd81e14ec8ae6820289789781c8f5d3ff8960bc2d79bf4898e3d94573414504612190e8bf73016daaea1a1f69783e699979a8925a07f550c6ce5e6
data/Gemfile CHANGED
@@ -12,4 +12,7 @@ gemspec
12
12
 
13
13
  # To use debugger
14
14
  # gem 'debugger'
15
- gem 'coveralls', require: false
15
+ gem 'coveralls', require: false
16
+ gem 'execjs'
17
+ gem 'therubyracer', platforms: :ruby
18
+ gem 'byebug', require: false
data/README.md CHANGED
@@ -69,6 +69,23 @@ $ rails generate orcid:install
69
69
 
70
70
  *Note: It will prompt you for your Orcid application secrets.*
71
71
 
72
+
73
+ ### Caveat
74
+
75
+ You will also need to **update your devise configuration** in your routes.
76
+
77
+ From something like this:
78
+
79
+ ```ruby
80
+ devise_for :users
81
+ ```
82
+
83
+ To:
84
+
85
+ ```ruby
86
+ devise_for :users, controllers: { omniauth_callbacks: 'devise/multi_auth/omniauth_callbacks' }
87
+ ```
88
+
72
89
  You may find it helpful to review the help text, as there are a few options for the generator.
73
90
 
74
91
  ```console
@@ -156,6 +173,23 @@ Run the online tests with
156
173
  $ rake spec:online
157
174
  ```
158
175
 
176
+ ### Running ALL of the Tests
177
+
178
+ Not all of the tests run. There are a few very long running tests that run.
179
+
180
+ ```console
181
+ $ ORCID_APP_ID=<YOUR ORCID APP ID> \
182
+ ORCID_APP_SECRET=<YOUR ORCID APP SECRET> \
183
+ MAILINATOR_API_KEY=<YOUR MAILINATOR KEY> \
184
+ ORCID_CLAIMED_PROFILE_ID=<AN ORCID PROFILE YOUR APP HAS ALREADY CLAIMED> \
185
+ ORCID_CLAIMED_PROFILE_PASSWORD=<THE PASSWORD FOR THE ALREADY CLAIMED ORCID> \
186
+ bundle exec rake spec:jenkins
187
+ ```
188
+
189
+ By setting all of the above environment variables, you will run tests that will:
190
+
191
+ * Create an Orcid, then claim it, and authenticate with your application via ORCID
192
+
159
193
  ## Versioning
160
194
 
161
195
  **Orcid** uses [Semantic Versioning 2.0.0](http://semver.org/)
data/Rakefile CHANGED
@@ -21,6 +21,7 @@ namespace :spec do
21
21
  RSpec::Core::RakeTask.new(:all) do
22
22
  ENV['COVERAGE'] = 'true'
23
23
  end
24
+
24
25
  desc 'Only run specs that do not require net connect'
25
26
  RSpec::Core::RakeTask.new(:offline) do |t|
26
27
  t.rspec_opts = '--tag ~requires_net_connect'
@@ -31,6 +32,15 @@ namespace :spec do
31
32
  t.rspec_opts = '--tag requires_net_connect'
32
33
  end
33
34
 
35
+ desc 'Run the Jenkins CI specs'
36
+ task :jenkins do
37
+ ENV['RAILS_ENV'] = 'test'
38
+ ENV['SPEC_OPTS'] = '--profile 20'
39
+ Rake::Task['engine_cart:clean'].invoke
40
+ Rake::Task['engine_cart:generate'].invoke
41
+ Rake::Task['spec:all'].invoke
42
+ end
43
+
34
44
  desc 'Run the Travis CI specs'
35
45
  task :travis do
36
46
  ENV['RAILS_ENV'] = 'test'
@@ -12,4 +12,3 @@ ORCID_APP_SECRET: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
12
12
 
13
13
  ORCID_CLAIMED_PROFILE_ID: 0000-0000-0000-0000
14
14
  ORCID_CLAIMED_PROFILE_PASSWORD: password1A
15
- ORCID_CLAIMED_PROFILE_EMAIL: cwksfxyqkmrudrfrdxvlzjxl@mailinator.com
@@ -17,7 +17,7 @@ module Orcid
17
17
  def authentication_scope
18
18
  @authentication_scope ||=
19
19
  store.fetch('ORCID_APP_AUTHENTICATION_SCOPE') do
20
- '/authenticate /orcid-works/create /orcid-works/update /read-public'
20
+ '/authenticate /orcid-works/create /orcid-works/update'
21
21
  end
22
22
  end
23
23
 
@@ -1,12 +1,16 @@
1
1
  require 'rest_client'
2
+
3
+ # This follows the instructions from:
4
+ # http://support.orcid.org/knowledgebase/articles/179969-methods-to-generate-an-access-token-for-testing#curl
2
5
  class RequestSandboxAuthorizationCode
3
6
 
4
- def self.call(options = {}, config = {})
5
- new(config).call(options)
7
+ def self.call(options = {})
8
+ new(options).call
6
9
  end
7
10
 
8
11
  attr_reader :cookies, :access_scope, :authorize_url, :login_url
9
12
  attr_reader :oauth_redirect_uri, :orcid_client_id, :authorization_code, :orcid_client_secret
13
+ attr_reader :orcid_profile_id, :password
10
14
 
11
15
  def initialize(options = {})
12
16
  @orcid_client_id = options.fetch(:orcid_client_id) { Orcid.provider.id }
@@ -15,13 +19,13 @@ class RequestSandboxAuthorizationCode
15
19
  @authorize_url = options.fetch(:authorize_url) { Orcid.provider.authorize_url }
16
20
  @oauth_redirect_uri = options.fetch(:oauth_redirect_uri) { 'https://developers.google.com/oauthplayground' }
17
21
  @access_scope = options.fetch(:scope) { Orcid.provider.authentication_scope }
22
+ @orcid_profile_id = options.fetch(:orcid_profile_id) { ENV['ORCID_CLAIMED_PROFILE_ID'] }
23
+ @password = options.fetch(:password) { ENV['ORCID_CLAIMED_PROFILE_PASSWORD'] }
18
24
  end
19
25
 
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)
26
+ def call
27
+ puts "Attempting to login to orcid { PROFILE_ID: '#{orcid_profile_id}', PASSWORD: '#{password}' }"
28
+ login_to_orcid
25
29
  request_authorization
26
30
  request_authorization_code
27
31
  end
@@ -31,10 +35,19 @@ class RequestSandboxAuthorizationCode
31
35
 
32
36
  private
33
37
 
34
- def login_to_orcid(orcid_profile_id, password)
35
- response = RestClient.post(
36
- login_url, userId: orcid_profile_id, password: password
37
- )
38
+ def custom_authorization_url
39
+ authorize_url.sub('oauth/authorize', 'oauth/custom/authorize.json')
40
+ end
41
+
42
+ def resource_options
43
+ { ssl_version: :SSLv23 }.tap {|options|
44
+ options[:headers] = { cookies: cookies } if cookies
45
+ }
46
+ end
47
+
48
+ def login_to_orcid
49
+ resource = RestClient::Resource.new(login_url, resource_options)
50
+ response = resource.post({ userId: orcid_profile_id, password: password })
38
51
  if JSON.parse(response)['success']
39
52
  self.cookies = response.cookies
40
53
  else
@@ -49,16 +62,70 @@ class RequestSandboxAuthorizationCode
49
62
  scope: access_scope,
50
63
  redirect_uri: oauth_redirect_uri
51
64
  }
52
- RestClient.get(authorize_url, { params: parameters, cookies: cookies })
65
+ resource = RestClient::Resource.new("#{authorize_url}?#{parameters.to_query}", resource_options)
66
+ response = resource.get
67
+ response
53
68
  end
54
69
 
55
70
  def request_authorization_code
56
- RestClient.post(
57
- authorize_url, { user_oauth_approval: true }, { cookies: cookies }
58
- )
59
- rescue RestClient::Found => e
60
- uri = URI.parse(e.response.headers.fetch(:location))
71
+ options = resource_options
72
+ options[:headers] ||= {}
73
+ options[:headers][:content_type] = :json
74
+ options[:headers][:accept] = :json
75
+ resource = RestClient::Resource.new(custom_authorization_url, options)
76
+ response = resource.post(authorization_code_payload.to_json)
77
+ json = JSON.parse(response)
78
+ redirected_to = json.fetch('redirectUri').fetch('value')
79
+ uri = URI.parse(redirected_to)
61
80
  CGI.parse(uri.query).fetch('code').first
81
+ rescue RestClient::Exception => e
82
+ File.open("/Users/jfriesen/Desktop/orcid.html", 'w+') {|f| f.puts e.response.body.force_encoding('UTF-8') }
83
+ $stderr.puts "Response Code: #{e.response.code}\n\tCookies: #{cookies.inspect}\n\tAuthorizeURL: #{authorize_url.inspect}"
84
+ raise e
85
+ end
86
+
87
+ def authorization_code_payload
88
+ {
89
+ "errors" => [],
90
+ "userName" => {
91
+ "errors" => [],
92
+ "value" => "",
93
+ "required" => true,
94
+ "getRequiredMessage" => nil
95
+ },
96
+ "password" => {
97
+ "errors" => [],
98
+ "value" => "",
99
+ "required" => true,
100
+ "getRequiredMessage" => nil
101
+ },
102
+ "clientId" => {
103
+ "errors" => [],
104
+ "value" => "#{orcid_client_id}",
105
+ "required" => true,
106
+ "getRequiredMessage" => nil
107
+ },
108
+ "redirectUri" => {
109
+ "errors" => [],
110
+ "value" => "=#{URI.escape(oauth_redirect_uri)}",
111
+ "required" => true,
112
+ "getRequiredMessage" => nil
113
+ },
114
+ "scope" => {
115
+ "errors" => [],
116
+ "value" => "#{access_scope}",
117
+ "required" => true,
118
+ "getRequiredMessage" => nil
119
+ },
120
+ "responseType" => {
121
+ "errors" => [],
122
+ "value" => "code",
123
+ "required" => true,
124
+ "getRequiredMessage" => nil
125
+ },
126
+ "approved" => true,
127
+ "persistentTokenEnabled" => false
128
+ }
62
129
  end
63
130
 
64
131
  end
@@ -1,3 +1,3 @@
1
1
  module Orcid
2
- VERSION = '0.8.2'
2
+ VERSION = '0.8.3'
3
3
  end
@@ -31,10 +31,10 @@ Gem::Specification.new do |s|
31
31
  s.require_paths = ['lib']
32
32
 
33
33
  s.add_dependency 'rails', '~> 4.0.3'
34
- s.add_dependency 'mappy', '~> 0.1.0'
35
34
  s.add_dependency 'figaro'
36
- s.add_dependency 'devise-multi_auth', '~> 0.1.0'
35
+ s.add_dependency 'devise-multi_auth', '~> 0.1'
37
36
  s.add_dependency 'omniauth-orcid'
37
+ s.add_dependency 'mappy'
38
38
  s.add_dependency 'virtus'
39
39
  s.add_dependency 'email_validator'
40
40
  s.add_dependency 'simple_form'
@@ -28,23 +28,25 @@ describe 'non-UI based interactions' , requires_net_connect: true do
28
28
  expect(profile_request.orcid_profile_id).to be_nil
29
29
  end
30
30
 
31
- it 'creates a profile' do
32
- profile_request_coordinator.call
33
- profile_request.reload
31
+ if ENV['MAILINATOR_API_KEY']
32
+ it 'creates a profile' do
33
+ profile_request_coordinator.call
34
+ profile_request.reload
34
35
 
35
- orcid_profile_id = profile_request.orcid_profile_id
36
+ orcid_profile_id = profile_request.orcid_profile_id
36
37
 
37
- expect(orcid_profile_id).to match(/\w{4}-\w{4}-\w{4}-\w{4}/)
38
+ expect(orcid_profile_id).to match(/\w{4}-\w{4}-\w{4}-\w{4}/)
38
39
 
39
- claim_the_orcid!(random_valid_email_prefix)
40
+ claim_the_orcid!(random_valid_email_prefix)
40
41
 
41
- authenticate_the_orcid!(orcid_profile_id, orcid_profile_password)
42
+ authenticate_the_orcid!(orcid_profile_id, orcid_profile_password)
42
43
 
43
- orcid_profile = Orcid::Profile.new(orcid_profile_id)
44
+ orcid_profile = Orcid::Profile.new(orcid_profile_id)
44
45
 
45
- orcid_profile.append_new_work(work)
46
+ orcid_profile.append_new_work(work)
46
47
 
47
- expect(orcid_profile.remote_works(force: true).count).to eq(1)
48
+ expect(orcid_profile.remote_works(force: true).count).to eq(1)
49
+ end
48
50
  end
49
51
 
50
52
  end
@@ -55,11 +57,11 @@ describe 'non-UI based interactions' , requires_net_connect: true do
55
57
 
56
58
  before(:each) do
57
59
  expect(work).to be_valid
58
- authenticate_the_orcid!(orcid_profile_id, orcid_profile_password)
59
60
  end
60
61
 
61
62
  subject { Orcid::Profile.new(orcid_profile_id) }
62
63
  it 'should increment orcid works' do
64
+ authenticate_the_orcid!(orcid_profile_id, orcid_profile_password)
63
65
  replacement_work = Orcid::Work.new(title: "Test Driven Orcid Integration", work_type: 'test')
64
66
  appended_work = Orcid::Work.new(title: "Another Test Drive", work_type: 'test')
65
67
 
@@ -80,32 +82,41 @@ describe 'non-UI based interactions' , requires_net_connect: true do
80
82
  Devise::MultiAuth::CaptureSuccessfulExternalAuthentication.call(user, normalized_token)
81
83
  end
82
84
 
83
- # Achtung, this is going to be fragile
84
85
  def claim_the_orcid!(email_prefix)
85
- Capybara.current_driver = :webkit
86
- Capybara.app_host = 'http://mailinator.com'
87
- Capybara.run_server = false
86
+ $stdout.puts "Claiming an ORCID. This could take a while."
87
+ api_token = ENV.fetch('MAILINATOR_API_KEY')
88
88
 
89
- sleep(2) # Because Orcid may not have delivered the mail just yet
90
-
91
- visit("/inbox.jsp?to=#{email_prefix}")
92
- sleep(2) # Because mailinator might be slow
93
- begin
94
- page.find('#mailcontainer a').click
95
- rescue Capybara::ElementNotFound => e
96
- filename = Rails.root.join('tmp/claim_orcid_failure.png')
97
- page.save_screenshot(filename, full: true)
98
- `open #{filename}`
99
- raise e
89
+ mailbox_uri = "https://api.mailinator.com/api/inbox?to=#{email_prefix}&token=#{api_token}"
90
+
91
+ orcid_messages = []
92
+ mailinator_requests(mailbox_uri) do |response|
93
+ orcid_messages = response['messages'].select {|m| m['from'] =~ /\.orcid\.org\Z/ }
94
+ !!orcid_messages.first
100
95
  end
101
96
 
102
- sleep(2) # Because mailinator might be slow
103
- href = page.all('.mailview a').collect { |a| a[:href] }.find {|href| href = /\/claim\//}
97
+ orcid_message = orcid_messages.first
98
+ raise "Unable to retrieve email for #{email_prefix}@mailinator.com" unless orcid_message
99
+
100
+ message_uri = "https://api.mailinator.com/api/email?msgid=#{orcid_message.fetch('id')}&token=#{api_token}"
101
+ claim_uri = nil
102
+ mailinator_requests(message_uri) do |response|
103
+ bodies = response.fetch('data').fetch('parts').map { |part| part.fetch('body') }
104
+ bodies.each do |body|
105
+ if body =~ %r{(https://sandbox.orcid.org/claim/[\w\?=]+)}
106
+ claim_uri = $1.strip
107
+ break
108
+ end
109
+ end
110
+ claim_uri
111
+ end
104
112
 
105
- uri = URI.parse(href)
113
+ # I have the href for the claim
114
+ uri = URI.parse(claim_uri)
115
+ Capybara.current_driver = :webkit
116
+ Capybara.run_server = false
106
117
  Capybara.app_host = "#{uri.scheme}://#{uri.host}"
107
118
 
108
- visit(uri.path)
119
+ visit("#{uri.path}?#{uri.query}")
109
120
  page.all('input').each do |input|
110
121
  case input[:name]
111
122
  when 'password' then input.set(orcid_profile_password)
@@ -114,6 +125,28 @@ describe 'non-UI based interactions' , requires_net_connect: true do
114
125
  end
115
126
  end
116
127
  page.all('button').find {|i| i.text == 'Claim' }.click
117
- sleep(2) # Because claiming your orcid could be slowe
128
+ sleep(5) # Because claiming your orcid could be slow
129
+ end
130
+
131
+ def mailinator_requests(uri)
132
+ base_sleep_duration = ENV.fetch('MAILINATOR_SECONDS_TO_RETRY', 120).to_i
133
+ retry_attempts = ENV.fetch('MAILINATOR_RETRY_ATTEMPTS', 6).to_i
134
+ (0...retry_attempts).each do |attempt|
135
+ sleep_duration = base_sleep_duration * (attempt +1)
136
+ $stdout.print "\n=-=-= Connecting to Mailinator. Attempt #{attempt+1}\n\tWaiting #{sleep_duration} seconds to connect: "
137
+ $stdout.flush
138
+ (0...sleep_duration).each do |second|
139
+ $stdout.print 'z' if (second % 5 == 0)
140
+ $stdout.flush
141
+ sleep(1)
142
+ end
143
+ resource = RestClient::Resource.new(uri, ssl_version: :SSLv23)
144
+ response = JSON.parse(resource.get(format: :json))
145
+ if yield(response)
146
+ $stdout.print "\n=-=-= Success on attempt #{attempt+1}. Moving on."
147
+ $stdout.flush
148
+ break
149
+ end
150
+ end
118
151
  end
119
152
  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.8.2
4
+ version: 0.8.3
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-09-24 00:00:00.000000000 Z
11
+ date: 2014-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,20 +24,6 @@ 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
27
  - !ruby/object:Gem::Dependency
42
28
  name: figaro
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +44,14 @@ dependencies:
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: 0.1.0
47
+ version: '0.1'
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: 0.1.0
54
+ version: '0.1'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: omniauth-orcid
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +66,20 @@ dependencies:
80
66
  - - ">="
81
67
  - !ruby/object:Gem::Version
82
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mappy
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
83
  - !ruby/object:Gem::Dependency
84
84
  name: virtus
85
85
  requirement: !ruby/object:Gem::Requirement