class Passwordstate::Client

Constants

DEFAULT_HEADERS
USER_AGENT

Attributes

api_type[W]
auth_data[RW]
headers[RW]
server_url[RW]
timeout[R]
validate_certificate[RW]

Public Class Methods

new(url, options = {}) click to toggle source
# File lib/passwordstate/client.rb, line 15
def initialize(url, options = {})
  @server_url = URI(url)
  @validate_certificate = true
  @headers = DEFAULT_HEADERS
  @auth_data = options.select { |k, _v| %i[apikey username password].include? k }
  @api_type = options.fetch(:api_type) if options.key? :api_type
  @timeout = options.fetch(:timeout, 15)
end

Public Instance Methods

api_type() click to toggle source
# File lib/passwordstate/client.rb, line 28
def api_type
  @api_type || (auth_data.key?(:apikey) ? :api : :winapi)
end
folders() click to toggle source
# File lib/passwordstate/client.rb, line 37
def folders
  ResourceList.new self, Passwordstate::Resources::Folder,
                   only: %i[all search post]
end
hosts() click to toggle source
# File lib/passwordstate/client.rb, line 42
def hosts
  ResourceList.new self, Passwordstate::Resources::Host,
                   except: %i[search put]
end
inspect() click to toggle source
# File lib/passwordstate/client.rb, line 117
def inspect
  "#{to_s[0..-2]} #{instance_variables.reject { |k| %i[@auth_data @http @logger].include? k }.map { |k| "#{k}=#{instance_variable_get(k).inspect}" }.join ', '}>"
end
logger() click to toggle source
# File lib/passwordstate/client.rb, line 24
def logger
  @logger ||= Logging.logger[self]
end
password_lists() click to toggle source
# File lib/passwordstate/client.rb, line 51
def password_lists
  ResourceList.new self, Passwordstate::Resources::PasswordList,
                   except: %i[put delete]
end
passwords() click to toggle source
# File lib/passwordstate/client.rb, line 47
def passwords
  ResourceList.new self, Passwordstate::Resources::Password
end
request(method, api_path, options = {}) click to toggle source
# File lib/passwordstate/client.rb, line 80
def request(method, api_path, options = {})
  uri = URI(server_url + "/#{api_type}/" + api_path)
  uri.query = URI.encode_www_form(options.fetch(:query)) if options.key? :query
  uri.query = nil if uri.query.nil? || uri.query.empty?

  req_obj = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new uri
  if options.key? :body
    req_obj.body = options.fetch(:body)
    req_obj.body = req_obj.body.to_json unless req_obj.body.is_a?(String)
    req_obj['content-type'] = 'application/json'
  end

  req_obj.ntlm_auth(auth_data[:username], auth_data[:password]) if api_type == :winapi
  headers.each { |h, v| req_obj[h] = v }
  req_obj['APIKey'] = auth_data[:apikey] if api_type == :api
  req_obj['Reason'] = options.fetch(:reason) if options.key?(:reason) && version?('>= 8.4.8449')

  print_http req_obj
  res_obj = http.request req_obj
  print_http res_obj

  return true if res_obj.is_a? Net::HTTPNoContent

  data = JSON.parse(res_obj.body) rescue nil
  if data
    return data if res_obj.is_a? Net::HTTPSuccess

    data = data&.first

    raise Passwordstate::HTTPError.new_by_code(res_obj.code, req_obj, res_obj, data&.fetch('errors', []) || [])
  else
    return res_obj.body if res_obj.is_a?(Net::HTTPSuccess) && options.fetch(:allow_html, true)

    raise Passwordstate::HTTPError.new_by_code(res_obj.code, req_obj, res_obj, [{ 'message' => res_obj.body }])
  end
end
require_version(compare) click to toggle source
# File lib/passwordstate/client.rb, line 76
def require_version(compare)
  raise "Your version of Passwordstate (#{version}) doesn't support the requested feature" unless version? compare
end
timeout=(sec) click to toggle source
# File lib/passwordstate/client.rb, line 32
def timeout=(sec)
  @timeout = sec
  @http.read_timeout = sec if @http
end
valid?() click to toggle source
# File lib/passwordstate/client.rb, line 56
def valid?
  version
  true
rescue StandardError
  false
end
version() click to toggle source
# File lib/passwordstate/client.rb, line 63
def version
  @version ||= begin
    html = request(:get, '', allow_html: true)
    version = html.find_line { |line| line.include? '<span>V</span>' }
    version = />(\d\.\d) \(Build (.+)\)</.match(version)
    "#{version[1]}.#{version[2]}"
  end
end
version?(compare) click to toggle source
# File lib/passwordstate/client.rb, line 72
def version?(compare)
  Gem::Dependency.new(to_s, compare).match?(to_s, version)
end

Private Instance Methods

http() click to toggle source
# File lib/passwordstate/client.rb, line 123
def http
  @http ||= Net::HTTP.new server_url.host, server_url.port
  return @http if @http.active?

  @http.read_timeout = @timeout if @timeout
  @http.use_ssl = server_url.scheme == 'https'
  @http.verify_mode = validate_certificate ? ::OpenSSL::SSL::VERIFY_NONE : nil
  @http.start
end
print_http(http, truncate = true) click to toggle source