Class: SulOrcidClient

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/sul_orcid_client.rb,
lib/sul_orcid_client/version.rb,
lib/sul_orcid_client/work_mapper.rb,
lib/sul_orcid_client/cocina_support.rb,
lib/sul_orcid_client/contributor_mapper.rb

Overview

Client for interacting with ORCID API

Defined Under Namespace

Classes: CocinaSupport, ContributorMapper, InvalidTokenError, WorkMapper

Constant Summary collapse

VERSION =
"0.4.1"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#base_auth_urlObject

Returns the value of attribute base_auth_url.



39
40
41
# File 'lib/sul_orcid_client.rb', line 39

def base_auth_url
  @base_auth_url
end

#base_public_urlObject

Returns the value of attribute base_public_url.



39
40
41
# File 'lib/sul_orcid_client.rb', line 39

def base_public_url
  @base_public_url
end

#base_urlObject

Returns the value of attribute base_url.



39
40
41
# File 'lib/sul_orcid_client.rb', line 39

def base_url
  @base_url
end

#client_idObject

Returns the value of attribute client_id.



39
40
41
# File 'lib/sul_orcid_client.rb', line 39

def client_id
  @client_id
end

#client_secretObject

Returns the value of attribute client_secret.



39
40
41
# File 'lib/sul_orcid_client.rb', line 39

def client_secret
  @client_secret
end

Class Method Details

.configure(client_id:, client_secret:, base_url:, base_public_url:, base_auth_url:) ⇒ Object

Parameters:

  • client_id (String)

    the client identifier registered with Orcid

  • client_secret (String)

    the client secret to authenticate with Orcid

  • base_url (String)

    the base URL for the API

  • base_public_url (String)

    the base public URL for the API

  • base_auth_url (String)

    the base authorization URL for the API



27
28
29
30
31
32
33
34
# File 'lib/sul_orcid_client.rb', line 27

def configure(client_id:, client_secret:, base_url:, base_public_url:, base_auth_url:)
  instance.base_url = base_url
  instance.base_public_url = base_public_url
  instance.client_id = client_id
  instance.client_secret = client_secret
  instance.base_auth_url = base_auth_url
  self
end

Instance Method Details

#add_work(orcidid:, work:, token:) ⇒ string

Add a new work for a researcher.

Parameters:

  • ORCID (string)

    ID for the researcher

  • work (Hash)

    in correct data structure for ORCID work

  • access (string)

    token

Returns:

  • (string)

    put-code



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/sul_orcid_client.rb', line 106

def add_work(orcidid:, work:, token:)
  response = conn_with_token(token).post("/v3.0/#{base_orcidid(orcidid)}/work",
    work.to_json,
    "Content-Type" => "application/json")

  case response.status
  when 201
    response["Location"].match(%r{work/(\d+)})[1]
  when 401
    raise InvalidTokenError,
      "Invalid token for #{orcidid} - ORCID.org API returned #{response.status} (#{response.body})"
  when 409
    match = response.body.match(/put-code (\d+)\./)
    raise "ORCID.org API returned a 409, but could not find put-code" unless match

    match[1]
  else
    raise "ORCID.org API returned #{response.status} (#{response.body}) for: #{work.to_json}"
  end
end

#delete_work(orcidid:, put_code:, token:) ⇒ boolean

Delete a work

Parameters:

  • ORCID (string)

    ID for the researcher

  • put-code (string)
  • access (string)

    token

Returns:

  • (boolean)

    true if delete succeeded



150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/sul_orcid_client.rb', line 150

def delete_work(orcidid:, put_code:, token:)
  response = conn_with_token(token).delete("/v3.0/#{base_orcidid(orcidid)}/work/#{put_code}")

  case response.status
  when 204
    true
  when 404
    false
  else
    raise "ORCID.org API returned #{response.status} when deleting #{put_code} for #{orcidid}"
  end
end

#fetch_name(orcidid:) ⇒ Object

Fetches the name for a user given an orcidid



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/sul_orcid_client.rb', line 55

def fetch_name(orcidid:)
  match = /[0-9xX]{4}-[0-9xX]{4}-[0-9xX]{4}-[0-9xX]{4}/.match(orcidid)
  raise "invalid orcidid provided" unless match

  response = public_conn.get("/v3.0/#{match[0]&.upcase}/personal-details")
  case response.status
  when 200
    resp_json = JSON.parse(response.body)
    [resp_json.dig("name", "given-names", "value"),
      resp_json.dig("name", "family-name", "value")]
  else
    raise "ORCID.org API returned #{response.status} (#{response.body}) for: #{orcidid}"
  end
end

#fetch_work(orcidid:, put_code:) ⇒ Object

Fetch the details for a work



50
51
52
# File 'lib/sul_orcid_client.rb', line 50

def fetch_work(orcidid:, put_code:)
  get("/v3.0/#{base_orcidid(orcidid)}/work/#{put_code}")
end

#fetch_works(orcidid:) ⇒ Hash

Fetch the works for a researcher. Model for the response: pub.orcid.org/v3.0/#!/Development_Public_API_v3.0/viewWorksv3

Parameters:

  • ORCID (string)

    ID for the researcher

Returns:

  • (Hash)


45
46
47
# File 'lib/sul_orcid_client.rb', line 45

def fetch_works(orcidid:)
  get("/v3.0/#{base_orcidid(orcidid)}/works")
end

#search(query:, expanded: false) ⇒ Object

Parameters:

  • query (query)

    to pass to ORCID

  • set (expanded)

    to true or false (defaults to false) to indicate an expanded query results (see ORCID docs)



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/sul_orcid_client.rb', line 74

def search(query:, expanded: false)
  if expanded
    search_method = "expanded-search"
    response_name = "expanded-result"
  else
    search_method = "search"
    response_name = "result"
  end

  # this is the maximum number of rows ORCID allows in their response currently
  max_num_returned = 1000
  total_response = get("/v3.0/#{search_method}/?q=#{query}&rows=#{max_num_returned}")
  num_results = total_response["num-found"]

  return total_response if num_results <= max_num_returned

  num_pages = (num_results / max_num_returned.to_f).ceil

  # we already have page 1 of the results
  (1..num_pages - 1).each do |page_num|
    response = get("/v3.0/#{search_method}/?q=#{query}&start=#{(page_num * max_num_returned) + 1}&rows=#{max_num_returned}")
    total_response[response_name] += response[response_name]
  end

  total_response
end

#update_work(orcidid:, work:, token:, put_code:) ⇒ Boolean

Update an existing work for a researcher.

Parameters:

  • orcidid (String)

    an ORCiD ID for the researcher

  • work (Hash)

    a work in correct data structure for ORCID work

  • token (String)

    an ORCiD API access token

  • put_code (String)

    the PUT code

Returns:

  • (Boolean)

    true if update succeeded

Raises:

  • (RuntimeError)

    if the API response status is not successful



134
135
136
137
138
139
140
141
142
143
# File 'lib/sul_orcid_client.rb', line 134

def update_work(orcidid:, work:, token:, put_code:)
  response = conn_with_token(token).put("/v3.0/#{base_orcidid(orcidid)}/work/#{put_code}",
    work.merge({"put-code" => put_code}).to_json,
    "Content-Type" => "application/vnd.orcid+json")

  raise "ORCID.org API returned #{response.status} when updating #{put_code} for #{orcidid}. The author may have previously deleted this work from their ORCID profile." if response.status == 404

  raise "ORCID.org API returned #{response.status} when updating #{put_code} for #{orcidid}" unless response.status == 200
  true
end