add more api endpoints

pull/133/head
DocuSeal 2 years ago
parent 872fbbc875
commit 1f41807412

@ -3,6 +3,12 @@
module Api
class ApiBaseController < ActionController::API
include ActiveStorage::SetCurrent
include Pagy::Backend
DEFAULT_LIMIT = 10
MAX_LIMIT = 100
wrap_parameters false
before_action :authenticate_user!
check_authorization
@ -17,6 +23,16 @@ module Api
private
def paginate(relation)
result = relation.order(id: :desc)
.limit([params[:limit] || DEFAULT_LIMIT, MAX_LIMIT].min)
result = result.where('id < ?', params[:after]) if params[:after].present?
result = result.where('id > ?', params[:before]) if params[:before].present?
result
end
def current_account
current_user&.account
end

@ -2,12 +2,52 @@
module Api
class SubmissionsController < ApiBaseController
load_and_authorize_resource :template
load_and_authorize_resource :template, only: :create
load_and_authorize_resource :submission, only: %i[show index]
before_action do
before_action only: :create do
authorize!(:create, Submission)
end
def index
submissions = Submissions.search(@submissions, params[:q])
submissions = submissions.where(template_id: params[:template_id]) if params[:template_id].present?
submissions = paginate(submissions.preload(:created_by_user, :template, :submitters))
render json: {
data: submissions.as_json(serialize_params),
pagination: {
count: submissions.size,
next: submissions.last&.id,
prev: submissions.first&.id
}
}
end
def show
serialized_subbmitters =
@submission.submitters.preload(documents_attachments: :blob, attachments_attachments: :blob).map do |submitter|
Submissions::EnsureResultGenerated.call(submitter) if submitter.completed_at?
Submitters::SerializeForApi.call(submitter)
end
json = @submission.as_json(
serialize_params.deep_merge(
include: {
submission_events: {
only: %i[id submitter_id event_type event_timestamp]
}
}
)
)
json[:submitters] = serialized_subbmitters
render json:
end
def create
is_send_email = !params[:send_email].in?(['false', false])
@ -42,8 +82,28 @@ module Api
render json: { error: e.message }, status: :unprocessable_entity
end
def destroy
@submission.update!(deleted_at: Time.current)
render json: @submission.as_json(only: %i[id deleted_at])
end
private
def serialize_params
{
only: %i[id source submitters_order created_at updated_at],
include: {
submitters: { only: %i[id slug uuid name email phone
completed_at opened_at sent_at
created_at updated_at],
methods: %i[status] },
template: { only: %i[id name created_at updated_at] },
created_by_user: { only: %i[id email first_name last_name] }
}
}
end
def submissions_params
params.permit(submission: [{
submitters: [[:uuid, :name, :email, :role, :completed, :phone, { values: {} }]]

@ -0,0 +1,13 @@
# frozen_string_literal: true
module Api
class SubmittersController < ApiBaseController
load_and_authorize_resource :submitter
def show
Submissions::EnsureResultGenerated.call(@submitter) if @submitter.completed_at?
render json: Submitters::SerializeForApi.call(@submitter, with_template: true, with_events: true)
end
end
end

@ -5,22 +5,51 @@ module Api
load_and_authorize_resource :template
def index
render json: @templates
templates = Templates.search(@templates, params[:q])
templates = params[:archived] ? templates.archived : templates.active
templates = paginate(templates.preload(:author, documents_attachments: :blob))
render json: {
data: templates.as_json(serialize_params),
pagination: {
count: templates.size,
next: templates.last&.id,
prev: templates.first&.id
}
}
end
def show
render json: @template.as_json(include: { author: { only: %i[id email first_name last_name] },
documents: { only: %i[id uuid], methods: %i[url filename] } })
render json: @template.as_json(serialize_params)
end
def update
if (folder_name = params.dig(:template, :folder_name))
@template.folder = TemplateFolders.find_or_create_by_name(current_user, folder_name)
end
@template.update!(template_params)
render :ok
render json: @template.as_json(only: %i[id updated_at])
end
def destroy
@template.update!(deleted_at: Time.current)
render json: @template.as_json(only: %i[id deleted_at])
end
private
def serialize_params
{
include: { author: { only: %i[id email first_name last_name] },
documents: { only: %i[id uuid], methods: %i[url filename] } }
}
end
def template_params
params.require(:template).permit(:name,
schema: [%i[attachment_uuid name]],

@ -58,6 +58,7 @@ class Template < ApplicationRecord
has_many :submissions, dependent: :destroy
scope :active, -> { where(deleted_at: nil) }
scope :archived, -> { where.not(deleted_at: nil) }
private

@ -16,7 +16,7 @@
<input type="checkbox">
<div class="collapse-title text-xl font-medium">
<div>
Request signature, single submitter
Request signature, multiple submitters with default values
</div>
<div class="mt-1">
<div class="badge badge-warning badge-lg">POST</div>
@ -28,8 +28,22 @@
<% text = capture do %>curl --location '<%= api_submissions_url %>' \
--header 'X-Auth-Token: <%= current_user.access_token.token %>' \
--data-raw '{
"template_id": <%= current_account.templates.last&.id || 1 %>,
"emails": "<%= current_user.email.sub('@', '+test@') %>, <%= current_user.email.sub('@', '+test2@') %>"
"template_id": <%= current_account.templates.last&.id || 1 %>,
"submission": [
{
"submitters": [
{
"name": "John Doe",
"role": "<%= current_account.templates.last ? current_account.templates.last.submitters.first['name'] : 'First Submitter' %>",
"email": "<%= current_user.email.sub('@', '+test@') %>",
"values": {
"Form Text Field Name": "Default Value"
}
},
{ "role": "Second Submitter", "email": "<%= current_user.email.sub('@', '+test2@') %>" }
]
}
]
}'<% end.to_str %>
<span class="top-0 right-0 absolute">
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
@ -42,34 +56,20 @@
<input type="checkbox">
<div class="collapse-title text-xl font-medium">
<div>
Request signature, multiple submitters with default values
Request signature, single submitter
</div>
<div class="mt-1">
<div class="badge badge-warning badge-lg">POST</div>
<div class="badge badge-primary badge-lg"><%= api_submissions_path %></div>
<div class="badge badge-primary badge-lg"><%= api_submissions_emails_path %></div>
</div>
</div>
<div class="collapse-content" style="display: inherit">
<div class="mockup-code overflow-hidden">
<% text = capture do %>curl --location '<%= api_submissions_url %>' \
<% text = capture do %>curl --location '<%= api_submissions_emails_url %>' \
--header 'X-Auth-Token: <%= current_user.access_token.token %>' \
--data-raw '{
"template_id": <%= current_account.templates.last&.id || 1 %>,
"submission": [
{
"submitters": [
{
"name": "John Doe",
"role": "<%= current_account.templates.last ? current_account.templates.last.submitters.first['name'] : 'First Submitter' %>",
"email": "<%= current_user.email.sub('@', '+test@') %>",
"values": {
"Form Text Field Name": "Default Value"
}
},
{ "name": "Second Submitter", "email": "<%= current_user.email.sub('@', '+test2@') %>" }
]
}
]
"template_id": <%= current_account.templates.last&.id || 1 %>,
"emails": "<%= current_user.email.sub('@', '+test@') %>, <%= current_user.email.sub('@', '+test2@') %>"
}'<% end.to_str %>
<span class="top-0 right-0 absolute">
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
@ -101,5 +101,8 @@
</div>
</div>
</div>
<div class="text-center">
<%= link_to 'Open Full API reference', Docuseal::PRODUCT_URL + '/docs/api', class: 'btn btn-warning text-base mt-4 px-8', target: '_blank' %>
</div>
</div>
</div>

@ -35,9 +35,14 @@ Rails.application.routes.draw do
resources :template_folders_autocomplete, only: %i[index]
resources :submitter_email_clicks, only: %i[create]
resources :submitter_form_views, only: %i[create]
resources :submissions, only: %i[create]
resources :templates, only: %i[update show index] do
resources :submissions, only: %i[create]
resources :submitters, only: %i[show]
resources :submissions, only: %i[index show create destroy] do
collection do
resources :emails, only: %i[create], controller: 'submissions', as: :submissions_emails
end
end
resources :templates, only: %i[update show index destroy] do
resources :submissions, only: %i[index create]
resources :documents, only: %i[create], controller: 'templates_documents'
end
end

@ -0,0 +1,38 @@
# frozen_string_literal: true
module Submitters
module SerializeForApi
module_function
def call(submitter, with_template: false, with_events: false)
ActiveRecord::Associations::Preloader.new(
records: [submitter],
associations: [documents_attachments: :blob, attachments_attachments: :blob]
).call
values = SerializeForWebhook.build_values_array(submitter)
documents = SerializeForWebhook.build_documents_array(submitter)
submitter_name = (submitter.submission.template_submitters ||
submitter.submission.template.submitters).find { |e| e['uuid'] == submitter.uuid }['name']
serialize_params = {
include: {},
only: %i[id slug uuid name email phone completed_at
opened_at sent_at created_at updated_at]
}
serialize_params[:include][:template] = { only: %i[id name created_at updated_at] } if with_template
if with_events
serialize_params[:include][:submission_events] =
{ as: :events, only: %i[id submitter_id event_type event_timestamp] }
end
submitter.as_json(serialize_params)
.merge('values' => values,
'documents' => documents,
'role' => submitter_name)
end
end
end

@ -5,6 +5,11 @@ module Submitters
module_function
def call(submitter)
ActiveRecord::Associations::Preloader.new(
records: [submitter],
associations: [documents_attachments: :blob, attachments_attachments: :blob]
).call
values = build_values_array(submitter)
documents = build_documents_array(submitter)
@ -21,7 +26,7 @@ module Submitters
def build_values_array(submitter)
fields_index = (submitter.submission.template_fields ||
submitter.submission.template.fields).index_by { |e| e['uuid'] }
attachments_index = submitter.attachments.preload(:blob).index_by(&:uuid)
attachments_index = submitter.attachments.index_by(&:uuid)
submitter_field_counters = Hash.new { 0 }
submitter.values.map do |uuid, value|
@ -38,7 +43,7 @@ module Submitters
end
def build_documents_array(submitter)
submitter.documents.preload(:blob).map do |attachment|
submitter.documents.map do |attachment|
{ name: attachment.filename.base, url: rails_storage_proxy_url(attachment) }
end
end

Loading…
Cancel
Save