Merge from docusealco/wip

This commit is contained in:
Alex Turchyn
2025-12-15 13:19:09 +02:00
committed by GitHub
53 changed files with 24337 additions and 26100 deletions
+7 -22
View File
@@ -1,27 +1,14 @@
name: Build Docker Images
on:
workflow_dispatch:
inputs:
version:
description: Version
type: string
required: true
image:
description: QEMU image
type: string
required: false
default: tonistiigi/binfmt:latest
os:
description: OS
type: string
required: false
default: ubuntu-24.04-arm
push:
tags:
- "*.*.*"
jobs:
build:
runs-on: ${{ inputs.os }}
timeout-minutes: 20
runs-on: ubuntu-24.04-arm
timeout-minutes: 30
steps:
- name: Checkout code
@@ -34,18 +21,16 @@ jobs:
uses: docker/metadata-action@v4
with:
images: docuseal/docuseal
tags: latest,${{ inputs.version }}
tags: type=semver,pattern={{version}}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
image: ${{ inputs.image }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create .version file
run: echo ${{ inputs.version }} > .version
run: echo ${{ github.ref_name }} > .version
- name: Login to Docker Hub
uses: docker/login-action@v3
@@ -182,13 +182,13 @@ module Api
def submissions_params
permitted_attrs = [
:send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last,
:require_phone_2fa, :expire_at, :name,
:require_phone_2fa, :require_email_2fa, :expire_at, :name,
{
variables: {},
message: %i[subject body],
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
:require_phone_2fa, :order,
:require_phone_2fa, :require_email_2fa, :order, :invite_by,
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
fields: [:name, :uuid, :default_value, :value, :title, :description,
:readonly, :required, :validation_pattern, :invalid_message,
+1 -1
View File
@@ -84,7 +84,7 @@ module Api
submitter_params.permit(
:send_email, :send_sms, :reply_to, :completed_redirect_url, :uuid, :name, :email, :role,
:completed, :phone, :application_key, :external_id, :go_to_last, :require_phone_2fa,
:completed, :phone, :application_key, :external_id, :go_to_last, :require_phone_2fa, :require_email_2fa,
{ metadata: {}, values: {}, readonly_fields: [], message: %i[subject body],
fields: [[:name, :uuid, :default_value, :value, :required,
:readonly, :validation_pattern, :invalid_message,
@@ -12,6 +12,14 @@ class SubmissionsController < ApplicationController
authorize!(:create, Submission)
end
FIELD_ICONS = {
'text' => 'text_size', 'signature' => 'writing_sign', 'date' => 'calendar_event',
'number' => 'square_number_1', 'image' => 'photo', 'initials' => 'letter_case_upper',
'file' => 'paperclip', 'select' => 'select', 'checkbox' => 'checkbox', 'radio' => 'circle_dot',
'stamp' => 'rubber_stamp', 'cells' => 'columns_3', 'multiple' => 'checks', 'phone' => 'phone_check',
'payment' => 'credit_card', 'verification' => 'id'
}.freeze
def show
@submission = Submissions.preload_with_pages(@submission)
+1 -1
View File
@@ -537,7 +537,7 @@
/>
<div
v-if="stepFields.length < 80"
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1"
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1 select-none"
>
<div class="flex items-center flex-wrap steps-progress">
<a
+14 -14
View File
@@ -13,7 +13,7 @@ const en = {
esignature_disclosure: 'eSignature Disclosure',
signature: 'Signature',
initials: 'Initials',
drawn_signature_on_a_touchscreen_device: 'Drawn signature on a touchscreen device',
sign_on_the_touchscreen: 'Sign on the touchscreen',
approved: 'Approved',
reviewed: 'Reviewed',
other: 'Other',
@@ -120,7 +120,7 @@ const es = {
select_a_reason: 'Selecciona una razón',
value_is_invalid: 'El valor no es válido',
verification_code_is_invalid: 'El código de verificación no es válido',
drawn_signature_on_a_touchscreen_device: 'Firma dibujada en un dispositivo con pantalla táctil',
sign_on_the_touchscreen: 'Firmar en pantalla táctil',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escanea el código QR con la aplicación de la cámara para abrir el formulario en el móvil y dibujar tu firma',
by_clicking_you_agree_to_the: 'Al hacer clic en "{button}", usted acepta el',
electronic_signature_disclosure: 'Divulgación de Firma Electrónica',
@@ -221,7 +221,7 @@ const it = {
select_a_reason: 'Seleziona una ragione',
value_is_invalid: 'Il valore non è valido',
verification_code_is_invalid: 'Il codice di verifica non è valido',
drawn_signature_on_a_touchscreen_device: 'Firma disegnata su un dispositivo con schermo tattile',
sign_on_the_touchscreen: 'Firma su schermo tattile',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: "Scansiona il codice QR con l'app della fotocamera per aprire il modulo sul cellulare e disegnare la tua firma",
by_clicking_you_agree_to_the: 'Cliccando su "{button}", accetti il',
electronic_signature_disclosure: 'Divulgazione della Firma Elettronica',
@@ -316,7 +316,7 @@ const de = {
esignature_disclosure: 'Hinweis zur eSignatur',
signature: 'Unterschrift',
initials: 'Initialen',
drawn_signature_on_a_touchscreen_device: 'Auf einem Touchscreen-Gerät gezeichnete Unterschrift',
sign_on_the_touchscreen: 'Auf Touchscreen signieren',
approved: 'Genehmigt',
reviewed: 'Geprüft',
other: 'Sonstiges',
@@ -417,7 +417,7 @@ const fr = {
esignature_disclosure: 'Déclaration eSignature',
signature: 'Signature',
initials: 'Initiales',
drawn_signature_on_a_touchscreen_device: 'Signature dessinée sur un appareil à écran tactile',
sign_on_the_touchscreen: 'Signer sur écran tactile',
approved: 'Approuvé',
reviewed: 'Révisé',
other: 'Autre',
@@ -524,7 +524,7 @@ const pl = {
select_a_reason: 'Wybierz powód',
value_is_invalid: 'Wartość jest nieprawidłowa',
verification_code_is_invalid: 'Kod weryfikacyjny jest nieprawidłowy',
drawn_signature_on_a_touchscreen_device: 'Podpis odręczny na urządzeniu z ekranem dotykowym',
sign_on_the_touchscreen: 'Podpisz na ekranie dotykowym',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Zeskanuj kod QR za pomocą aplikacji aparatu, aby otworzyć formularz na telefonie i narysować swój podpis',
by_clicking_you_agree_to_the: 'Klikając na "{button}", zgadzasz się na',
electronic_signature_disclosure: 'Ujawnienie Elektronicznej Sygnatury',
@@ -625,7 +625,7 @@ const uk = {
select_a_reason: 'Виберіть причину',
value_is_invalid: 'Значення є неправильним',
verification_code_is_invalid: 'Код підтвердження є неправильним',
drawn_signature_on_a_touchscreen_device: 'Підпис на сенсорному пристрої',
sign_on_the_touchscreen: 'Підписати на сенсорному екрані',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Скануйте QR-код за допомогою програми камери, щоб відкрити форму на мобільному пристрої та намалювати свій підпис',
by_clicking_you_agree_to_the: 'Натиснувши на "{button}", ви погоджуєтеся з',
electronic_signature_disclosure: 'Розголошення Електронного Підпису',
@@ -726,7 +726,7 @@ const cs = {
select_a_reason: 'Vyberte důvod',
value_is_invalid: 'Hodnota je neplatná',
verification_code_is_invalid: 'Ověřovací kód je neplatný',
drawn_signature_on_a_touchscreen_device: 'Namalovaný podpis na dotykovém zařízení',
sign_on_the_touchscreen: 'Podepsat na dotykové obrazovce',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Naskenujte QR kód pomocí aplikace fotoaparátu, abyste otevřeli formulář na mobilním zařízení a nakreslili svůj podpis',
by_clicking_you_agree_to_the: 'Kliknutím na "{button}" souhlasíte s',
electronic_signature_disclosure: 'Zveřejněním Elektronického Podpisu',
@@ -827,7 +827,7 @@ const pt = {
select_a_reason: 'Selecione um motivo',
value_is_invalid: 'Valor é inválido',
verification_code_is_invalid: 'Código de verificação é inválido',
drawn_signature_on_a_touchscreen_device: 'Assinatura desenhada em um dispositivo com tela sensível ao toque',
sign_on_the_touchscreen: 'Assinar na tela sensível',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escaneie o código QR com o aplicativo da câmera para abrir o formulário no celular e desenhar sua assinatura',
by_clicking_you_agree_to_the: 'Ao clicar em "{button}", você concorda com o',
electronic_signature_disclosure: 'Divulgação de Assinatura Eletrônica',
@@ -928,7 +928,7 @@ const he = {
select_a_reason: 'בחר סיבה',
value_is_invalid: 'ערך לא תקין',
verification_code_is_invalid: 'קוד האימות אינו תקין',
drawn_signature_on_a_touchscreen_device: 'חתימה שנוצרה במכשיר עם מסך מגע',
sign_on_the_touchscreen: 'חתום על מסך המגע',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'סרוק את קוד ה-QR באמצעות אפליקציית המצלמה כדי לפתוח את הטופס במובייל ולצייר את החתימה שלך',
by_clicking_you_agree_to_the: 'על ידי לחיצה על "{button}", אתה מסכים ל',
electronic_signature_disclosure: 'חשיפת חתימה אלקטרונית',
@@ -1029,7 +1029,7 @@ const nl = {
select_a_reason: 'Selecteer een reden',
value_is_invalid: 'Waarde is ongeldig',
verification_code_is_invalid: 'Verificatiecode is ongeldig',
drawn_signature_on_a_touchscreen_device: 'Getekende handtekening op een apparaat met een touchscreen',
sign_on_the_touchscreen: 'Onderteken op touchscreen',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Scan de QR-code met de camera-app om het formulier op mobiel te openen en uw handtekening te tekenen',
by_clicking_you_agree_to_the: 'Door op "{button}" te klikken, gaat u akkoord met de',
electronic_signature_disclosure: 'Openbaarmaking van Elektronische Handtekening',
@@ -1131,7 +1131,7 @@ const ar = {
value_is_invalid: 'القيمة غير صالحة',
verification_code_is_invalid: 'رمز التحقق غير صالح',
already_paid: 'تم الدفع بالفعل',
drawn_signature_on_a_touchscreen_device: 'توقيع مرسوم على جهاز بشاشة تعمل باللمس',
sign_on_the_touchscreen: 'وقع على شاشة اللمس',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'امسح رمز الاستجابة السريعة باستخدام تطبيق الكاميرا لفتح النموذج على الهاتف المحمول ورسم توقيعك',
by_clicking_you_agree_to_the: 'بالنقر فوق "{button}"، أنت توافق على',
electronic_signature_disclosure: 'كشف التوقيع الإلكتروني',
@@ -1229,7 +1229,7 @@ const ko = {
reviewed_by: '검토자',
authored_by: '작성자',
select_a_reason: '이유 선택',
drawn_signature_on_a_touchscreen_device: '터치스크린 장치에서 그린 서명',
sign_on_the_touchscreen: '터치스크린에서 서명',
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: '카메라 앱으로 QR 코드를 스캔하여 모바일에서 양식을 열고 서명을 그리세요',
by_clicking_you_agree_to_the: '"{button}"를 클릭함으로써, 다음에 동의하게 됩니다',
electronic_signature_disclosure: '전자 서명 공개',
@@ -1326,7 +1326,7 @@ const ja = {
esignature_disclosure: '電子署名開示',
signature: '署名',
initials: 'イニシャル',
drawn_signature_on_a_touchscreen_device: 'タッチスクリーンデバイスで描かれた署名',
sign_on_the_touchscreen: 'タッチスクリーン署名',
approved: '承認済み',
reviewed: '確認済み',
other: 'その他',
@@ -19,7 +19,7 @@
<div class="space-x-2 flex flex-none">
<span
v-if="isDrawInitials"
class="tooltip"
class="md:tooltip"
:data-tip="t('type_initial')"
>
<a
@@ -36,7 +36,7 @@
</span>
<span
v-else
class="tooltip ml-2"
class="md:tooltip ml-2"
:data-tip="t('draw_initials')"
>
<a
@@ -52,7 +52,7 @@
</a>
</span>
<span
class="tooltip"
class="md:tooltip"
:data-tip="t('click_to_upload')"
>
<label class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button">
@@ -22,7 +22,7 @@
<div class="space-x-2 flex flex-none">
<span
v-if="isTextSignature && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
class="tooltip"
class="md:tooltip"
:data-tip="t('draw_signature')"
>
<a
@@ -39,7 +39,7 @@
</span>
<span
v-else-if="withTypedSignature && format !== 'drawn_or_upload' && format !== 'typed_or_upload' && format !== 'typed' && format !== 'drawn' && format !== 'upload'"
class="tooltip ml-2"
class="md:tooltip ml-2"
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
:data-tip="t('type_text')"
>
@@ -57,7 +57,7 @@
</span>
<span
v-if="format !== 'typed' && format !== 'drawn' && format !== 'upload' && format !== 'drawn_or_typed'"
class="tooltip"
class="md:tooltip"
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
:data-tip="t('take_photo')"
>
@@ -86,8 +86,8 @@
</a>
<span
v-if="withQrButton && !modelValue && !computedPreviousValue && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
class="tooltip before:translate-x-[-90%]"
:data-tip="t('drawn_signature_on_a_touchscreen_device')"
class="md:tooltip before:translate-x-[-90%]"
:data-tip="t('sign_on_the_touchscreen')"
>
<a
href="#"
@@ -142,7 +142,7 @@
/>
<div
v-else
class="relative"
class="relative select-none"
>
<div
v-if="!modelValue && !computedPreviousValue && !isShowQr && !isTextSignature && isSignatureStarted"
@@ -176,7 +176,7 @@
class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl"
>
<div
class="absolute top-1.5 right-1.5 tooltip"
class="absolute top-1.5 right-1.5 md:tooltip"
>
<a
href="#"
@@ -281,7 +281,7 @@
<div
v-else-if="withDisclosure"
dir="auto"
class="text-base-content/60 text-xs text-center w-full mt-1"
class="text-base-content/60 text-xs text-center w-full mt-1 select-none"
>
{{ t('by_clicking_you_agree_to_the').replace('{button}', buttonText.charAt(0).toUpperCase() + buttonText.slice(1)) }} <a
href="https://www.docuseal.com/esign-disclosure"
@@ -6,7 +6,9 @@ class SendSubmitterVerificationEmailJob
def perform(params = {})
submitter = Submitter.find(params['submitter_id'])
SubmitterMailer.otp_verification_email(submitter).deliver_now!
locale = params['locale'].presence || submitter.account.locale
SubmitterMailer.otp_verification_email(submitter, locale:).deliver_now!
SubmissionEvent.create!(submitter_id: params['submitter_id'],
event_type: 'send_2fa_email',
+2 -2
View File
@@ -144,13 +144,13 @@ class SubmitterMailer < ApplicationMailer
end
end
def otp_verification_email(submitter)
def otp_verification_email(submitter, locale: nil)
@submitter = submitter
@otp_code = EmailVerificationCodes.generate([submitter.email.downcase.strip, submitter.slug].join(':'))
assign_message_metadata('otp_verification_email', submitter)
I18n.with_locale(submitter.account.locale) do
I18n.with_locale(locale || submitter.account.locale) do
mail(to: submitter.email, subject: I18n.t('email_verification'))
end
end
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z"></path>
<path d="M16 3l0 4"></path>
<path d="M8 3l0 4"></path>
<path d="M4 11l16 0"></path>
<path d="M8 15h2v2h-2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 450 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M9 11l3 3l8 -8"></path>
<path d="M20 12v6a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h9"></path>
</svg>

After

Width:  |  Height:  |  Size: 346 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M7 12l5 5l10 -10"></path>
<path d="M2 12l5 5m5 -5l5 -5"></path>
</svg>

After

Width:  |  Height:  |  Size: 303 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3m0 1a1 1 0 0 1 1 -1h16a1 1 0 0 1 1 1v16a1 1 0 0 1 -1 1h-16a1 1 0 0 1 -1 -1zm6 -1v18m6 -18v18"></path>
</svg>

After

Width:  |  Height:  |  Size: 343 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 5m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z"></path>
<path d="M3 10l18 0"></path>
<path d="M7 15l.01 0"></path>
<path d="M11 15l2 0"></path>
</svg>

After

Width:  |  Height:  |  Size: 419 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v10a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z"></path>
<path d="M9 10m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"></path>
<path d="M15 8l2 0"></path>
<path d="M15 12l2 0"></path>
<path d="M7 16l10 0"></path>
</svg>

After

Width:  |  Height:  |  Size: 478 B

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 19v-10.5a3.5 3.5 0 0 1 7 0v10.5"></path>
<path d="M3 13h7"></path>
<path d="M14 19v-10.5a3.5 3.5 0 0 1 7 0v10.5"></path>
<path d="M14 13h7"></path>
</svg>

After

Width:  |  Height:  |  Size: 394 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 8h.01"></path>
<path d="M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12z"></path>
<path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5"></path>
<path d="M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3"></path>
</svg>

After

Width:  |  Height:  |  Size: 481 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 17.85h-18c0 -4.05 1.421 -4.05 3.79 -4.05c5.21 0 1.21 -4.59 1.21 -6.8a4 4 0 1 1 8 0c0 2.21 -4 6.8 1.21 6.8c2.369 0 3.79 0 3.79 4.05z"></path>
<path d="M5 21h14"></path>
</svg>

After

Width:  |  Height:  |  Size: 411 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z"></path>
<path d="M9 11l3 3l3 -3"></path>
</svg>

After

Width:  |  Height:  |  Size: 361 B

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z"></path>
<path d="M10 10l2 -2v8"></path>
</svg>

After

Width:  |  Height:  |  Size: 360 B

+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 7v-2h13v2"></path>
<path d="M10 5v14"></path>
<path d="M12 19h-4"></path>
<path d="M15 13v-1h6v1"></path>
<path d="M18 12v7"></path>
<path d="M17 19h2"></path>
</svg>

After

Width:  |  Height:  |  Size: 410 B

+1 -1
View File
@@ -1,6 +1,6 @@
<a target="_blank" href="<%= Docuseal::GITHUB_URL %>" rel="noopener noreferrer nofollow" class="relative flex items-center rounded-full px-2 py-0.5 text-xs leading-4 mt-1 text-base-content border border-base-300 tooltip tooltip-bottom" data-tip="Give a star on GitHub">
<span class="flex items-center justify-between space-x-0.5 font-medium">
<%= svg_icon('start', class: 'h-3 w-3') %>
<span>10k</span>
<span>11k</span>
</span>
</a>
+7 -6
View File
@@ -50,12 +50,13 @@
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
</div>
<% elsif field['type'].in?(%w[multiple radio]) && area['option_uuid'] %>
<% option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] } %>
<% option_name = option['value'].presence || "Option #{field['options'].index(option) + 1}" %>
<% if option && Array.wrap(value).include?(option_name) %>
<div class="w-full flex items-center justify-center">
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
</div>
<% if (option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }) %>
<% option_name = option['value'].presence || "Option #{field['options'].index(option) + 1}" %>
<% if Array.wrap(value).include?(option_name) %>
<div class="w-full flex items-center justify-center">
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
</div>
<% end %>
<% end %>
<% elsif field['type'] == 'cells' && area['cell_w'].to_f > 0.0 %>
<% cell_width = area['cell_w'] / area['w'] * 100 %>
+24 -12
View File
@@ -4,7 +4,7 @@
<% font_scale = 1040.0 / PdfUtils::US_LETTER_W %>
<% configs = AccountConfig.where(account_id: @submission.account_id, key: [AccountConfig::COMBINE_PDF_RESULT_KEY, AccountConfig::WITH_SIGNATURE_ID, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY]) %>
<% with_signature_id = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true %>
<% is_combined_enabled = configs.find { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }&.value == true %>
<% is_combined_enabled = configs.find { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }&.value == true && !@submission.template_fields&.any? { |f| f['type'] == 'verification' } %>
<% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %>
<% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %>
<div style="max-width: 1600px" class="mx-auto pl-4">
@@ -93,8 +93,10 @@
<div class="pr-3.5 pl-0.5">
<% fields_index = Templates.build_field_areas_index(@submission.template_fields || @submission.template.fields) %>
<% submitters_index = @submission.submitters.index_by(&:uuid) %>
<% submitters_order_index = nil %>
<% attachments_index = ActiveStorage::Attachment.where(record: @submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %>
<% page_blob_struct = Struct.new(:url, :metadata, keyword_init: true) %>
<% bg_classes = %w[bg-red-100 bg-sky-100 bg-emerald-100 bg-yellow-100 bg-purple-100 bg-pink-100 bg-cyan-100 bg-orange-100 bg-lime-100 bg-indigo-100] %>
<% schema.each do |item| %>
<% document = @submission.schema_documents.find { |e| e.uuid == item['attachment_uuid'] } %>
<% document_annots_index = document.metadata.dig('pdf', 'annotations')&.group_by { |e| e['page'] } || {} %>
@@ -111,19 +113,29 @@
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
<% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['conditions'].blank? && 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']] %>
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
<span class="group">
<span class="hidden group-hover:inline">
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value:, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
<% if value.present? %>
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
<span class="group">
<span class="hidden group-hover:inline">
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value:, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
</span>
<span class="group-hover:hidden">
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', '), locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
</span>
</span>
<span class="group-hover:hidden">
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', '), locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
</span>
</span>
<% else %>
<%= render 'submissions/value', page_width: width, page_height: height, font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id:, with_submitter_timezone:, with_signature_id_reason: %>
<% else %>
<%= render 'submissions/value', page_width: width, page_height: height, font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id:, with_submitter_timezone:, with_signature_id_reason: %>
<% end %>
<% elsif field['readonly'] != true && submitter && !submitter.completed_at? %>
<% submitters_order_index ||= (@submission.template_submitters || @submission.template.submitters).each_with_index.to_h { |s, i| [s['uuid'], i] } %>
<% submitter_index = submitters_order_index[submitter.uuid] %>
<% bg_class = bg_classes[submitter_index % bg_classes.size] %>
<div class="absolute overflow-visible" style="width: <%= area['w'] * 100 %>%; height: <%= area['h'] * 100 %>%; left: <%= area['x'] * 100 %>%; top: <%= area['y'] * 100 %>%;">
<div class="flex h-full w-full bg-opacity-80 justify-center items-center <%= bg_class %>">
<%= svg_icon(SubmissionsController::FIELD_ICONS[field['type']], class: 'max-h-10 w-full h-full stroke-2 opacity-50') %>
</div>
</div>
<% end %>
<% end %>
</div>
+1 -1
View File
@@ -1,7 +1,7 @@
{
"ignored_warnings": [
{
"fingerprint": "bbd1bdad94998e53a48921859065e06cd1595502d4dc40362afcaa90307b591a",
"fingerprint": "de39648cd3f79d51e95e45f05fc77da49b0ad68bf80458061151016c0ef78208",
"note": "Permitted parameters are necessary for creating submitters via API"
},
{
+14
View File
@@ -876,6 +876,7 @@ en: &en
you_requested_to_reset_your_password_use_the_link_below_to_continue: You requested to reset your password. Use the link below to continue
if_you_didnt_request_this_you_can_ignore_this_email: "If you didn't request this, please ignore this email."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Your password won't change until you open the link above and set a new one."
too_many_requests_try_again_later: Too many requests, try again later.
devise:
confirmations:
confirmed: Your email address has been successfully confirmed.
@@ -1847,6 +1848,7 @@ es: &es
you_requested_to_reset_your_password_use_the_link_below_to_continue: Solicitaste restablecer tu contraseña. Usa el enlace a continuación para continuar.
if_you_didnt_request_this_you_can_ignore_this_email: "Si no solicitaste esto, puedes ignorar este correo electrónico."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Tu contraseña no cambiará hasta que abras el enlace anterior y establezcas una nueva."
too_many_requests_try_again_later: Demasiadas solicitudes. Intenta de nuevo más tarde.
devise:
confirmations:
confirmed: Tu dirección de correo electrónico ha sido confirmada correctamente.
@@ -2819,6 +2821,7 @@ it: &it
you_requested_to_reset_your_password_use_the_link_below_to_continue: Hai richiesto di reimpostare la tua password. Usa il link qui sotto per continuare.
if_you_didnt_request_this_you_can_ignore_this_email: "Se non hai richiesto questo, puoi ignorare questa email."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "La tua password non cambierà finché non apri il link sopra e ne imposti una nuova."
too_many_requests_try_again_later: Troppe richieste. Riprova più tardi.
devise:
confirmations:
confirmed: Il tuo indirizzo email è stato confermato con successo.
@@ -3787,6 +3790,7 @@ fr: &fr
you_requested_to_reset_your_password_use_the_link_below_to_continue: Vous avez demandé à réinitialiser votre mot de passe. Utilisez le lien ci-dessous pour continuer.
if_you_didnt_request_this_you_can_ignore_this_email: "Si vous n'avez pas fait cette demande, veuillez ignorer cet e-mail."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Votre mot de passe ne changera pas tant que vous naurez pas ouvert le lien ci-dessus et défini un nouveau mot de passe."
too_many_requests_try_again_later: Trop de demandes. Réessayez plus tard.
devise:
confirmations:
confirmed: Votre adresse e-mail a été confirmée avec succès.
@@ -4758,6 +4762,7 @@ pt: &pt
you_requested_to_reset_your_password_use_the_link_below_to_continue: Você solicitou a redefinição da sua senha. Use o link abaixo para continuar.
if_you_didnt_request_this_you_can_ignore_this_email: "Se você não solicitou isso, pode ignorar este e-mail."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Sua senha não será alterada até que você abra o link acima e defina uma nova."
too_many_requests_try_again_later: Muitas solicitações. Tente novamente mais tarde.
devise:
confirmations:
confirmed: Seu endereço de e-mail foi confirmado com sucesso.
@@ -5729,6 +5734,7 @@ de: &de
you_requested_to_reset_your_password_use_the_link_below_to_continue: Sie haben angefordert, Ihr Passwort zurückzusetzen. Verwenden Sie den untenstehenden Link, um fortzufahren.
if_you_didnt_request_this_you_can_ignore_this_email: "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Ihr Passwort wird erst geändert, wenn Sie den obigen Link öffnen und ein neues festlegen."
too_many_requests_try_again_later: Zu viele Anfragen. Versuchen Sie es später erneut.
devise:
confirmations:
confirmed: Ihre E-Mail-Adresse wurde erfolgreich bestätigt.
@@ -5938,6 +5944,7 @@ pl:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Nadawca zażądał uwierzytelniania dwuskładnikowego za pośrednictwem hasła jednorazowego wysłanego na Twój adres e-mail <b>%{email}</b>.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Skontaktuj się z nadawcą, aby podać swój adres e-mail do uwierzytelniania dwuskładnikowego.
rate_limit_exceeded: Przekroczono limit
too_many_requests_try_again_later: Zbyt wiele żądań. Spróbuj ponownie później.
uk:
require_phone_2fa_to_open: Вимагати двофакторну автентифікацію через телефон для відкриття
@@ -6034,6 +6041,7 @@ uk:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Відправник запросив двофакторну автентифікацію за допомогою одноразового пароля, відправленого на вашу електронну пошту <b>%{email}</b>.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Будь ласка, зв'яжіться з відправником, щоб вказати вашу електронну пошту для двофакторної автентифікації.
rate_limit_exceeded: Перевищено ліміт
too_many_requests_try_again_later: Забагато запитів. Спробуйте пізніше.
cs:
require_phone_2fa_to_open: Vyžadovat otevření pomocí telefonního 2FA
@@ -6130,6 +6138,7 @@ cs:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Odesílatel požádal o dvoufaktorové ověření pomocí jednorázového hesla odeslaného na vaši e-mailovou adresu <b>%{email}</b>.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Prosím kontaktujte odesílatele a uveďte svůj e-mail pro dvoufaktorové ověření.
rate_limit_exceeded: Překročena hranice
too_many_requests_try_again_later: Příliš mnoho požadavků. Zkuste to později.
he:
require_phone_2fa_to_open: דרוש אימות דו-שלבי באמצעות טלפון לפתיחה
@@ -6226,6 +6235,7 @@ he:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: השולח ביקש אימות דו-שלבי באמצעות סיסמה חד-פעמית שנשלחה לכתובת הדוא"ל שלך <b>%{email}</b>.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: אנא פנה לשולח וציין את כתובת הדוא"ל שלך לאימות דו-שלבי.
rate_limit_exceeded: חריגה ממגבלת
too_many_requests_try_again_later: יותר מדי בקשות. נסה שוב מאוחר יותר.
nl: &nl
templates_that_require_email_or_phone_2fa_cannot_be_used_via_a_shared_link: Sjablonen waarvoor e-mail- of telefoon-2FA vereist is, kunnen niet via een gedeelde link worden gebruikt.
@@ -7081,6 +7091,7 @@ nl: &nl
you_requested_to_reset_your_password_use_the_link_below_to_continue: Je hebt gevraagd je wachtwoord te resetten. Gebruik de onderstaande link om verder te gaan.
if_you_didnt_request_this_you_can_ignore_this_email: "Als je dit niet hebt aangevraagd, kun je deze e-mail negeren."
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Je wachtwoord wordt niet gewijzigd totdat je de bovenstaande link opent en een nieuw wachtwoord instelt."
too_many_requests_try_again_later: Te veel verzoeken. Probeer het later opnieuw.
devise:
confirmations:
confirmed: Je e-mailadres is succesvol bevestigd.
@@ -7290,6 +7301,7 @@ ar:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: طلب المرسل المصادقة الثنائية عبر كلمة مرور لمرة واحدة مرسلة إلى عنوان بريدك الإلكتروني <b>%{email}</b>.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: يرجى الاتصال بالمرسل لتحديد عنوان بريدك الإلكتروني للمصادقة الثنائية.
rate_limit_exceeded: تم تجاوز الحد المسموح به
too_many_requests_try_again_later: طلبات كثيرة جدًا. حاول مرة أخرى لاحقًا.
ko:
require_phone_2fa_to_open: 휴대폰 2FA를 열 때 요구함
@@ -7386,6 +7398,7 @@ ko:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 발신자가 <b>%{email}</b> 이메일 주소로 전송된 일회용 비밀번호를 통해 2단계 인증을 요청했습니다.
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2단계 인증을 위해 이메일 주소를 지정하려면 발신자에게 문의하세요.
rate_limit_exceeded: 속도 제한 초과
too_many_requests_try_again_later: 요청이 너무 많습니다. 나중에 다시 시도하세요.
ja:
require_phone_2fa_to_open: 電話による2段階認証が必要です
@@ -7482,6 +7495,7 @@ ja:
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 送信者は、<b>%{email}</b> メールアドレスに送信されたワンタイムパスワードによる2段階認証を要求しました。
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2段階認証用にメールアドレスを指定するために、送信者にお問い合わせください。
rate_limit_exceeded: レート制限を超えました
too_many_requests_try_again_later: リクエストが多すぎます。後でもう一度お試しください。
en-US:
<<: *en
@@ -9,6 +9,8 @@ class AddIsFirstToCompletedSubmitters < ActiveRecord::Migration[8.0]
add_index :completed_submitters, %i[account_id completed_at],
where: 'is_first = TRUE',
name: 'index_completed_submitters_account_id_completed_at_is_first'
add_index :completed_submitters, :submission_id, unique: true, where: 'is_first = TRUE'
add_index :completed_submitters, :submission_id, unique: adapter_name != 'Mysql2',
where: 'is_first = TRUE'
end
end
+2243 -2455
View File
File diff suppressed because it is too large Load Diff
+2603 -2861
View File
File diff suppressed because it is too large Load Diff
+2233 -2443
View File
File diff suppressed because it is too large Load Diff
+2345 -2580
View File
File diff suppressed because it is too large Load Diff
+2555 -2802
View File
File diff suppressed because it is too large Load Diff
+2331 -2562
View File
File diff suppressed because it is too large Load Diff
+2350 -2587
View File
File diff suppressed because it is too large Load Diff
+2351 -2588
View File
File diff suppressed because it is too large Load Diff
+2239 -2449
View File
File diff suppressed because it is too large Load Diff
+2345 -2580
View File
File diff suppressed because it is too large Load Diff
+13 -4
View File
@@ -151,7 +151,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"drawFieldType": {
@@ -194,7 +195,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -321,7 +323,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -444,6 +447,12 @@ const token = jwt.sign({
"default": true,
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
},
"withFieldsDetection": {
"type": "boolean",
"required": false,
"default": false,
"description": "Display a button to automatically detect and add fields to the document with AI."
},
"withFieldPlaceholder": {
"type": "boolean",
"required": false,
@@ -483,7 +492,7 @@ const token = jwt.sign({
"type": "string",
"required": false,
"default": "en",
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
},
"i18n": {
"type": "object",
+13 -4
View File
@@ -118,7 +118,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -249,7 +250,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -336,7 +338,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"data-draw-field-type": {
@@ -408,6 +411,12 @@
"default": true,
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
},
"data-with-fields-detection": {
"type": "boolean",
"required": false,
"default": false,
"description": "Display a button to automatically detect and add fields to the document with AI."
},
"data-with-field-placeholder": {
"type": "boolean",
"required": false,
@@ -453,7 +462,7 @@
"type": "string",
"required": false,
"default": "en",
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
},
"data-background-color": {
"type": "string",
+13 -4
View File
@@ -142,7 +142,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"drawFieldType": {
@@ -185,7 +186,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -312,7 +314,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -435,6 +438,12 @@ const token = jwt.sign({
"default": true,
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
},
"withFieldsDetection": {
"type": "boolean",
"required": false,
"default": false,
"description": "Display a button to automatically detect and add fields to the document with AI."
},
"withFieldPlaceholder": {
"type": "boolean",
"required": false,
@@ -474,7 +483,7 @@ const token = jwt.sign({
"type": "string",
"required": false,
"default": "en",
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
},
"i18n": {
"type": "object",
+13 -4
View File
@@ -163,7 +163,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"draw-field-type": {
@@ -206,7 +207,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -333,7 +335,8 @@ const token = jwt.sign({
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -450,6 +453,12 @@ const token = jwt.sign({
"default": true,
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
},
"with-fields-detection": {
"type": "boolean",
"required": false,
"default": false,
"description": "Display a button to automatically detect and add fields to the document with AI."
},
"with-field-placeholder": {
"type": "boolean",
"required": false,
@@ -483,7 +492,7 @@ const token = jwt.sign({
"type": "string",
"required": false,
"default": "en",
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
},
"i18n": {
"type": "object",
+1 -1
View File
@@ -30,7 +30,7 @@ export class AppComponent {}
"src": {
"type": "string",
"required": true,
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
},
"email": {
"type": "string",
+1 -1
View File
@@ -26,7 +26,7 @@
"data-src": {
"type": "string",
"required": true,
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
},
"data-email": {
"type": "string",
+1 -1
View File
@@ -27,7 +27,7 @@ export function App() {
"src": {
"type": "string",
"required": true,
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
},
"email": {
"type": "string",
+1 -1
View File
@@ -36,7 +36,7 @@ export default {
"src": {
"type": "string",
"required": true,
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
},
"email": {
"type": "string",
+454 -85
View File
@@ -251,7 +251,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -277,6 +278,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -300,6 +305,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -714,7 +726,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -740,6 +753,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -763,6 +780,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -1782,6 +1806,11 @@
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
"default": false
},
"require_email_2fa": {
"type": "boolean",
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
"default": false
},
"message": {
"type": "object",
"properties": {
@@ -1933,6 +1962,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -1986,6 +2024,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -2622,6 +2667,10 @@
"event_timestamp": {
"type": "string",
"description": "Date and time when the event was triggered."
},
"data": {
"type": "object",
"description": "Additional event details object."
}
}
}
@@ -2733,7 +2782,8 @@
"id": 1,
"submitter_id": 2,
"event_type": "view_form",
"event_timestamp": "2023-12-14T15:47:24.566Z"
"event_timestamp": "2023-12-14T15:47:24.566Z",
"data": {}
}
],
"documents": [
@@ -3318,7 +3368,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -3471,6 +3522,15 @@
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
"default": false
},
"require_email_2fa": {
"type": "boolean",
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
"default": false
},
"invite_by": {
"type": "string",
"description": "Set the role name of the previous party that should invite this party via email."
},
"fields": {
"type": "array",
"description": "A list of configurations for document form fields.",
@@ -3609,6 +3669,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -3662,6 +3731,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -3744,7 +3820,6 @@
"type": "object",
"required": [
"id",
"submission_id",
"uuid",
"email",
"slug",
@@ -3833,6 +3908,53 @@
"awaiting"
]
},
"values": {
"type": "array",
"description": "An array of pre-filled values for the submitter.",
"items": {
"type": "object",
"required": [
"field",
"value"
],
"properties": {
"field": {
"type": "string",
"description": "Document template field name."
},
"value": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
}
],
"description": "Pre-filled value of the field."
}
}
}
},
"role": {
"type": "string",
"description": "The role of the submitter."
@@ -3944,7 +4066,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -3970,6 +4093,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -3993,6 +4120,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -4040,27 +4174,6 @@
}
}
},
"documents": {
"type": "array",
"description": "List of documents attached to the one-off submission.",
"items": {
"type": "object",
"required": [
"attachment_uuid",
"name"
],
"properties": {
"attachment_uuid": {
"type": "string",
"description": "Unique indentifier of attached document to the one-off submission."
},
"name": {
"type": "string",
"description": "Name of the attached document to the one-off submission."
}
}
}
},
"expire_at": {
"type": "string",
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
@@ -4158,7 +4271,7 @@
"Submissions"
],
"summary": "Create a submission from DOCX",
"description": "The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href=\"https://www.docuseal.com/examples/demo_template.docx\" target=\"_blank\" class=\"link font-bold\">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href=\"https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form\" class=\"link\">Use embedded text field tags to create a fillable form</a>",
"description": "The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href=\"https://www.docuseal.com/examples/demo_template.docx\" target=\"_blank\" class=\"link font-bold\">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href=\"https://www.docuseal.com/guides/use-dynamic-content-variables-in-docx-to-create-personalized-documents\" class=\"link\">Use dynamic content variables in DOCX to create personalized documents</a>",
"operationId": "createSubmissionFromDocx",
"parameters": [],
"requestBody": {
@@ -4189,7 +4302,7 @@
},
"variables": {
"type": "object",
"description": "Dynamic content variables object",
"description": "Dynamic content variables object. Variable values can be strings, numbers, arrays, objects, or HTML content used to generate styled text, paragraphs, and tables in DOCX.",
"example": {
"variable_name": "value"
}
@@ -4327,6 +4440,15 @@
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
"default": false
},
"require_email_2fa": {
"type": "boolean",
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
"default": false
},
"invite_by": {
"type": "string",
"description": "Set the role name of the previous party that should invite this party via email."
},
"fields": {
"type": "array",
"description": "A list of configurations for document form fields.",
@@ -4465,6 +4587,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -4518,6 +4649,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -4595,7 +4733,6 @@
"type": "object",
"required": [
"id",
"submission_id",
"uuid",
"email",
"slug",
@@ -4684,6 +4821,53 @@
"awaiting"
]
},
"values": {
"type": "array",
"description": "An array of pre-filled values for the submitter.",
"items": {
"type": "object",
"required": [
"field",
"value"
],
"properties": {
"field": {
"type": "string",
"description": "Document template field name."
},
"value": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
}
],
"description": "Pre-filled value of the field."
}
}
}
},
"role": {
"type": "string",
"description": "The role of the submitter."
@@ -4795,7 +4979,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -4821,6 +5006,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -4844,6 +5033,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -4891,27 +5087,6 @@
}
}
},
"documents": {
"type": "array",
"description": "List of documents attached to the one-off submission.",
"items": {
"type": "object",
"required": [
"attachment_uuid",
"name"
],
"properties": {
"attachment_uuid": {
"type": "string",
"description": "Unique indentifier of attached document to the one-off submission."
},
"name": {
"type": "string",
"description": "Name of the attached document to the one-off submission."
}
}
}
},
"expire_at": {
"type": "string",
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
@@ -5198,6 +5373,15 @@
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
"default": false
},
"require_email_2fa": {
"type": "boolean",
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
"default": false
},
"invite_by": {
"type": "string",
"description": "Set the role name of the previous party that should invite this party via email."
},
"fields": {
"type": "array",
"description": "A list of configurations for document form fields.",
@@ -5336,6 +5520,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -5389,6 +5582,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -5461,7 +5661,6 @@
"type": "object",
"required": [
"id",
"submission_id",
"uuid",
"email",
"slug",
@@ -5550,6 +5749,53 @@
"awaiting"
]
},
"values": {
"type": "array",
"description": "An array of pre-filled values for the submitter.",
"items": {
"type": "object",
"required": [
"field",
"value"
],
"properties": {
"field": {
"type": "string",
"description": "Document template field name."
},
"value": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
}
]
}
}
],
"description": "Pre-filled value of the field."
}
}
}
},
"role": {
"type": "string",
"description": "The role of the submitter."
@@ -5661,7 +5907,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -5687,6 +5934,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -5710,6 +5961,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -5757,27 +6015,6 @@
}
}
},
"documents": {
"type": "array",
"description": "List of documents attached to the one-off submission.",
"items": {
"type": "object",
"required": [
"attachment_uuid",
"name"
],
"properties": {
"attachment_uuid": {
"type": "string",
"description": "Unique indentifier of attached document to the one-off submission."
},
"name": {
"type": "string",
"description": "Name of the attached document to the one-off submission."
}
}
}
},
"expire_at": {
"type": "string",
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
@@ -6078,6 +6315,10 @@
"event_timestamp": {
"type": "string",
"description": "Date and time when the event was triggered."
},
"data": {
"type": "object",
"description": "Additional event details object."
}
}
}
@@ -6185,7 +6426,8 @@
"id": 12,
"submitter_id": 7,
"event_type": "view_form",
"event_timestamp": "2023-12-14T15:47:17.351Z"
"event_timestamp": "2023-12-14T15:47:17.351Z",
"data": {}
}
],
"values": [
@@ -6435,6 +6677,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -6488,6 +6739,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -6990,6 +7248,10 @@
"event_timestamp": {
"type": "string",
"description": "Date and time when the event was triggered."
},
"data": {
"type": "object",
"description": "Additional event details object."
}
}
}
@@ -7126,7 +7388,8 @@
"id": 12,
"submitter_id": 7,
"event_type": "view_form",
"event_timestamp": "2023-12-14T15:48:17.351Z"
"event_timestamp": "2023-12-14T15:48:17.351Z",
"data": {}
}
],
"values": [
@@ -7346,7 +7609,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -7372,6 +7636,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -7395,6 +7663,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -7793,7 +8068,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -7819,6 +8095,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -7842,6 +8122,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -8294,7 +8581,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -8320,6 +8608,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -8343,6 +8635,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -8674,7 +8973,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -8812,6 +9112,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -8865,6 +9174,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -8989,7 +9305,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -9015,6 +9332,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -9038,6 +9359,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -9369,7 +9697,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"role": {
@@ -9515,6 +9844,15 @@
],
"default": "black"
},
"background": {
"type": "string",
"description": "Field box background color.",
"enum": [
"black",
"white",
"blue"
]
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value.",
@@ -9568,6 +9906,13 @@
}
],
"default": false
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
@@ -9702,7 +10047,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -9728,6 +10074,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -9751,6 +10101,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
@@ -10169,7 +10526,8 @@
"stamp",
"payment",
"phone",
"verification"
"verification",
"strikethrough"
]
},
"required": {
@@ -10195,6 +10553,10 @@
"type": "string",
"description": "Font color of the field value."
},
"background": {
"type": "string",
"description": "Field box background color."
},
"align": {
"type": "string",
"description": "Horizontal alignment of the field text value."
@@ -10218,6 +10580,13 @@
"mask": {
"type": "boolean",
"description": "Indicates if the field is masked on the document."
},
"reasons": {
"description": "An array of signature reasons to choose from.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
+4
View File
@@ -281,6 +281,10 @@ Get submission creation, completion, expiration, and archiving notifications usi
"event_timestamp": {
"type": "string",
"description": "Date and time when the event was triggered."
},
"data": {
"type": "object",
"description": "Additional event details object."
}
}
}
+38 -6
View File
@@ -1,7 +1,35 @@
# frozen_string_literal: true
module DownloadUtils
LOCALHOSTS = %w[0.0.0.0 127.0.0.1 localhost].freeze
LOCALHOSTS = Set[
'0.0.0.0',
'127.0.0.1',
'127.0.1.1',
'localhost',
'localhost.localdomain',
'::1',
'[::1]',
'ip6-localhost',
'ip6-loopback',
'127.0.0.0',
'127.255.255.255',
'::',
'0:0:0:0:0:0:0:1',
'[0:0:0:0:0:0:0:1]',
'0000:0000:0000:0000:0000:0000:0000:0001',
'[0000:0000:0000:0000:0000:0000:0000:0001]',
'::0',
'0::0',
'::ffff:127.0.0.1',
'[::ffff:127.0.0.1]',
'::ffff:7f00:1',
'[::ffff:7f00:1]',
'local',
'localhost.local',
'ip6-localnet',
'ip6-allnodes',
'ip6-allrouters'
].freeze
UnableToDownload = Class.new(StandardError)
@@ -14,10 +42,7 @@ module DownloadUtils
Addressable::URI.parse(url).normalize
end
if Docuseal.multitenant?
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
end
validate_uri!(uri) if Docuseal.multitenant?
resp = conn.get(uri)
@@ -26,9 +51,16 @@ module DownloadUtils
resp
end
def validate_uri!(uri)
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
end
def conn
Faraday.new do |faraday|
faraday.response :follow_redirects
faraday.response :follow_redirects, callback: lambda { |_, new_env|
validate_uri!(new_env[:url]) if Docuseal.multitenant?
}
end
end
end
+5 -1
View File
@@ -71,7 +71,11 @@ module Params
end
def validate_submitter(submitter_params)
required(submitter_params, %i[email phone name])
if submitter_params['invite_by'].present?
required(submitter_params, :role)
else
required(submitter_params, %i[email phone name])
end
type(submitter_params, :name, String)
type(submitter_params, :reply_to, String)
+10 -2
View File
@@ -81,7 +81,7 @@ module Submissions
next if submission.submitters.blank?
maybe_add_invite_submitters(submission, template)
maybe_add_invite_submitters(submission, template, attrs[:submitters])
submission.template = nil unless with_template
@@ -102,8 +102,16 @@ module Submissions
end
end
def maybe_add_invite_submitters(submission, template)
def maybe_add_invite_submitters(submission, template, submitter_attrs)
template.submitters.each_with_index do |item, index|
submitter_attr = submitter_attrs.find { |e| e['role'].to_s.casecmp?(item['name'].to_s) }
if submitter_attr && submitter_attr['invite_by'].present?
invite_by_uuid = template.submitters.find { |s| s['name'] == submitter_attr['invite_by'] }&.dig('uuid')
item = item.merge('invite_by_uuid' => invite_by_uuid) if invite_by_uuid
end
next if item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank?
next if submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
+10 -3
View File
@@ -522,10 +522,17 @@ module Submissions
if field['type'].in?(%w[multiple radio])
option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
option_name = option['value'].presence
option_name ||= "#{I18n.t('option', locale: locale)} #{field['options'].index(option) + 1}"
value =
if option
option_name = option['value'].presence
option_name ||= "#{I18n.t('option', locale: locale)} #{field['options'].index(option) + 1}"
value = Array.wrap(value).include?(option_name)
Array.wrap(value).include?(option_name)
else
Rollbar.error("Invalid option: #{field['uuid']}") if defined?(Rollbar)
false
end
end
next unless value == true
+3 -1
View File
@@ -106,7 +106,8 @@ module Submitters
if AccountConfig.exists?(account_id: submitter.submission.account_id,
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
value: true) &&
submitter.submission.submitters.all?(&:completed_at?)
submitter.submission.submitters.all?(&:completed_at?) &&
submitter.submission.template_fields.none? { |f| f['type'] == 'verification' }
return [submitter.submission.combined_document_attachment || Submissions::EnsureCombinedGenerated.call(submitter)]
end
@@ -157,6 +158,7 @@ module Submitters
preferences['send_email'] = params['send_email'].in?(TRUE_VALUES) if params.key?('send_email')
preferences['send_sms'] = params['send_sms'].in?(TRUE_VALUES) if params.key?('send_sms')
preferences['require_phone_2fa'] = params['require_phone_2fa'].in?(TRUE_VALUES) if params.key?('require_phone_2fa')
preferences['require_email_2fa'] = params['require_email_2fa'].in?(TRUE_VALUES) if params.key?('require_email_2fa')
preferences['bcc_completed'] = params['bcc_completed'] if params.key?('bcc_completed')
preferences['reply_to'] = params['reply_to'] if params.key?('reply_to')
preferences['go_to_last'] = params['go_to_last'] if params.key?('go_to_last')