Skip to content

Commit

Permalink
Extend the linked data API
Browse files Browse the repository at this point in the history
* list - returns a list of the loaded linked data authorities
* reload - reload linked data configurations (does not require restart of rails server)
* fetch - retrieve a single linked data term by passing URI as a parameter
  • Loading branch information
elrayle committed Nov 13, 2018
1 parent cdcd992 commit 0f5b97f
Show file tree
Hide file tree
Showing 14 changed files with 1,070 additions and 95 deletions.
143 changes: 96 additions & 47 deletions app/controllers/qa/linked_data_terms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
# out which linked data authority to query based on the 'vocab' param.

class Qa::LinkedDataTermsController < ::ApplicationController
before_action :check_authority, :init_authority
before_action :check_authority, :init_authority, except: [:list, :reload]
before_action :check_search_subauthority, :check_query_param, only: :search
before_action :check_show_subauthority, :check_id_param, only: :show
before_action :check_uri_param, only: :fetch
before_action :validate_auth_reload_token, only: :reload

delegate :cors_allow_origin_header, to: Qa::ApplicationController

Expand All @@ -14,55 +16,85 @@ def index
head :not_found
end

# Return a list of supported authority names
# get "/list/linked_data/authorities"
# @see Qa::Authorities::LinkedData::AuthorityService#authority_names
def list
render json: Qa::Authorities::LinkedData::AuthorityService.authority_names.to_json
end

# Reload authority configurations
# get "/reload/linked_data/authorities?auth_token=YOUR_AUTH_TOKEN_DEFINED_HERE"
# @see Qa::Authorities::LinkedData::AuthorityService#load_authorities
def reload
Qa::Authorities::LinkedData::AuthorityService.load_authorities
list
end

# Return a list of terms based on a query
# get "/search/linked_data/:vocab(/:subauthority)"
# @see Qa::Authorities::LinkedData::SearchQuery#search
def search # rubocop:disable Metrics/MethodLength
begin
terms = @authority.search(query, subauth: subauthority, language: language, replacements: replacement_params)
rescue Qa::ServiceUnavailable
logger.warn "Service Unavailable - Search query #{query} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :service_unavailable
return
rescue Qa::ServiceError
logger.warn "Internal Server Error - Search query #{query} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :internal_server_error
return
rescue RDF::FormatError
logger.warn "RDF Format Error - Results from search query #{query} for#{subauth_warn_msg} authority #{vocab_param} " \
"was not identified as a valid RDF format. You may need to include the linkeddata gem."
head :internal_server_error
return
end
def search
terms = @authority.search(query, subauth: subauthority, language: language, replacements: replacement_params)
cors_allow_origin_header(response)
render json: terms
rescue Qa::ServiceUnavailable
logger.warn "Service Unavailable - Search query #{query} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :service_unavailable
rescue Qa::ServiceError
logger.warn "Internal Server Error - Search query #{query} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :internal_server_error
rescue RDF::FormatError
logger.warn "RDF Format Error - Results from search query #{query} for#{subauth_warn_msg} authority #{vocab_param} " \
"was not identified as a valid RDF format. You may need to include the linkeddata gem."
head :internal_server_error
end

# Return all the information for a given term
# Return all the information for a given term given an id or URI
# get "/show/linked_data/:vocab/:id"
# get "/show/linked_data/:vocab/:subauthority/:id
# @see Qa::Authorities::LinkedData::FindTerm#find
def show # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
begin
term = @authority.find(id, subauth: subauthority, language: language, replacements: replacement_params, jsonld: jsonld?)
rescue Qa::TermNotFound
logger.warn "Term Not Found - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :not_found
return
rescue Qa::ServiceUnavailable
logger.warn "Service Unavailable - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :service_unavailable
return
rescue Qa::ServiceError
logger.warn "Internal Server Error - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :internal_server_error
return
rescue RDF::FormatError
logger.warn "RDF Format Error - Results from fetch term #{id} for#{subauth_warn_msg} authority #{vocab_param} " \
"was not identified as a valid RDF format. You may need to include the linkeddata gem."
head :internal_server_error
return
end
term = @authority.find(id, subauth: subauthority, language: language, replacements: replacement_params, jsonld: jsonld?)
cors_allow_origin_header(response)
content_type = jsonld? ? 'application/ld+json' : 'application/json'
render json: term, content_type: content_type
rescue Qa::TermNotFound
logger.warn "Term Not Found - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :not_found
rescue Qa::ServiceUnavailable
logger.warn "Service Unavailable - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :service_unavailable
rescue Qa::ServiceError
logger.warn "Internal Server Error - Fetch term #{id} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :internal_server_error
rescue RDF::FormatError
logger.warn "RDF Format Error - Results from fetch term #{id} for#{subauth_warn_msg} authority #{vocab_param} " \
"was not identified as a valid RDF format. You may need to include the linkeddata gem."
head :internal_server_error
end

# Return all the information for a given term given a URI
# get "/fetch/linked_data/:vocab"
# @see Qa::Authorities::LinkedData::FindTerm#find
def fetch # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
term = @authority.find(uri, subauth: subauthority, language: language, replacements: replacement_params, jsonld: jsonld?)
cors_allow_origin_header(response)
content_type = jsonld? ? 'application/ld+json' : 'application/json'
render json: term, content_type: content_type
rescue Qa::TermNotFound
logger.warn "Term Not Found - Fetch term #{uri} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :not_found
rescue Qa::ServiceUnavailable
logger.warn "Service Unavailable - Fetch term #{uri} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :service_unavailable
rescue Qa::ServiceError
logger.warn "Internal Server Error - Fetch term #{uri} unsuccessful for#{subauth_warn_msg} authority #{vocab_param}"
head :internal_server_error
rescue RDF::FormatError
logger.warn "RDF Format Error - Results from fetch term #{uri} for#{subauth_warn_msg} authority #{vocab_param} " \
"was not identified as a valid RDF format. You may need to include the linkeddata gem."
head :internal_server_error
end

private
Expand Down Expand Up @@ -102,10 +134,9 @@ def vocab_param
end

def check_query_param
if params[:q].nil? || !params[:q].size.positive? # rubocop:disable Style/GuardClause
logger.warn "Required search param 'q' is missing or empty"
head :bad_request
end
return unless q.blank?
logger.warn "Required search param 'q' is missing or empty"
head :bad_request
end

# converts wildcards into URL-encoded characters
Expand All @@ -114,10 +145,19 @@ def query
end

def check_id_param
if params[:id].nil? || !params[:id].size.positive? # rubocop:disable Style/GuardClause
logger.warn "Required show param 'id' is missing or empty"
head :bad_request
end
return unless id.blank?
logger.warn "Required show param 'id' is missing or empty"
head :bad_request
end

def check_uri_param
return unless uri.blank?
logger.warn "Required show param 'uri' is missing or empty"
head :bad_request
end

def uri
params[:uri]
end

def id
Expand Down Expand Up @@ -149,4 +189,13 @@ def format
def jsonld?
format == 'jsonld'
end

def validate_auth_reload_token
token = params.key?(:auth_token) ? params[:auth_token] : nil
valid = Qa.config.valid_authority_reload_token?(token)
return true if valid
logger.warn "FAIL: unable to reload authorities; error_msg: Invalid token (#{token}) does not match expected token."
head :unauthorized
false
end
end
18 changes: 1 addition & 17 deletions config/initializers/linked_data_authorities.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
auth_cfg = {}
# load QA configured linked data authorities
Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
auth = File.basename(fn, '.json').upcase.to_sym
json = File.read(File.expand_path(fn, __FILE__))
cfg = JSON.parse(json).deep_symbolize_keys
auth_cfg[auth] = cfg
end

# load app configured linked data authorities and overrides
Dir[Rails.root.join('config', 'authorities', 'linked_data', '*.json')].each do |fn|
auth = File.basename(fn, '.json').upcase.to_sym
json = File.read(File.expand_path(fn, __FILE__))
cfg = JSON.parse(json).deep_symbolize_keys
auth_cfg[auth] = cfg
end
LINKED_DATA_AUTHORITIES_CONFIG = auth_cfg.freeze
Qa::Authorities::LinkedData::AuthorityService.load_authorities
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Qa::Engine.routes.draw do
get "/list/linked_data/authorities", controller: :linked_data_terms, action: :list
get "/reload/linked_data/authorities", controller: :linked_data_terms, action: :reload
get "/search/linked_data/:vocab(/:subauthority)", controller: :linked_data_terms, action: :search
get "/fetch/linked_data/:vocab", controller: :linked_data_terms, action: :fetch
get "/show/linked_data/:vocab/:id", controller: :linked_data_terms, action: :show
get "/show/linked_data/:vocab/:subauthority/:id", controller: :linked_data_terms, action: :show
get "/terms/:vocab(/:subauthority)", controller: :terms, action: :index
Expand Down
Loading

0 comments on commit 0f5b97f

Please sign in to comment.