class Keycard::Request::Attributes

Base class for extracting attributes from a Rack request.

This provides the interface for attribute extraction, independent of how the application is served and accessed. It is not intended to be used directly; you should use {AttributesFactory} to create an appropriate subclass based on configuration.

The overall design is that a subclass will extract various attributes from the request headers and environment, and a set of attribute finders may be supplied to examine the base set and add additional attributes.

Constants

IDENTITY_ATTRS

Attributes

finders[R]
request[R]

Public Class Methods

new(request, finders: []) click to toggle source
# File lib/keycard/request/attributes.rb, line 17
def initialize(request, finders: [])
  @request = request
  @finders = finders
end

Public Instance Methods

[](attr) click to toggle source
# File lib/keycard/request/attributes.rb, line 74
def [](attr)
  all[attr]
end
all() click to toggle source
# File lib/keycard/request/attributes.rb, line 78
def all
  base.merge!(external).delete_if { |_k, v| v.nil? || v == '' }
end
auth_token() click to toggle source

The token supplied by the user via auth_param according to RFC 7235. Typically, this is the API token.

# File lib/keycard/request/attributes.rb, line 57
def auth_token
  Keycard::Token.rfc7235(safe('HTTP_AUTHORIZATION'))
end
base() click to toggle source

The set of base attributes for this request.

Subclasses should implement user_pid, user_eid, and client_ip and include them in the hash under those keys.

# File lib/keycard/request/attributes.rb, line 65
def base
  {
    user_pid: user_pid,
    user_eid: user_eid,
    client_ip: client_ip,
    auth_token: auth_token
  }
end
client_ip() click to toggle source

The user's IP address.

This will be a string version of the IP address of the client, whether or not they have been proxied.

# File lib/keycard/request/attributes.rb, line 51
def client_ip
  nil
end
external() click to toggle source
# File lib/keycard/request/attributes.rb, line 82
def external
  finders
    .map        { |finder| finder.attributes_for(self) }
    .reduce({}) { |hash, attrs| hash.merge!(attrs) }
end
identity() click to toggle source
# File lib/keycard/request/attributes.rb, line 88
def identity
  all.select { |k, _v| identity_keys.include?(k.to_sym) }
end
identity_keys() click to toggle source
# File lib/keycard/request/attributes.rb, line 96
def identity_keys
  @identity_keys ||= IDENTITY_ATTRS + finders.map(&:identity_keys).flatten
end
supplemental() click to toggle source
# File lib/keycard/request/attributes.rb, line 92
def supplemental
  all.reject { |k, _v| identity_keys.include?(k.to_sym) }
end
user_eid() click to toggle source

The user's enterprise identifier.

If the client has authenticated as a user and the identity provider has releases one, this will be the “enterprise” identifier, some string that is useful for display and resolving to a person. It will tend to be something recognizable to that person, such as a network ID or email address. It may be helpful for displaying who is logged in or looking up directory information, for example. It should not be assumed to be permanent; that is, the EID may change for a person (and PID), so this should not used as a database key, for example.

# File lib/keycard/request/attributes.rb, line 43
def user_eid
  nil
end
user_pid() click to toggle source

The user's persistent identifier.

If the client has authenticated as a user, this will be a peristent identifier suitable as a key for an application account. It is expressly opaque, meaning that it cannot be assumed to be resolvable to a person or be useful for display purposes. It can be relied on to be stable for the same person as the identity provider determines that.

# File lib/keycard/request/attributes.rb, line 29
def user_pid
  nil
end

Private Instance Methods

get(key) click to toggle source

Retrieve the value from the request's environment for a given key.

This will trim whitespace and yield nil for empty values or those with the special value of '(null)'. Use {#safe} if you always want a string.

@return [String|nil] value for the key, filtered and trimmed to nil

# File lib/keycard/request/attributes.rb, line 108
def get(key)
  scrub request.env[key]
end
safe(key) click to toggle source

Retrieve a guaranteed string value from the request's environment for a given key.

This has the same behavior as {#get}, except that it will coalesce missing values to an empty string, convenient if you need to do string operations like splitting the value.

# File lib/keycard/request/attributes.rb, line 118
def safe(key)
  get(key) || ''
end
scrub(value) click to toggle source

Scrub a value to remove whitespace, filter the special '(null)' value, and translate resulting empty strings to nil.

# File lib/keycard/request/attributes.rb, line 124
def scrub(value)
  str = (value || '').strip
  case str
  when nil, '(null)', ''
    nil
  else
    str
  end
end