Module: ZeroClick::Sellers::Stateful::Responses

Defined in:
lib/zeroclick/sellers/stateful/responses.rb

Overview

The exact responses ZeroClick expects from the stateful routes.

Class Method Summary collapse

Class Method Details

.auth_error_response(code) ⇒ Object



16
17
18
# File 'lib/zeroclick/sellers/stateful/responses.rb', line 16

def auth_error_response(code)
  Response.json({ "error" => code }, status: 401)
end

.mint_response(api_key:, max_keys: nil, key_expires_at: nil) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/zeroclick/sellers/stateful/responses.rb', line 51

def mint_response(api_key:, max_keys: nil, key_expires_at: nil)
  unless api_key.is_a?(String) && !api_key.empty?
    raise Error.new("malformed_input", operation: "mint_response",
                                       message: "api_key must be a non-empty string")
  end
  if !max_keys.nil? &&
     (max_keys.is_a?(TrueClass) || max_keys.is_a?(FalseClass) || !max_keys.is_a?(Integer) || max_keys <= 0)
    raise Error.new("malformed_input", operation: "mint_response",
                                       message: "max_keys must be a positive integer")
  end
  if !key_expires_at.nil? && !Contracts.iso_datetime?(key_expires_at)
    raise Error.new("malformed_input", operation: "mint_response",
                                       message: "key_expires_at must be an ISO datetime with a zone")
  end

  body = { "apiKey" => api_key }
  body["maxKeys"] = max_keys unless max_keys.nil?
  body["keyExpiresAt"] = key_expires_at unless key_expires_at.nil?

  # A freshly minted credential must not sit in any cache.
  Response.json(body, headers: { "cache-control" => "no-store" })
end

.retry_hint(value, operation) ⇒ Object

Non-positive hints are dropped rather than rejected — a handler saying "retry in 0 seconds" means "no hint". Anything that is not an integer is a handler bug and raises.



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/zeroclick/sellers/stateful/responses.rb', line 27

def retry_hint(value, operation)
  return nil if value.nil?

  value = value.to_i if value.is_a?(Float) && value.finite? && (value % 1).zero?
  if value.is_a?(TrueClass) || value.is_a?(FalseClass) || !value.is_a?(Integer)
    raise Error.new("malformed_input", operation: operation,
                                       message: "retry_after_seconds must be an integer")
  end

  value.positive? ? value : nil
end

.seller_unavailable_responseObject



20
21
22
# File 'lib/zeroclick/sellers/stateful/responses.rb', line 20

def seller_unavailable_response
  Response.json({ "error" => "seller_unavailable" }, status: 503)
end

.upsert_response(lifecycle:, retry_after_seconds: nil) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zeroclick/sellers/stateful/responses.rb', line 39

def upsert_response(lifecycle:, retry_after_seconds: nil)
  unless ACCESS_LIFECYCLES.include?(lifecycle)
    raise Error.new("malformed_input", operation: "upsert_response",
                                       message: "lifecycle must be provisioning or active")
  end

  body = { "lifecycle" => lifecycle }
  hint = retry_hint(retry_after_seconds, "upsert_response")
  body["retryAfterSeconds"] = hint unless hint.nil?
  Response.json(body)
end