add submission update api
This commit is contained in:
@@ -7,7 +7,7 @@ module Api
|
|||||||
TEMPLATE_COLUMNS = %i[id name external_id created_at updated_at folder_id submitters].freeze
|
TEMPLATE_COLUMNS = %i[id name external_id created_at updated_at folder_id submitters].freeze
|
||||||
|
|
||||||
load_and_authorize_resource :template, only: :create
|
load_and_authorize_resource :template, only: :create
|
||||||
load_and_authorize_resource :submission, only: %i[show index destroy]
|
load_and_authorize_resource :submission, only: %i[show index update destroy]
|
||||||
|
|
||||||
before_action only: :create do
|
before_action only: :create do
|
||||||
authorize!(:create, Submission)
|
authorize!(:create, Submission)
|
||||||
@@ -104,6 +104,25 @@ module Api
|
|||||||
render json: { error: e.message }, status: :unprocessable_content
|
render json: { error: e.message }, status: :unprocessable_content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@submission = assign_submission_attrs(@submission, submission_params)
|
||||||
|
|
||||||
|
@submission.save!
|
||||||
|
|
||||||
|
if @submission.saved_change_to_archived_at? && @submission.archived_at?
|
||||||
|
WebhookUrls.enqueue_events(@submission, 'submission.archived')
|
||||||
|
end
|
||||||
|
|
||||||
|
if @submission.saved_change_to_expire_at? && @submission.expire_at?
|
||||||
|
ProcessSubmissionExpiredJob.perform_at(@submission.expire_at, 'submission_id' => @submission.id,
|
||||||
|
'expire_at' => @submission.expire_at.to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
SearchEntries.enqueue_reindex(@submission) if @submission.saved_change_to_name?
|
||||||
|
|
||||||
|
render json: Submissions::SerializeForApi.call(@submission, nil, params, with_events: false)
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
if params[:permanently].in?(['true', true])
|
if params[:permanently].in?(['true', true])
|
||||||
@submission.destroy!
|
@submission.destroy!
|
||||||
@@ -118,6 +137,25 @@ module Api
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def assign_submission_attrs(submission, attrs)
|
||||||
|
archived = attrs.key?(:archived) ? attrs[:archived] : attrs[:archived_at]
|
||||||
|
|
||||||
|
if archived.in?([true, false, 'true', 'false']) && current_ability.can?(:destroy, submission)
|
||||||
|
submission.archived_at = archived.in?(Submitters::TRUE_VALUES) ? Time.current : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
submission.name = attrs[:name] if attrs.key?(:name)
|
||||||
|
submission.expire_at = attrs[:expire_at].presence if attrs.key?(:expire_at)
|
||||||
|
|
||||||
|
submission
|
||||||
|
end
|
||||||
|
|
||||||
|
def submission_params
|
||||||
|
submission_params = params.key?(:submission) ? params.require(:submission) : params
|
||||||
|
|
||||||
|
submission_params.permit(:name, :expire_at, :archived, :archived_at)
|
||||||
|
end
|
||||||
|
|
||||||
def maybe_return_template_error
|
def maybe_return_template_error
|
||||||
return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil?
|
return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil?
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ module Api
|
|||||||
|
|
||||||
@template.update!(template_params)
|
@template.update!(template_params)
|
||||||
|
|
||||||
SearchEntries.enqueue_reindex(@template)
|
SearchEntries.enqueue_reindex(@template) if @template.saved_change_to_name?
|
||||||
|
|
||||||
WebhookUrls.enqueue_events(@template, 'template.updated')
|
WebhookUrls.enqueue_events(@template, 'template.updated')
|
||||||
|
|
||||||
|
|||||||
@@ -93,9 +93,12 @@ class StartFormController < ApplicationController
|
|||||||
|
|
||||||
SearchEntries.enqueue_reindex(submitter)
|
SearchEntries.enqueue_reindex(submitter)
|
||||||
|
|
||||||
return unless submitter.submission.expire_at?
|
expire_at = submitter.submission.expire_at
|
||||||
|
|
||||||
ProcessSubmissionExpiredJob.perform_at(submitter.submission.expire_at, 'submission_id' => submitter.submission_id)
|
return unless expire_at
|
||||||
|
|
||||||
|
ProcessSubmissionExpiredJob.perform_at(expire_at, 'submission_id' => submitter.submission_id,
|
||||||
|
'expire_at' => expire_at.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_resubmit_submitter
|
def load_resubmit_submitter
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class ProcessSubmissionExpiredJob
|
|||||||
return if submission.template&.archived_at?
|
return if submission.template&.archived_at?
|
||||||
return if submission.submitters.where.not(declined_at: nil).exists?
|
return if submission.submitters.where.not(declined_at: nil).exists?
|
||||||
return if submission.completed_at?
|
return if submission.completed_at?
|
||||||
|
return if params['expire_at'] && submission.expire_at&.to_i != params['expire_at']
|
||||||
|
|
||||||
WebhookUrls.enqueue_events(submission, 'submission.expired')
|
WebhookUrls.enqueue_events(submission, 'submission.expired')
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ Rails.application.routes.draw do
|
|||||||
resources :submitter_email_clicks, only: %i[create]
|
resources :submitter_email_clicks, only: %i[create]
|
||||||
resources :submitter_form_views, only: %i[create]
|
resources :submitter_form_views, only: %i[create]
|
||||||
resources :submitters, only: %i[index show update]
|
resources :submitters, only: %i[index show update]
|
||||||
resources :submissions, only: %i[index show create destroy] do
|
resources :submissions, only: %i[index show create update destroy] do
|
||||||
resources :documents, only: %i[index], controller: 'submission_documents'
|
resources :documents, only: %i[index], controller: 'submission_documents'
|
||||||
collection do
|
collection do
|
||||||
resources :init, only: %i[create], controller: 'submissions'
|
resources :init, only: %i[create], controller: 'submissions'
|
||||||
|
|||||||
+2
-1
@@ -132,7 +132,8 @@ module Submissions
|
|||||||
submission.save!
|
submission.save!
|
||||||
|
|
||||||
if submission.expire_at?
|
if submission.expire_at?
|
||||||
ProcessSubmissionExpiredJob.perform_at(submission.expire_at, 'submission_id' => submission.id)
|
ProcessSubmissionExpiredJob.perform_at(submission.expire_at, 'submission_id' => submission.id,
|
||||||
|
'expire_at' => submission.expire_at.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
submission
|
submission
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ module Submissions
|
|||||||
submissions.each do |submission|
|
submissions.each do |submission|
|
||||||
next unless submission.expire_at?
|
next unless submission.expire_at?
|
||||||
|
|
||||||
ProcessSubmissionExpiredJob.perform_at(submission.expire_at, 'submission_id' => submission.id)
|
ProcessSubmissionExpiredJob.perform_at(submission.expire_at, 'submission_id' => submission.id,
|
||||||
|
'expire_at' => submission.expire_at.to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe ProcessSubmissionExpiredJob do
|
||||||
|
let(:account) { create(:account) }
|
||||||
|
let(:user) { create(:user, account:) }
|
||||||
|
let(:template) { create(:template, account:, author: user) }
|
||||||
|
let(:expire_at) { 2.days.from_now.change(usec: 0) }
|
||||||
|
let(:submission) do
|
||||||
|
create(:submission, :with_submitters, template:, created_by_user: user, expire_at:)
|
||||||
|
end
|
||||||
|
|
||||||
|
before { allow(WebhookUrls).to receive(:enqueue_events) }
|
||||||
|
|
||||||
|
describe '#perform' do
|
||||||
|
it 'enqueues the expired event when the scheduled expire_at still matches' do
|
||||||
|
described_class.new.perform('submission_id' => submission.id, 'expire_at' => expire_at.to_i)
|
||||||
|
|
||||||
|
expect(WebhookUrls).to have_received(:enqueue_events).with(submission, 'submission.expired')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'enqueues the expired event for legacy jobs scheduled without an expire_at param' do
|
||||||
|
described_class.new.perform('submission_id' => submission.id)
|
||||||
|
|
||||||
|
expect(WebhookUrls).to have_received(:enqueue_events).with(submission, 'submission.expired')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'skips a stale job scheduled for an earlier expire_at that was extended' do
|
||||||
|
submission.update!(expire_at: 3.days.from_now)
|
||||||
|
|
||||||
|
described_class.new.perform('submission_id' => submission.id, 'expire_at' => expire_at.to_i)
|
||||||
|
|
||||||
|
expect(WebhookUrls).not_to have_received(:enqueue_events)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'skips a stale job scheduled for a later expire_at that was shortened' do
|
||||||
|
submission.update!(expire_at: 1.day.from_now)
|
||||||
|
|
||||||
|
described_class.new.perform('submission_id' => submission.id, 'expire_at' => expire_at.to_i)
|
||||||
|
|
||||||
|
expect(WebhookUrls).not_to have_received(:enqueue_events)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'skips a stale job when the expiration has been cleared' do
|
||||||
|
submission.update!(expire_at: nil)
|
||||||
|
|
||||||
|
described_class.new.perform('submission_id' => submission.id, 'expire_at' => expire_at.to_i)
|
||||||
|
|
||||||
|
expect(WebhookUrls).not_to have_received(:enqueue_events)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -259,6 +259,62 @@ describe 'Submission API' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'PUT /api/submissions/:id' do
|
||||||
|
it 'updates the submission name' do
|
||||||
|
submission = create(:submission, :with_submitters, template: templates[0], created_by_user: author)
|
||||||
|
|
||||||
|
put "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
|
||||||
|
name: 'Updated Name'
|
||||||
|
}.to_json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(submission.reload.name).to eq('Updated Name')
|
||||||
|
expect(response.parsed_body['name']).to eq('Updated Name')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'updates the expiration date' do
|
||||||
|
submission = create(:submission, :with_submitters, template: templates[0], created_by_user: author)
|
||||||
|
expire_at = 1.week.from_now.change(usec: 0)
|
||||||
|
|
||||||
|
put "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
|
||||||
|
expire_at: expire_at.iso8601
|
||||||
|
}.to_json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(submission.reload.expire_at).to be_within(1.second).of(expire_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'clears the expiration date when passed nil' do
|
||||||
|
submission = create(:submission, :with_submitters, template: templates[0], created_by_user: author,
|
||||||
|
expire_at: 1.week.from_now)
|
||||||
|
|
||||||
|
put "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
|
||||||
|
expire_at: nil
|
||||||
|
}.to_json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(submission.reload.expire_at).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'archives and unarchives the submission' do
|
||||||
|
submission = create(:submission, :with_submitters, template: templates[0], created_by_user: author)
|
||||||
|
|
||||||
|
put "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
|
||||||
|
archived: true
|
||||||
|
}.to_json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(submission.reload.archived_at).not_to be_nil
|
||||||
|
|
||||||
|
put "/api/submissions/#{submission.id}", headers: { 'x-auth-token': author.access_token.token }, params: {
|
||||||
|
archived: false
|
||||||
|
}.to_json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(submission.reload.archived_at).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'view-only (CC) party' do
|
describe 'view-only (CC) party' do
|
||||||
let(:viewer_template) { create(:template, account:, author:, submitter_count: 2, only_field_types: %w[text]) }
|
let(:viewer_template) { create(:template, account:, author:, submitter_count: 2, only_field_types: %w[text]) }
|
||||||
let(:viewer_uuid) { viewer_template.submitters.second['uuid'] }
|
let(:viewer_uuid) { viewer_template.submitters.second['uuid'] }
|
||||||
|
|||||||
Reference in New Issue
Block a user