diff --git a/Dockerfile b/Dockerfile index a5a8f855..1e397cf0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,7 +50,7 @@ ENV OPENSSL_CONF=/app/openssl_legacy.cnf WORKDIR /app -RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge redis libheif@edge vips-heif@edge gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf +RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge yaml-dev redis libheif@edge vips-heif@edge gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf RUN echo $'.include = /etc/ssl/openssl.cnf\n\ \n\ diff --git a/Gemfile.lock b/Gemfile.lock index df7255dd..493b46bb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,29 @@ GEM remote: https://rubygems.org/ specs: - actioncable (8.0.1) - actionpack (= 8.0.1) - activesupport (= 8.0.1) + actioncable (8.0.2.1) + actionpack (= 8.0.2.1) + activesupport (= 8.0.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.0.1) - actionpack (= 8.0.1) - activejob (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + actionmailbox (8.0.2.1) + actionpack (= 8.0.2.1) + activejob (= 8.0.2.1) + activerecord (= 8.0.2.1) + activestorage (= 8.0.2.1) + activesupport (= 8.0.2.1) mail (>= 2.8.0) - actionmailer (8.0.1) - actionpack (= 8.0.1) - actionview (= 8.0.1) - activejob (= 8.0.1) - activesupport (= 8.0.1) + actionmailer (8.0.2.1) + actionpack (= 8.0.2.1) + actionview (= 8.0.2.1) + activejob (= 8.0.2.1) + activesupport (= 8.0.2.1) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.1) - actionview (= 8.0.1) - activesupport (= 8.0.1) + actionpack (8.0.2.1) + actionview (= 8.0.2.1) + activesupport (= 8.0.2.1) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -31,35 +31,35 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.0.1) - actionpack (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + actiontext (8.0.2.1) + actionpack (= 8.0.2.1) + activerecord (= 8.0.2.1) + activestorage (= 8.0.2.1) + activesupport (= 8.0.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.0.1) - activesupport (= 8.0.1) + actionview (8.0.2.1) + activesupport (= 8.0.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.1) - activesupport (= 8.0.1) + activejob (8.0.2.1) + activesupport (= 8.0.2.1) globalid (>= 0.3.6) - activemodel (8.0.1) - activesupport (= 8.0.1) - activerecord (8.0.1) - activemodel (= 8.0.1) - activesupport (= 8.0.1) + activemodel (8.0.2.1) + activesupport (= 8.0.2.1) + activerecord (8.0.2.1) + activemodel (= 8.0.2.1) + activesupport (= 8.0.2.1) timeout (>= 0.4.0) - activestorage (8.0.1) - actionpack (= 8.0.1) - activejob (= 8.0.1) - activerecord (= 8.0.1) - activesupport (= 8.0.1) + activestorage (8.0.2.1) + actionpack (= 8.0.2.1) + activejob (= 8.0.2.1) + activerecord (= 8.0.2.1) + activesupport (= 8.0.2.1) marcel (~> 1.0) - activesupport (8.0.1) + activesupport (8.0.2.1) base64 benchmark (>= 0.3) bigdecimal @@ -104,9 +104,9 @@ GEM faraday_middleware (~> 1.0, >= 1.0.0.rc1) net-http-persistent (~> 4.0) nokogiri (~> 1, >= 1.10.8) - base64 (0.2.0) + base64 (0.3.0) bcrypt (3.1.20) - benchmark (0.4.0) + benchmark (0.4.1) better_html (2.1.1) actionview (>= 6.0) activesupport (>= 6.0) @@ -114,7 +114,7 @@ GEM erubi (~> 1.4) parser (>= 2.4) smart_properties - bigdecimal (3.1.8) + bigdecimal (3.2.2) bindex (0.8.1) bootsnap (1.18.4) msgpack (~> 1.2) @@ -141,8 +141,8 @@ GEM cldr-plurals-runtime-rb (1.1.0) cmdparse (3.0.7) coderay (1.1.3) - concurrent-ruby (1.3.4) - connection_pool (2.4.1) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) crack (1.0.0) bigdecimal rexml @@ -174,8 +174,9 @@ GEM rake (>= 12.0.0, < 14.0.0) docile (1.4.1) dotenv (3.1.7) - drb (2.2.1) + drb (2.2.3) email_typo (0.2.3) + erb (5.0.2) erb_lint (0.7.0) activesupport better_html (>= 2.0.1) @@ -276,13 +277,14 @@ GEM openssl (>= 2.2.1) htmlentities (4.3.4) httpclient (2.8.3) - i18n (1.14.6) + i18n (1.14.7) concurrent-ruby (~> 1.0) image_processing (1.13.0) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) - io-console (0.8.0) - irb (1.14.3) + io-console (0.8.1) + irb (1.15.2) + pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jmespath (1.6.2) @@ -300,13 +302,13 @@ GEM letter_opener (~> 1.9) railties (>= 6.1) rexml - logger (1.6.4) + logger (1.7.0) lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.23.1) + loofah (2.24.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -320,7 +322,7 @@ GEM mini_magick (4.13.2) mini_mime (1.1.5) mini_portile2 (2.8.9) - minitest (5.25.4) + minitest (5.25.5) msgpack (1.7.5) multi_json (1.15.0) multipart-post (2.4.1) @@ -328,14 +330,14 @@ GEM mysql2 (0.5.6) net-http-persistent (4.0.5) connection_pool (~> 2.2) - net-imap (0.5.6) + net-imap (0.5.9) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.5.0) + net-smtp (0.5.1) net-protocol nio4r (2.7.4) nokogiri (1.18.9) @@ -365,6 +367,8 @@ GEM ast (~> 2.4.1) racc pg (1.5.9) + pp (0.6.2) + prettyprint premailer (1.27.0) addressable css_parser (>= 1.19.0) @@ -375,42 +379,44 @@ GEM premailer (~> 1.7, >= 1.7.9) pretender (0.5.0) actionpack (>= 6.1) + prettyprint (0.2.0) pry (0.15.0) coderay (~> 1.1) method_source (~> 1.0) pry-rails (0.3.11) pry (>= 0.13.0) - psych (5.2.2) + psych (5.2.6) date stringio public_suffix (6.0.1) puma (6.5.0) nio4r (~> 2.0) racc (1.8.1) - rack (3.1.16) + rack (3.2.0) rack-proxy (0.7.7) rack - rack-session (2.0.0) + rack-session (2.1.1) + base64 (>= 0.1.0) rack (>= 3.0.0) - rack-test (2.1.0) + rack-test (2.2.0) rack (>= 1.3) rackup (2.2.1) rack (>= 3) - rails (8.0.1) - actioncable (= 8.0.1) - actionmailbox (= 8.0.1) - actionmailer (= 8.0.1) - actionpack (= 8.0.1) - actiontext (= 8.0.1) - actionview (= 8.0.1) - activejob (= 8.0.1) - activemodel (= 8.0.1) - activerecord (= 8.0.1) - activestorage (= 8.0.1) - activesupport (= 8.0.1) + rails (8.0.2.1) + actioncable (= 8.0.2.1) + actionmailbox (= 8.0.2.1) + actionmailer (= 8.0.2.1) + actionpack (= 8.0.2.1) + actiontext (= 8.0.2.1) + actionview (= 8.0.2.1) + activejob (= 8.0.2.1) + activemodel (= 8.0.2.1) + activerecord (= 8.0.2.1) + activestorage (= 8.0.2.1) + activesupport (= 8.0.2.1) bundler (>= 1.15.0) - railties (= 8.0.1) - rails-dom-testing (2.2.0) + railties (= 8.0.2.1) + rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) @@ -424,22 +430,23 @@ GEM actionview (> 3.1) activesupport (> 3.1) railties (> 3.1) - railties (8.0.1) - actionpack (= 8.0.1) - activesupport (= 8.0.1) + railties (8.0.2.1) + actionpack (= 8.0.2.1) + activesupport (= 8.0.2.1) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.2.1) - rdoc (6.10.0) + rake (13.3.0) + rdoc (6.14.2) + erb psych (>= 4.0.0) redis-client (0.23.0) connection_pool regexp_parser (2.9.3) - reline (0.6.0) + reline (0.6.2) io-console (~> 0.5) representable (3.2.0) declarative (< 0.1.0) @@ -538,7 +545,7 @@ GEM sqlite3 (2.5.0-arm64-darwin) sqlite3 (2.5.0-x86_64-linux-gnu) sqlite3 (2.5.0-x86_64-linux-musl) - stringio (3.1.2) + stringio (3.1.7) strip_attributes (1.14.1) activemodel (>= 3.0, < 9.0) thor (1.4.0) @@ -574,12 +581,13 @@ GEM crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) webrick (1.9.1) - websocket-driver (0.7.6) + websocket-driver (0.8.0) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.7.1) + zeitwerk (2.7.3) PLATFORMS aarch64-linux diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 5a2797ff..6409946e 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -27,7 +27,7 @@ class AccountsController < ApplicationController unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS]) @encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url')) - return render :show, status: :unprocessable_entity + return render :show, status: :unprocessable_content end @encrypted_config.save! @@ -39,7 +39,7 @@ class AccountsController < ApplicationController redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated') end rescue ActiveRecord::RecordInvalid - render :show, status: :unprocessable_entity + render :show, status: :unprocessable_content end def destroy diff --git a/app/controllers/api/api_base_controller.rb b/app/controllers/api/api_base_controller.rb index b681aa67..70b992ed 100644 --- a/app/controllers/api/api_base_controller.rb +++ b/app/controllers/api/api_base_controller.rb @@ -16,7 +16,7 @@ module Api check_authorization rescue_from Params::BaseValidator::InvalidParameterError do |e| - render json: { error: e.message }, status: :unprocessable_entity + render json: { error: e.message }, status: :unprocessable_content end rescue_from RateLimit::LimitApproached do |e| @@ -33,7 +33,7 @@ module Api rescue_from JSON::ParserError do |e| Rollbar.warning(e) if defined?(Rollbar) - render json: { error: "JSON parse error: #{e.message}" }, status: :unprocessable_entity + render json: { error: "JSON parse error: #{e.message}" }, status: :unprocessable_content end end diff --git a/app/controllers/api/attachments_controller.rb b/app/controllers/api/attachments_controller.rb index dca89f67..5051cfeb 100644 --- a/app/controllers/api/attachments_controller.rb +++ b/app/controllers/api/attachments_controller.rb @@ -16,14 +16,14 @@ module Api if ImageUtils.blank?(image) Rollbar.error("Empty signature: #{submitter.id}") if defined?(Rollbar) - return render json: { error: "#{params[:type]} is empty" }, status: :unprocessable_entity + return render json: { error: "#{params[:type]} is empty" }, status: :unprocessable_content end if ImageUtils.error?(image) Rollbar.error("Error signature: #{submitter.id}") if defined?(Rollbar) return render json: { error: "#{params[:type]} error, try to sign on another device" }, - status: :unprocessable_entity + status: :unprocessable_content end end diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index f75d7299..95ab2bda 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -50,12 +50,12 @@ module Api def create Params::SubmissionCreateValidator.call(params) - return render json: { error: 'Template not found' }, status: :unprocessable_entity if @template.nil? + return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil? if @template.fields.blank? Rollbar.warning("Template does not contain fields: #{@template.id}") if defined?(Rollbar) - return render json: { error: 'Template does not contain fields' }, status: :unprocessable_entity + return render json: { error: 'Template does not contain fields' }, status: :unprocessable_content end params[:send_email] = true unless params.key?(:send_email) @@ -82,7 +82,7 @@ module Api DownloadUtils::UnableToDownload => e Rollbar.warning(e) if defined?(Rollbar) - render json: { error: e.message }, status: :unprocessable_entity + render json: { error: e.message }, status: :unprocessable_content end def destroy diff --git a/app/controllers/api/submitters_controller.rb b/app/controllers/api/submitters_controller.rb index 70fb107f..990f11ba 100644 --- a/app/controllers/api/submitters_controller.rb +++ b/app/controllers/api/submitters_controller.rb @@ -34,7 +34,7 @@ module Api def update if @submitter.completed_at? - return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_entity + return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content end submission = @submitter.submission @@ -74,7 +74,7 @@ module Api rescue Submitters::NormalizeValues::BaseError, DownloadUtils::UnableToDownload => e Rollbar.warning(e) if defined?(Rollbar) - render json: { error: e.message }, status: :unprocessable_entity + render json: { error: e.message }, status: :unprocessable_content end def submitter_params diff --git a/app/controllers/api/tools_controller.rb b/app/controllers/api/tools_controller.rb index 63a50f89..09ea9235 100644 --- a/app/controllers/api/tools_controller.rb +++ b/app/controllers/api/tools_controller.rb @@ -7,8 +7,8 @@ module Api def merge files = params[:files] || [] - return render json: { error: 'Files are required' }, status: :unprocessable_entity if files.blank? - return render json: { error: 'At least 2 files are required' }, status: :unprocessable_entity if files.size < 2 + return render json: { error: 'Files are required' }, status: :unprocessable_content if files.blank? + return render json: { error: 'At least 2 files are required' }, status: :unprocessable_content if files.size < 2 render json: { data: Base64.encode64(PdfUtils.merge(files.map { |base64| StringIO.new(Base64.decode64(base64)) }).string) @@ -35,7 +35,7 @@ module Api end } rescue HexaPDF::MalformedPDFError - render json: { error: 'Malformed PDF' }, status: :unprocessable_entity + render json: { error: 'Malformed PDF' }, status: :unprocessable_content end end end diff --git a/app/controllers/email_smtp_settings_controller.rb b/app/controllers/email_smtp_settings_controller.rb index 766a9545..f918f172 100644 --- a/app/controllers/email_smtp_settings_controller.rb +++ b/app/controllers/email_smtp_settings_controller.rb @@ -15,12 +15,12 @@ class EmailSmtpSettingsController < ApplicationController redirect_to settings_email_index_path, notice: I18n.t('changes_have_been_saved') else - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end rescue StandardError => e flash[:alert] = e.message - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end private diff --git a/app/controllers/esign_settings_controller.rb b/app/controllers/esign_settings_controller.rb index 34feb84e..81c75fae 100644 --- a/app/controllers/esign_settings_controller.rb +++ b/app/controllers/esign_settings_controller.rb @@ -53,7 +53,7 @@ class EsignSettingsController < ApplicationController @cert_record.errors.add(:name, I18n.t('already_exists')) return render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'), - status: :unprocessable_entity + status: :unprocessable_content end save_new_cert!(@encrypted_config, @cert_record) @@ -64,7 +64,7 @@ class EsignSettingsController < ApplicationController @cert_record.errors.add(:password, e.message) - render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'), status: :unprocessable_content end def update diff --git a/app/controllers/mfa_setup_controller.rb b/app/controllers/mfa_setup_controller.rb index 6ec74ccd..2ea90412 100644 --- a/app/controllers/mfa_setup_controller.rb +++ b/app/controllers/mfa_setup_controller.rb @@ -24,7 +24,7 @@ class MfaSetupController < ApplicationController @error_message = I18n.t('code_is_invalid') - render turbo_stream: turbo_stream.replace(:mfa_form, partial: 'mfa_setup/form'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:mfa_form, partial: 'mfa_setup/form'), status: :unprocessable_content end end @@ -36,7 +36,7 @@ class MfaSetupController < ApplicationController else @error_message = I18n.t('code_is_invalid') - render turbo_stream: turbo_stream.replace(:modal, template: 'mfa_setup/edit'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:modal, template: 'mfa_setup/edit'), status: :unprocessable_content end end diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb index e0adb16e..668cd140 100644 --- a/app/controllers/profile_controller.rb +++ b/app/controllers/profile_controller.rb @@ -11,7 +11,7 @@ class ProfileController < ApplicationController if current_user.update(contact_params) redirect_to settings_profile_index_path, notice: I18n.t('contact_information_has_been_update') else - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end end @@ -20,7 +20,7 @@ class ProfileController < ApplicationController bypass_sign_in(current_user) redirect_to settings_profile_index_path, notice: I18n.t('password_has_been_changed') else - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 8a7a5e5f..2281d56f 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -16,7 +16,7 @@ class SessionsController < Devise::SessionsController end if User.exists?(email:, otp_required_for_login: true) && sign_in_params[:otp_attempt].blank? - return render :otp, locals: { resource: User.new(sign_in_params) }, status: :unprocessable_entity + return render :otp, locals: { resource: User.new(sign_in_params) }, status: :unprocessable_content end super diff --git a/app/controllers/setup_controller.rb b/app/controllers/setup_controller.rb index 778255bc..734edbb5 100644 --- a/app/controllers/setup_controller.rb +++ b/app/controllers/setup_controller.rb @@ -23,10 +23,10 @@ class SetupController < ApplicationController unless URI.parse(encrypted_config_params[:value].to_s).class.in?([URI::HTTP, URI::HTTPS]) @encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url')) - return render :index, status: :unprocessable_entity + return render :index, status: :unprocessable_content end - return render :index, status: :unprocessable_entity unless @account.valid? + return render :index, status: :unprocessable_content unless @account.valid? if @user.save encrypted_configs = [ @@ -42,7 +42,7 @@ class SetupController < ApplicationController redirect_to newsletter_path else - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end end diff --git a/app/controllers/start_form_controller.rb b/app/controllers/start_form_controller.rb index d71fba64..08778a3e 100644 --- a/app/controllers/start_form_controller.rb +++ b/app/controllers/start_form_controller.rb @@ -42,7 +42,7 @@ class StartFormController < ApplicationController if filter_undefined_submitters(@template).size > 1 && @submitter.new_record? @error_message = multiple_submitters_error_message - return render :show, status: :unprocessable_entity + return render :show, status: :unprocessable_content end if (is_new_record = @submitter.new_record?) @@ -60,7 +60,7 @@ class StartFormController < ApplicationController redirect_to submit_form_path(@submitter.slug) else - render :show, status: :unprocessable_entity + render :show, status: :unprocessable_content end end end @@ -206,7 +206,7 @@ class StartFormController < ApplicationController end def handle_require_2fa(submitter, is_new_record:) - return render :show, status: :unprocessable_entity if submitter.errors.present? + return render :show, status: :unprocessable_content if submitter.errors.present? is_otp_verified = Submitters.verify_link_otp!(params[:one_time_code], submitter) @@ -223,7 +223,7 @@ class StartFormController < ApplicationController redirect_to submit_form_path(submitter.slug) else - render :show, status: :unprocessable_entity + render :show, status: :unprocessable_content end else Submitters.send_shared_link_email_verification_code(submitter, request:) diff --git a/app/controllers/storage_settings_controller.rb b/app/controllers/storage_settings_controller.rb index 182e8ca8..4b3a8390 100644 --- a/app/controllers/storage_settings_controller.rb +++ b/app/controllers/storage_settings_controller.rb @@ -13,7 +13,7 @@ class StorageSettingsController < ApplicationController redirect_to settings_storage_index_path, notice: I18n.t('changes_have_been_saved') else - render :index, status: :unprocessable_entity + render :index, status: :unprocessable_content end end diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 4f31322c..7dc689e0 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -66,7 +66,7 @@ class SubmissionsController < ApplicationController rescue Submissions::CreateFromSubmitters::BaseError => e render turbo_stream: turbo_stream.replace(:submitters_error, partial: 'submissions/error', locals: { error: e.message }), - status: :unprocessable_entity + status: :unprocessable_content end def destroy diff --git a/app/controllers/submit_form_controller.rb b/app/controllers/submit_form_controller.rb index 44d10445..f7bf565e 100644 --- a/app/controllers/submit_form_controller.rb +++ b/app/controllers/submit_form_controller.rb @@ -48,20 +48,20 @@ class SubmitFormController < ApplicationController def update if @submitter.completed_at? - return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_entity + return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_content end if @submitter.submission.template&.archived_at? || @submitter.submission.archived_at? - return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_entity + return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_content end if @submitter.submission.expired? - return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_entity + return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_content end if @submitter.declined_at? return render json: { error: I18n.t('form_has_been_declined') }, - status: :unprocessable_entity + status: :unprocessable_content end Submitters::SubmitValues.call(@submitter, params, request) @@ -70,9 +70,9 @@ class SubmitFormController < ApplicationController rescue Submitters::SubmitValues::RequiredFieldError => e Rollbar.warning("Required field #{@submitter.id}: #{e.message}") if defined?(Rollbar) - render json: { field_uuid: e.message }, status: :unprocessable_entity + render json: { field_uuid: e.message }, status: :unprocessable_content rescue Submitters::SubmitValues::ValidationError => e - render json: { error: e.message }, status: :unprocessable_entity + render json: { error: e.message }, status: :unprocessable_content end def completed; end diff --git a/app/controllers/submit_form_download_controller.rb b/app/controllers/submit_form_download_controller.rb index d357019c..d6e0b692 100644 --- a/app/controllers/submit_form_download_controller.rb +++ b/app/controllers/submit_form_download_controller.rb @@ -11,13 +11,13 @@ class SubmitFormDownloadController < ApplicationController return redirect_to submitter_download_index_path(@submitter.slug) if @submitter.completed_at? - return head :unprocessable_entity if @submitter.declined_at? || - @submitter.submission.archived_at? || - @submitter.submission.expired? || - @submitter.submission.template&.archived_at? || - AccountConfig.exists?(account_id: @submitter.account_id, - key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY, - value: false) + return head :unprocessable_content if @submitter.declined_at? || + @submitter.submission.archived_at? || + @submitter.submission.expired? || + @submitter.submission.template&.archived_at? || + AccountConfig.exists?(account_id: @submitter.account_id, + key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY, + value: false) last_completed_submitter = @submitter.submission.submitters .where.not(id: @submitter.id) diff --git a/app/controllers/submit_form_invite_controller.rb b/app/controllers/submit_form_invite_controller.rb index 0f400ad9..ab1f26c3 100644 --- a/app/controllers/submit_form_invite_controller.rb +++ b/app/controllers/submit_form_invite_controller.rb @@ -7,7 +7,7 @@ class SubmitFormInviteController < ApplicationController def create submitter = Submitter.find_by!(slug: params[:submit_form_slug]) - return head :unprocessable_entity unless can_invite?(submitter) + return head :unprocessable_content unless can_invite?(submitter) invite_submitters = filter_invite_submitters(submitter, 'invite_by_uuid') optional_invite_submitters = filter_invite_submitters(submitter, 'optional_invite_by_uuid') @@ -34,7 +34,7 @@ class SubmitFormInviteController < ApplicationController head :ok else - head :unprocessable_entity + head :unprocessable_content end end diff --git a/app/controllers/template_documents_controller.rb b/app/controllers/template_documents_controller.rb index abd72010..cfca1297 100644 --- a/app/controllers/template_documents_controller.rb +++ b/app/controllers/template_documents_controller.rb @@ -5,7 +5,7 @@ class TemplateDocumentsController < ApplicationController def create if params[:blobs].blank? && params[:files].blank? - return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_entity + return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_content end old_fields_hash = @template.fields.hash @@ -28,6 +28,6 @@ class TemplateDocumentsController < ApplicationController ) } rescue Templates::CreateAttachments::PdfEncrypted - render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_entity + render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_content end end diff --git a/app/controllers/templates_clone_and_replace_controller.rb b/app/controllers/templates_clone_and_replace_controller.rb index 21989067..f4acfd3f 100644 --- a/app/controllers/templates_clone_and_replace_controller.rb +++ b/app/controllers/templates_clone_and_replace_controller.rb @@ -4,7 +4,7 @@ class TemplatesCloneAndReplaceController < ApplicationController load_and_authorize_resource :template def create - return head :unprocessable_entity if params[:files].blank? + return head :unprocessable_content if params[:files].blank? ActiveRecord::Associations::Preloader.new( records: [@template], @@ -31,7 +31,7 @@ class TemplatesCloneAndReplaceController < ApplicationController rescue Templates::CreateAttachments::PdfEncrypted respond_to do |f| f.html { render turbo_stream: turbo_stream.append(params[:form_id], html: helpers.tag.prompt_password) } - f.json { render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_entity } + f.json { render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_content } end end end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index a3d78606..3af0a0f2 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -78,7 +78,7 @@ class TemplatesController < ApplicationController maybe_redirect_to_template(@template) else - render turbo_stream: turbo_stream.replace(:modal, template: 'templates/new'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:modal, template: 'templates/new'), status: :unprocessable_content end end diff --git a/app/controllers/templates_debug_controller.rb b/app/controllers/templates_debug_controller.rb index 810c042a..676c2f64 100644 --- a/app/controllers/templates_debug_controller.rb +++ b/app/controllers/templates_debug_controller.rb @@ -3,6 +3,8 @@ class TemplatesDebugController < ApplicationController load_and_authorize_resource :template + DEBUG_FILE = '' + def show attachment = @template.documents.first @@ -16,6 +18,8 @@ class TemplatesDebugController < ApplicationController @template.update!(fields: Templates::ProcessDocument.normalize_attachment_fields(@template, [attachment])) + debug_file if DEBUG_FILE.present? + ActiveRecord::Associations::Preloader.new( records: [@template], associations: [schema_documents: { preview_images_attachments: :blob }] @@ -31,4 +35,27 @@ class TemplatesDebugController < ApplicationController render 'templates/edit', layout: 'plain' end + + def debug_file + tempfile = Tempfile.new + tempfile.binmode + tempfile.write(File.read(DEBUG_FILE)) + tempfile.rewind + + filename = File.basename(DEBUG_FILE) + + file = ActionDispatch::Http::UploadedFile.new( + tempfile:, + filename:, + type: Marcel::MimeType.for(tempfile) + ) + + params = { files: [file] } + + documents = Templates::CreateAttachments.call(@template, params) + + schema = documents.map { |doc| { attachment_uuid: doc.uuid, name: doc.filename.base } } + + @template.update!(schema:) + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9771fc4e..8f433577 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -27,7 +27,7 @@ class UsersController < ApplicationController if User.accessible_by(current_ability).exists?(email: @user.email) @user.errors.add(:email, I18n.t('already_exists')) - return render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity + return render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_content end @user.role = User::ADMIN_ROLE unless role_valid?(@user.role) @@ -37,7 +37,7 @@ class UsersController < ApplicationController redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_invited') else - render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_content end end @@ -57,7 +57,7 @@ class UsersController < ApplicationController if @user.update(attrs.except(current_user == @user ? :role : nil)) redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_updated') else - render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_entity + render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_content end end diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index cd2339f4..ad295068 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -660,7 +660,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' }, baseUrl: { type: String, diff --git a/app/javascript/template_builder/controls.vue b/app/javascript/template_builder/controls.vue index 270aa623..2196fe56 100644 --- a/app/javascript/template_builder/controls.vue +++ b/app/javascript/template_builder/controls.vue @@ -66,7 +66,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' }, withReplaceButton: { type: Boolean, diff --git a/app/javascript/template_builder/dropzone.vue b/app/javascript/template_builder/dropzone.vue index 9031f3d1..ff30e756 100644 --- a/app/javascript/template_builder/dropzone.vue +++ b/app/javascript/template_builder/dropzone.vue @@ -107,7 +107,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' } }, emits: ['success', 'error', 'loading'], @@ -131,7 +131,7 @@ export default { message () { if (this.isLoading) { return this.t('uploading') - } else if (this.acceptFileTypes === 'image/*, application/pdf') { + } else if (this.acceptFileTypes === 'image/*, application/pdf, application/zip') { return this.title || this.t('add_pdf_documents_or_images') } else { return this.title || this.t('add_documents_or_images') @@ -146,7 +146,7 @@ export default { methods: { upload: Upload.methods.upload, onDropFiles (e) { - if (this.acceptFileTypes !== 'image/*, application/pdf' || [...e.dataTransfer.files].every((f) => f.type.match(/(?:image\/)|(?:application\/pdf)/))) { + if (this.acceptFileTypes !== 'image/*, application/pdf, application/zip' || [...e.dataTransfer.files].every((f) => f.type.match(/(?:image\/)|(?:application\/pdf)|(?:application\/zip)/))) { this.$refs.input.files = e.dataTransfer.files this.upload() diff --git a/app/javascript/template_builder/hover_dropzone.vue b/app/javascript/template_builder/hover_dropzone.vue index 575c832c..28a07281 100644 --- a/app/javascript/template_builder/hover_dropzone.vue +++ b/app/javascript/template_builder/hover_dropzone.vue @@ -78,7 +78,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' } }, emits: ['add', 'replace', 'replace-and-clone', 'error'], diff --git a/app/javascript/template_builder/preview.vue b/app/javascript/template_builder/preview.vue index 7a60d71e..c83f58f7 100644 --- a/app/javascript/template_builder/preview.vue +++ b/app/javascript/template_builder/preview.vue @@ -157,7 +157,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' }, withReplaceButton: { type: Boolean, diff --git a/app/javascript/template_builder/replace.vue b/app/javascript/template_builder/replace.vue index 6a467206..bc72b4f0 100644 --- a/app/javascript/template_builder/replace.vue +++ b/app/javascript/template_builder/replace.vue @@ -35,7 +35,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' } }, emits: ['success'], diff --git a/app/javascript/template_builder/upload.vue b/app/javascript/template_builder/upload.vue index a502ff3e..bdb633ce 100644 --- a/app/javascript/template_builder/upload.vue +++ b/app/javascript/template_builder/upload.vue @@ -57,7 +57,7 @@ export default { acceptFileTypes: { type: String, required: false, - default: 'image/*, application/pdf' + default: 'image/*, application/pdf, application/zip' } }, emits: ['success', 'error'], diff --git a/app/jobs/process_submitter_completion_job.rb b/app/jobs/process_submitter_completion_job.rb index 647aab5f..49f79fcf 100644 --- a/app/jobs/process_submitter_completion_job.rb +++ b/app/jobs/process_submitter_completion_job.rb @@ -146,7 +146,8 @@ class ProcessSubmitterCompletionJob current_group_index = submitter_groups.find { |_, group| group.any? { |s| s['uuid'] == submitter.uuid } }&.first if submitter_groups[current_group_index + 1] && - submitters_index.values_at(*submitter_groups[current_group_index].pluck('uuid')).all?(&:completed_at?) + submitters_index.values_at(*submitter_groups[current_group_index].pluck('uuid')) + .compact.all?(&:completed_at?) submitter_groups[current_group_index + 1] end else @@ -159,7 +160,7 @@ class ProcessSubmitterCompletionJob end end - next_submitters = submitters_index.values_at(*Array.wrap(next_submitter_items).pluck('uuid')) + next_submitters = submitters_index.values_at(*Array.wrap(next_submitter_items).pluck('uuid')).compact Submitters.send_signature_requests(next_submitters) end diff --git a/app/views/submissions/show.html.erb b/app/views/submissions/show.html.erb index 0ab61c68..eb1999e1 100644 --- a/app/views/submissions/show.html.erb +++ b/app/views/submissions/show.html.erb @@ -109,7 +109,7 @@ <%= render 'submissions/annotation', annot: %> <% end %> <% fields_index.dig(document.uuid, index)&.each do |(area, field)| %> - <% value = values[field['uuid']] %> + <% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %> <% value ||= field['default_value'] if field['type'] == 'heading' %> <% next if value.blank? %> <% submitter = submitters_index[field['submitter_uuid']] %> @@ -238,7 +238,7 @@
<% submitter_fields_index[item['uuid']].to_a.each_with_index do |field, index| %> <% submitter_field_counters[field['type']] += 1 %> - <% value = values[field['uuid']] %> + <% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %> <% next if value.blank? %> <% next if field['type'] == 'heading' %>
diff --git a/app/views/submit_form/show.html.erb b/app/views/submit_form/show.html.erb index d6dbc629..1649b848 100644 --- a/app/views/submit_form/show.html.erb +++ b/app/views/submit_form/show.html.erb @@ -77,7 +77,7 @@ <%= render 'submit_form/annotations', annots: %> <% end %> <% fields_index.dig(document.uuid, index)&.each do |(area, field)| %> - <% value = values[field['uuid']].presence || (field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submitter.submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %> + <% value = values[field['uuid']].presence || (field['readonly'] == true && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submitter.submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %> <% next if value.blank? %> <% next if !field['readonly'] && field['submitter_uuid'] == @submitter.uuid %> <% next if value == '{{date}}' && field['submitter_uuid'] != @submitter.uuid %> diff --git a/app/views/templates/_dropzone.html.erb b/app/views/templates/_dropzone.html.erb index 124efa83..2569aa7d 100644 --- a/app/views/templates/_dropzone.html.erb +++ b/app/views/templates/_dropzone.html.erb @@ -23,7 +23,7 @@
- + " multiple> diff --git a/app/views/templates/_upload_button.html.erb b/app/views/templates/_upload_button.html.erb index 12f36df0..40460070 100644 --- a/app/views/templates/_upload_button.html.erb +++ b/app/views/templates/_upload_button.html.erb @@ -14,6 +14,6 @@ - + " multiple> <% end %> diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 154deb25..d7b80f1a 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -321,7 +321,7 @@ Devise.setup do |config| # apps is `200 OK` and `302 Found respectively`, but new apps are generated with # these new defaults that match Hotwire/Turbo behavior. # Note: These might become the new default in future versions of Devise. - config.responder.error_status = :unprocessable_entity + config.responder.error_status = :unprocessable_content config.responder.redirect_status = :see_other # ==> Configuration for :registerable diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index cf5cfc97..3243e90c 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -24,6 +24,7 @@ en: &en thanks: Thanks private: Private select: Select + party: Party edit_order: Edit Order invite_form_fields: Invite form fields default_parties: Default parties @@ -899,6 +900,7 @@ en: &en range_without_total: "%{from}-%{to} events" es: &es + party: Parte edit_order: Edita Pedido select: Seleccionar invite_form_fields: Invitar campos del formulario @@ -1778,6 +1780,7 @@ es: &es range_without_total: "%{from}-%{to} eventos" it: &it + party: Parte edit_order: Modifica Ordine select: Seleziona invite_form_fields: Invita campi modulo @@ -2657,6 +2660,7 @@ it: &it range_without_total: "%{from}-%{to} eventi" fr: &fr + party: Partie edit_order: Modifier la commande select: Sélectionner invite_form_fields: Inviter des champs de formulaire @@ -3539,6 +3543,7 @@ fr: &fr range_without_total: "%{from} à %{to} événements" pt: &pt + party: Parte edit_order: Edita Pedido select: Selecionar invite_form_fields: Convidar campos do formulário @@ -4419,6 +4424,7 @@ pt: &pt range_without_total: "%{from}-%{to} eventos" de: &de + party: Partei edit_order: Bestellung bearbeiten select: Auswählen invite_form_fields: Formularfelder einladen diff --git a/lib/accounts.rb b/lib/accounts.rb index 898051fc..6153111b 100644 --- a/lib/accounts.rb +++ b/lib/accounts.rb @@ -53,8 +53,11 @@ module Accounts ApplicationRecord.transaction do account.testing_accounts << testing_account + original_email = account.users.order(:id).first.email + test_email = generate_unique_test_email(original_email) + testing_account.users.create!( - email: account.users.order(:id).first.email.sub('@', '+test@'), + email: test_email, first_name: 'Testing', last_name: 'Environment', password: SecureRandom.hex, @@ -63,6 +66,22 @@ module Accounts end end + def generate_unique_test_email(original_email) + base_email = original_email.sub('@', '+test@') + + return base_email unless User.exists?(email: base_email) + + (1..3).each do |i| + test_email = original_email.sub('@', "+test#{i}@") + + return test_email unless User.exists?(email: test_email) + end + + timestamp = Time.current.to_i + + original_email.sub('@', "+test#{timestamp}@") + end + def create_default_template(account) template = Template.find(1) diff --git a/lib/submitters.rb b/lib/submitters.rb index 2e04b7b3..2eef2f9b 100644 --- a/lib/submitters.rb +++ b/lib/submitters.rb @@ -177,7 +177,11 @@ module Submitters submitter_items.first(submitter_items.find_index { |e| e['uuid'] == submitter.uuid }) end - before_items.all? { |item| submission.submitters.find { |e| e.uuid == item['uuid'] }&.completed_at? } + before_items.all? do |item| + submitter = submission.submitters.find { |e| e.uuid == item['uuid'] } + + submitter.nil? || submitter.completed_at? + end end def build_document_filename(submitter, blob, filename_format) diff --git a/lib/submitters/submit_values.rb b/lib/submitters/submit_values.rb index 0216361c..3262633d 100644 --- a/lib/submitters/submit_values.rb +++ b/lib/submitters/submit_values.rb @@ -8,6 +8,14 @@ module Submitters VARIABLE_REGEXP = /\{\{?(\w+)\}\}?/ NONEDITABLE_FIELD_TYPES = %w[stamp heading].freeze + STRFTIME_MAP = { + 'hour' => '%-k', + 'minute' => '%M', + 'day' => '%-d', + 'month' => '%-m', + 'year' => '%Y' + }.freeze + module_function def call(submitter, params, request, validate_required: true) @@ -327,12 +335,10 @@ module Submitters else e end + when 'hour', 'minute', 'day', 'month', 'year' + with_time ? Time.current.in_time_zone(submission.account.timezone).strftime(STRFTIME_MAP[key]) : e when 'date' - if with_time - Time.current.in_time_zone(submission.account.timezone).to_date.to_s - else - e - end + with_time ? Time.current.in_time_zone(submission.account.timezone).to_date.to_s : e when 'role', 'email', 'phone', 'name' attrs[key] || e else diff --git a/lib/templates/create_attachments.rb b/lib/templates/create_attachments.rb index 22d84e2f..10b08ac7 100644 --- a/lib/templates/create_attachments.rb +++ b/lib/templates/create_attachments.rb @@ -3,6 +3,20 @@ module Templates module CreateAttachments PDF_CONTENT_TYPE = 'application/pdf' + ZIP_CONTENT_TYPE = 'application/zip' + X_ZIP_CONTENT_TYPE = 'application/x-zip-compressed' + JSON_CONTENT_TYPE = 'application/json' + DOCUMENT_EXTENSIONS = %w[.docx .doc .xlsx .xls .odt .rtf].freeze + + DOCUMENT_CONTENT_TYPES = %w[ + application/vnd.openxmlformats-officedocument.wordprocessingml.document + application/msword + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + application/vnd.ms-excel + application/vnd.oasis.opendocument.text + application/rtf + ].freeze + ANNOTATIONS_SIZE_LIMIT = 6.megabytes InvalidFileType = Class.new(StandardError) PdfEncrypted = Class.new(StandardError) @@ -10,7 +24,7 @@ module Templates module_function def call(template, params, extract_fields: false) - Array.wrap(params[:files].presence || params[:file]).map do |file| + extract_zip_files(params[:files].presence || params[:file]).flat_map do |file| handle_file_types(template, file, params, extract_fields:) end end @@ -53,6 +67,40 @@ module Templates raise PdfEncrypted end + def extract_zip_files(files) + extracted_files = [] + + Array.wrap(files).each do |file| + if file.content_type == ZIP_CONTENT_TYPE || file.content_type == X_ZIP_CONTENT_TYPE + Zip::File.open(file.tempfile).each do |entry| + next if entry.directory? + + tempfile = Tempfile.new(entry.name) + tempfile.binmode + entry.get_input_stream { |in_stream| IO.copy_stream(in_stream, tempfile) } + tempfile.rewind + + type = Marcel::MimeType.for(tempfile, name: entry.name) + + next if type.exclude?('image') && + type != PDF_CONTENT_TYPE && + type != JSON_CONTENT_TYPE && + DOCUMENT_CONTENT_TYPES.exclude?(type) + + extracted_files << ActionDispatch::Http::UploadedFile.new( + filename: File.basename(entry.name), + type:, + tempfile: + ) + end + else + extracted_files << file + end + end + + extracted_files + end + def handle_file_types(template, file, params, extract_fields:) if file.content_type.include?('image') || file.content_type == PDF_CONTENT_TYPE return handle_pdf_or_image(template, file, file.read, params, extract_fields:) diff --git a/spec/requests/submissions_spec.rb b/spec/requests/submissions_spec.rb index 7a362ef5..468b5715 100644 --- a/spec/requests/submissions_spec.rb +++ b/spec/requests/submissions_spec.rb @@ -151,7 +151,7 @@ describe 'Submission API' do ] }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'email is invalid in `submitters[0]`.' }) end @@ -165,7 +165,7 @@ describe 'Submission API' do submitters: [{ role: 'First Party', email: 'john.doe@example.com' }] }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'Template does not contain fields' }) end @@ -179,7 +179,7 @@ describe 'Submission API' do ] }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'role must be unique in `submitters`.' }) end @@ -193,7 +193,7 @@ describe 'Submission API' do ] }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'Defined more signing parties than in template' }) end @@ -209,7 +209,7 @@ describe 'Submission API' do } }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'body is required in `message`.' }) end end @@ -235,7 +235,7 @@ describe 'Submission API' do emails: 'amy.baker@example.com, george.morris@example.com@gmail.com' }.to_json - expect(response).to have_http_status(:unprocessable_entity) + expect(response).to have_http_status(:unprocessable_content) expect(response.parsed_body).to eq({ 'error' => 'emails are invalid' }) end