class Util::VSAC::VSACAPI

Constants

DEFAULT_PROGRAM

The default program to use for get_program_details and get_program_release_names calls. This can be overriden by providing a :program in the config or by the single optional parameter for those methods.

TICKET_SERVICE_PARAM

This is the value of the service parameter passed when getting a ticket. This never changes.

Attributes

ticket_granting_ticket[R]

The ticket granting that will be obtained if needed. Accessible so it may be stored in user session. Is a hash of the :ticket and time it :expires.

Public Class Methods

new(options) click to toggle source

Creates a new VSACAPI. If credentials were provided they are checked now. If no credentials are provided then the API can still be used for utility methods.

Options for the API are passed in as a hash.

  • config -

# File lib/util/vsac_api.rb, line 81
def initialize(options)
  # check that :config exists and has needed fields
  if options[:config].nil?
    raise VSACArgumentError.new("Required param :config is missing or empty.")
  else
    symbolized_config = options[:config].symbolize_keys
    if check_config symbolized_config
      @config = symbolized_config
    else
      raise VSACArgumentError.new("Required param :config is missing required URLs.")
    end
  end

  # if a ticket_granting_ticket was passed in, check it and raise errors if found
  # VSAC API Key will be ignored
  if !options[:ticket_granting_ticket].nil?
    provided_ticket_granting_ticket = options[:ticket_granting_ticket]
    if provided_ticket_granting_ticket[:ticket].nil? || provided_ticket_granting_ticket[:expires].nil?
      raise VSACArgumentError.new("Optional param :ticket_granting_ticket is missing :ticket or :expires")
    end

    # check if it has expired
    if Time.now > provided_ticket_granting_ticket[:expires]
      raise VSACTicketExpiredError.new
    end

    # ticket granting ticket looks good
    @ticket_granting_ticket = { ticket: provided_ticket_granting_ticket[:ticket],
      expires: provided_ticket_granting_ticket[:expires] }

  # if api key was provided use it to get a ticket granting ticket
  elsif !options[:api_key].nil?
    @ticket_granting_ticket = get_ticket_granting_ticket(options[:api_key])
  end
end

Public Instance Methods

get_latest_profile_for_program(program = nil) click to toggle source

Gets the latest profile for a program. This is a separate call from the program details call. It returns JSON with only the name of the latest profile and the timestamp of the request. ex:

{
  "name": "eCQM Update 2018-05-04",
  "requestTime": "2018-05-21 03:39:04 PM"
}

Optional parameter program is the program to request from the API. If it is not provided it will look for a :program in the config passed in during construction. If there is no :program in the config it will use the DEFAULT_PROGRAM constant for the program.

Returns the name of the latest profile for the given program.

# File lib/util/vsac_api.rb, line 187
def get_latest_profile_for_program(program = nil)
  # if no program was provided use the one in the config or default in constant
  if program.nil?
    program = @config.fetch(:program, DEFAULT_PROGRAM)
  end

  begin
    # parse json response and return it
    parsedResponse = JSON.parse(RestClient.get("#{@config[:utility_url]}/program/#{ERB::Util.url_encode(program)}/latest%20profile"))

    # As of 5/17/18 VSAC does not return 404 when an invalid profile is provided. It just doesnt fill the name
    # attribute in the 200 response. We need to check this.
    if !parsedResponse['name'].nil?
      return parsedResponse['name']
    else
      raise VSACProgramNotFoundError.new(program)
    end

  # keeping this rescue block in case the API is changed to return 404 for invalid profile
  rescue RestClient::ResourceNotFound
    raise VSACProgramNotFoundError.new(program)
  end
end
get_profile_names() click to toggle source

Gets the list of profiles. This may be used without credentials.

Returns a list of profile names. These are kept in the order that VSAC provides them in.

# File lib/util/vsac_api.rb, line 121
def get_profile_names
  profiles_response = RestClient.get("#{@config[:utility_url]}/profiles")
  profiles = []

  # parse xml response and get text content of each profile element
  doc = Nokogiri::XML(profiles_response)
  profile_list = doc.at_xpath("/ProfileList")
  profile_list.xpath("//profile").each do |profile|
    profiles << profile.text
  end

  return profiles
end
get_program_details(program = nil) click to toggle source

Gets the details for a program. This may be used without credentials.

Optional parameter program is the program to request from the API. If it is not provided it will look for a :program in the config passed in during construction. If there is no :program in the config it will use the DEFAULT_PROGRAM constant for the program.

Returns the JSON parsed response for program details.

# File lib/util/vsac_api.rb, line 160
def get_program_details(program = nil)
  # if no program was provided use the one in the config or default in constant
  if program.nil?
    program = @config.fetch(:program, DEFAULT_PROGRAM)
  end

  begin
    # parse json response and return it
    return JSON.parse(RestClient.get("#{@config[:utility_url]}/program/#{ERB::Util.url_encode(program)}"))
  rescue RestClient::ResourceNotFound
    raise VSACProgramNotFoundError.new(program)
  end
end
get_program_names() click to toggle source

Gets the list of programs. This may be used without credentials.

Returns a list of program names. These are kept in the order that VSAC provides them in.

# File lib/util/vsac_api.rb, line 139
def get_program_names
  programs_response = RestClient.get("#{@config[:utility_url]}/programs")
  program_names = []

  # parse json response and return the names of the programs
  programs_info = JSON.parse(programs_response)['Program']
  programs_info.each do |program|
    program_names << program['name']
  end

  return program_names
end
get_program_release_names(program = nil) click to toggle source

Gets the releases for a program. This may be used without credentials.

Optional parameter program is the program to request from the API. If it is not provided it will look for a :program in the config passed in during construction. If there is no :program in the config it will use the DEFAULT_PROGRAM constant for the program.

Returns a list of release names in a program. These are kept in the order that VSAC provides them in.

# File lib/util/vsac_api.rb, line 219
def get_program_release_names(program = nil)
  program_details = get_program_details(program)
  releases = []

  # pull just the release names out
  program_details['release'].each do |release|
    releases << release['name']
  end

  return releases
end
get_valueset(oid, options = {}) click to toggle source

Gets a valueset. This requires credentials.

# File lib/util/vsac_api.rb, line 234
def get_valueset(oid, options = {})
  # base parameter oid is always needed
  params = { id: oid }

  # release parameter, should be used moving forward
  if !options[:release].nil?
    params[:release] = options[:release]
  end

  # profile parameter, may be needed for getting draft value sets
  if !options[:profile].nil?
    params[:profile] = options[:profile]
    if !options[:include_draft].nil?
      params[:includeDraft] = if !!options[:include_draft] then 'yes' else 'no' end
    end
  else
    if !options[:include_draft].nil?
      raise VSACArgumentError.new("Option :include_draft requires :profile to be provided.")
    end
  end

  # version parameter, rarely used
  if !options[:version].nil?
    params[:version] = options[:version]
  end

  # get a new service ticket
  params[:ticket] = get_ticket

  # run request
  begin
    return RestClient.get("#{@config[:content_url]}/RetrieveMultipleValueSets", params: params)
  rescue RestClient::ResourceNotFound
    raise VSNotFoundError.new(oid)
  rescue RestClient::InternalServerError
    raise VSACError.new("Server error response from VSAC for (#{oid}).")
  end
end

Private Instance Methods

check_config(config) click to toggle source

Checks to ensure the API config has all necessary fields

# File lib/util/vsac_api.rb, line 301
def check_config(config)
  return config != nil &&
         !config[:auth_url].nil? &&
         !config[:content_url].nil? &&
         !config[:utility_url].nil?
end
get_ticket() click to toggle source
# File lib/util/vsac_api.rb, line 275
def get_ticket
  # if there is no ticket granting ticket then we should raise an error
  raise VSACNoCredentialsError.new unless @ticket_granting_ticket
  # if the ticket granting ticket has expired, throw an error
  raise VSACTicketExpiredError.new if Time.now > @ticket_granting_ticket[:expires]

  # attempt to get a ticket
  begin
    ticket = RestClient.post("#{@config[:auth_url]}/Ticket/#{@ticket_granting_ticket[:ticket]}", service: TICKET_SERVICE_PARAM)
    return ticket.to_s
  rescue RestClient::Unauthorized
    @ticket_granting_ticket[:expires] = Time.now
    raise VSACTicketExpiredError.new
  end
end
get_ticket_granting_ticket(api_key) click to toggle source
# File lib/util/vsac_api.rb, line 291
def get_ticket_granting_ticket(api_key)
  begin
    ticket = RestClient.post("#{@config[:auth_url]}/Ticket", apikey: api_key)
    return { ticket: String.new(ticket), expires: Time.now + 8.hours }
  rescue RestClient::Unauthorized
    raise VSACInvalidCredentialsError.new
  end
end