Class: PauboxRails::Forms::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/paubox_rails/forms/client.rb

Constant Summary collapse

UPDATABLE_FORM_KEYS =
%i[title description form_json vanity_url recipient active subscription_list_id].freeze
UUID_PATTERN =
/\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/.freeze
DEFAULT_OPEN_TIMEOUT =

Net::HTTP has no default socket timeouts — a black-holed connection can hang for the TCP stack default (~2 minutes) rather than raising promptly. These are deliberately generous for CSV/PDF exports; a caller with tighter latency budgets can still wrap the call in its own Timeout.

10
DEFAULT_READ_TIMEOUT =
60

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key: ENV.fetch('PAUBOX_FORMS_API_KEY', nil)) ⇒ Client

Returns a new instance of Client.



21
22
23
# File 'lib/paubox_rails/forms/client.rb', line 21

def initialize(api_key: ENV.fetch('PAUBOX_FORMS_API_KEY', nil))
  @api_key = api_key
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



19
20
21
# File 'lib/paubox_rails/forms/client.rb', line 19

def api_key
  @api_key
end

Instance Method Details

#archive_form(form_id) ⇒ Object



110
111
112
113
# File 'lib/paubox_rails/forms/client.rb', line 110

def archive_form(form_id)
  form_id = path_segment!(form_id, 'form_id')
  authenticated_post("/api/forms/#{form_id}/archive")
end

#copy_form(form_id, title:) ⇒ Object

copy_form's form_id is a JSON body field, not a URL path segment, so the path-splicing risk does not apply. The server owns the shape check.



122
123
124
# File 'lib/paubox_rails/forms/client.rb', line 122

def copy_form(form_id, title:)
  authenticated_post('/api/forms/copy', body: { form_id: form_id, title: title })
end

#create_form(title:, form_json:, customer_id:, version:, description: nil, form_html: nil, form_css: nil, recipient: nil, signable: nil, signature_confirmation_label: nil, subscription_list_id: nil, type: nil, active: nil, submission_count: nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/paubox_rails/forms/client.rb', line 63

def create_form(title:, form_json:, customer_id:, version:, description: nil,
                form_html: nil, form_css: nil, recipient: nil, signable: nil,
                signature_confirmation_label: nil, subscription_list_id: nil,
                type: nil, active: nil, submission_count: nil)
  payload = {
    title: title,
    form_json: form_json,
    customer_id: customer_id,
    version: version,
    description: description,
    form_html: form_html,
    form_css: form_css,
    recipient: recipient,
    signable: signable,
    signature_confirmation_label: signature_confirmation_label,
    subscription_list_id: subscription_list_id,
    type: type,
    active: active,
    submission_count: submission_count
  }.reject { |_key, value| value.nil? }

  authenticated_post('/api/forms', body: payload)
end

#form_stats(customer_id: nil) ⇒ Object



126
127
128
129
# File 'lib/paubox_rails/forms/client.rb', line 126

def form_stats(customer_id: nil)
  query = build_query(customer_id: customer_id)
  authenticated_get("/api/forms/stats#{query}")
end

#get_form(form_id) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/paubox_rails/forms/client.rb', line 25

def get_form(form_id)
  # require_uuid: false — the public endpoint predates 0.3.0 and may have
  # existing callers passing non-UUID ids; rejecting anything but UUID
  # here would be a breaking change. Percent-encoding + dot-segment
  # rejection still closes the path-splicing vector for this call.
  form_id = path_segment!(form_id, 'form_id', require_uuid: false)
  uri = URI.parse("#{BASE_URL}/public/form_data/#{form_id}")
  http = build_http(uri)
  response = http.get(uri.path)
  handle_response(response)
end

#get_form_details(form_id) ⇒ Object



87
88
89
90
# File 'lib/paubox_rails/forms/client.rb', line 87

def get_form_details(form_id)
  form_id = path_segment!(form_id, 'form_id')
  authenticated_get("/api/forms/#{form_id}")
end

#list_forms(customer_id:, form_id: nil, search: nil, order: nil, order_by: nil, archived: nil, active: nil, page: nil, items: nil) ⇒ Object

customer_id is required: the Forms API authorizes list requests by comparing the provided customer_id against the API key's customer (or a related customer), and rejects requests without one with 403 Forbidden.



55
56
57
58
59
60
61
# File 'lib/paubox_rails/forms/client.rb', line 55

def list_forms(customer_id:, form_id: nil, search: nil, order: nil, order_by: nil,
               archived: nil, active: nil, page: nil, items: nil)
  query = build_query(customer_id: customer_id, form_id: form_id, search: search,
                      order: order, order_by: order_by, archived: archived,
                      active: active, page: page, items: items)
  authenticated_get("/api/forms#{query}")
end

#list_submissions(form_id, page: nil, items: nil, order: nil, order_by: nil, submission_id: nil) ⇒ Object



131
132
133
134
135
136
137
138
# File 'lib/paubox_rails/forms/client.rb', line 131

def list_submissions(form_id, page: nil, items: nil, order: nil, order_by: nil, submission_id: nil)
  form_id = path_segment!(form_id, 'form_id')
  # submission_id here is a query param, not a URL path segment —
  # URI.encode_www_form takes care of encoding it.
  query = build_query(page: page, items: items, order: order,
                      order_by: order_by, submission_id: submission_id)
  authenticated_get("/api/forms/#{form_id}/submissions#{query}")
end

#submission_pdf(form_id, submission_id) ⇒ Object



150
151
152
153
154
# File 'lib/paubox_rails/forms/client.rb', line 150

def submission_pdf(form_id, submission_id)
  form_id = path_segment!(form_id, 'form_id')
  submission_id = path_segment!(submission_id, 'submission_id')
  authenticated_get("/api/forms/#{form_id}/submissions/#{submission_id}/submission-pdf", raw: true)
end

#submissions_csv(form_id, submission_id: nil) ⇒ Object



140
141
142
143
144
145
146
147
148
# File 'lib/paubox_rails/forms/client.rb', line 140

def submissions_csv(form_id, submission_id: nil)
  form_id = path_segment!(form_id, 'form_id')
  path = "/api/forms/#{form_id}/submissions/submission-csv"
  if submission_id
    submission_id = path_segment!(submission_id, 'submission_id')
    path += "/#{submission_id}"
  end
  authenticated_get(path, raw: true)
end

#submit_form(form_id, form_data:, attachments: nil) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/paubox_rails/forms/client.rb', line 37

def submit_form(form_id, form_data:, attachments: nil)
  form_id = path_segment!(form_id, 'form_id', require_uuid: false)
  uri = URI.parse("#{BASE_URL}/api/forms/#{form_id}/submissions")
  http = build_http(uri)

  payload = { form_data: form_data }
  payload[:attachments] = attachments if attachments

  request = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
  request.body = payload.to_json

  response = http.request(request)
  handle_response(response)
end

#unarchive_form(form_id) ⇒ Object



115
116
117
118
# File 'lib/paubox_rails/forms/client.rb', line 115

def unarchive_form(form_id)
  form_id = path_segment!(form_id, 'form_id')
  authenticated_post("/api/forms/#{form_id}/unarchive")
end

#update_form(form_id, **attrs) ⇒ Object

The server treats a JSON null the same as omitting the key ("leave unchanged"), so nil values are dropped rather than sent — fields cannot be cleared via this endpoint.



95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/paubox_rails/forms/client.rb', line 95

def update_form(form_id, **attrs)
  form_id = path_segment!(form_id, 'form_id')
  payload = attrs.slice(*UPDATABLE_FORM_KEYS).reject { |_key, value| value.nil? }

  require_api_key!
  uri = URI.parse("#{BASE_URL}/api/forms/#{form_id}")
  http = build_http(uri)

  request = Net::HTTP::Put.new(uri.path, auth_headers('Content-Type' => 'application/json'))
  request.body = payload.to_json

  response = http.request(request)
  handle_response(response)
end