Compare commits

..

8 Commits

Author SHA1 Message Date
Alex Turchyn 8c4cbd86f7
Merge from docusealco/wip
4 weeks ago
Pete Matsyburka eaedaa96bb fix rubocop
1 month ago
Pete Matsyburka bd7ad5fce8 update gems
1 month ago
Pete Matsyburka 759dac1b70 update schema
1 month ago
Pete Matsyburka 38577c6235 fix dynamic doc fields assignment
1 month ago
Pete Matsyburka b24fff0f55 fix rtl stamp
1 month ago
Pete Matsyburka 9e0efeb092 fix unicode in stamp
1 month ago
Pete Matsyburka 41152f90fc fix erblint
1 month ago

@ -51,6 +51,15 @@ Style/NumericPredicate:
Style/MinMaxComparison: Style/MinMaxComparison:
Enabled: false Enabled: false
Style/EmptyClassDefinition:
Enabled: false
Style/OneClassPerFile:
Enabled: false
Layout/MultilineMethodCallIndentation:
Enabled: false
Naming/PredicateMethod: Naming/PredicateMethod:
Enabled: false Enabled: false

@ -2,20 +2,17 @@ FROM ruby:4.0.1-alpine AS download
WORKDIR /fonts WORKDIR /fonts
RUN apk --no-cache add fontforge wget && \ RUN apk --no-cache add wget && \
wget https://github.com/satbyy/go-noto-universal/releases/download/v7.0/GoNotoKurrent-Regular.ttf && \ wget https://github.com/satbyy/go-noto-universal/releases/download/v7.0/GoNotoKurrent-Regular.ttf && \
wget https://github.com/satbyy/go-noto-universal/releases/download/v7.0/GoNotoKurrent-Bold.ttf && \ wget https://github.com/satbyy/go-noto-universal/releases/download/v7.0/GoNotoKurrent-Bold.ttf && \
wget https://github.com/impallari/DancingScript/raw/master/fonts/DancingScript-Regular.otf && \ wget https://github.com/impallari/DancingScript/raw/master/fonts/DancingScript-Regular.otf && \
wget https://cdn.jsdelivr.net/gh/notofonts/notofonts.github.io/fonts/NotoSansSymbols2/hinted/ttf/NotoSansSymbols2-Regular.ttf && \ wget https://raw.githubusercontent.com/impallari/DancingScript/master/OFL.txt && \
wget https://github.com/Maxattax97/gnu-freefont/raw/master/ttf/FreeSans.ttf && \ wget https://raw.githubusercontent.com/notofonts/noto-fonts/refs/heads/main/LICENSE && \
wget https://github.com/impallari/DancingScript/raw/master/OFL.txt && \
wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \ wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \
wget -O pdfium-linux.tgz "https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-musl-$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/').tgz" && \ wget -O pdfium-linux.tgz "https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-musl-$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/').tgz" && \
mkdir -p /pdfium-linux && \ mkdir -p /pdfium-linux && \
tar -xzf pdfium-linux.tgz -C /pdfium-linux tar -xzf pdfium-linux.tgz -C /pdfium-linux
RUN fontforge -lang=py -c 'font1 = fontforge.open("FreeSans.ttf"); font2 = fontforge.open("NotoSansSymbols2-Regular.ttf"); font1.mergeFonts(font2); font1.generate("FreeSans.ttf")'
FROM ruby:4.0.1-alpine AS webpack FROM ruby:4.0.1-alpine AS webpack
ENV RAILS_ENV=production ENV RAILS_ENV=production
@ -51,7 +48,7 @@ ENV OPENSSL_CONF=/etc/openssl_legacy.cnf
WORKDIR /app WORKDIR /app
RUN apk add --no-cache libpq vips redis vips-heif ttf-freefont onnxruntime && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf RUN apk add --no-cache libpq vips redis vips-heif fontconfig onnxruntime
RUN addgroup -g 2000 docuseal && adduser -u 2000 -G docuseal -s /bin/sh -D -h /home/docuseal docuseal RUN addgroup -g 2000 docuseal && adduser -u 2000 -G docuseal -s /bin/sh -D -h /home/docuseal docuseal
@ -82,14 +79,14 @@ COPY --chown=docuseal:docuseal ./tmp ./tmp
COPY --chown=docuseal:docuseal LICENSE LICENSE_ADDITIONAL_TERMS README.md Rakefile config.ru .version ./ COPY --chown=docuseal:docuseal LICENSE LICENSE_ADDITIONAL_TERMS README.md Rakefile config.ru .version ./
COPY --chown=docuseal:docuseal .version ./public/version COPY --chown=docuseal:docuseal .version ./public/version
COPY --chown=docuseal:docuseal --from=download /fonts/GoNotoKurrent-Regular.ttf /fonts/GoNotoKurrent-Bold.ttf /fonts/DancingScript-Regular.otf /fonts/OFL.txt /fonts COPY --chown=docuseal:docuseal --from=download /fonts/GoNotoKurrent-Regular.ttf /fonts/GoNotoKurrent-Bold.ttf /fonts/DancingScript-Regular.otf /fonts/OFL.txt /fonts/LICENSE /fonts/
COPY --from=download /fonts/FreeSans.ttf /usr/share/fonts/freefont
COPY --from=download /pdfium-linux/lib/libpdfium.so /usr/lib/libpdfium.so COPY --from=download /pdfium-linux/lib/libpdfium.so /usr/lib/libpdfium.so
COPY --from=download /pdfium-linux/licenses/pdfium.txt /usr/lib/libpdfium-LICENSE.txt COPY --from=download /pdfium-linux/licenses/pdfium.txt /usr/lib/libpdfium-LICENSE.txt
COPY --chown=docuseal:docuseal --from=download /model.onnx /app/tmp/model.onnx COPY --chown=docuseal:docuseal --from=download /model.onnx /app/tmp/model.onnx
COPY --chown=docuseal:docuseal --from=webpack /app/public/packs ./public/packs COPY --chown=docuseal:docuseal --from=webpack /app/public/packs ./public/packs
RUN ln -s /fonts /app/public/fonts && \ RUN mkdir -p /app/public/fonts && ln -s /fonts/DancingScript-Regular.otf /app/public/fonts/ && \
mkdir -p /usr/share/fonts/noto && ln -s /fonts/GoNotoKurrent-Regular.ttf /usr/share/fonts/noto/ && ln -s /fonts/GoNotoKurrent-Bold.ttf /usr/share/fonts/noto/ && fc-cache -f && \
bundle exec bootsnap precompile -j 1 --gemfile app/ lib/ && \ bundle exec bootsnap precompile -j 1 --gemfile app/ lib/ && \
chown -R docuseal:docuseal /app/tmp/cache chown -R docuseal:docuseal /app/tmp/cache

@ -1,7 +1,7 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
action_text-trix (2.1.17) action_text-trix (2.1.18)
railties railties
actioncable (8.1.3) actioncable (8.1.3)
actionpack (= 8.1.3) actionpack (= 8.1.3)
@ -75,16 +75,16 @@ GEM
securerandom (>= 0.3) securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5) tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1) uri (>= 0.13.1)
addressable (2.8.8) addressable (2.8.9)
public_suffix (>= 2.0.2, < 8.0) public_suffix (>= 2.0.2, < 8.0)
annotaterb (4.20.0) annotaterb (4.22.0)
activerecord (>= 6.0.0) activerecord (>= 6.0.0)
activesupport (>= 6.0.0) activesupport (>= 6.0.0)
arabic-letter-connector (0.1.1) arabic-letter-connector (0.1.1)
ast (2.4.3) ast (2.4.3)
aws-eventstream (1.4.0) aws-eventstream (1.4.0)
aws-partitions (1.1209.0) aws-partitions (1.1233.0)
aws-sdk-core (3.241.4) aws-sdk-core (3.244.0)
aws-eventstream (~> 1, >= 1.3.0) aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0) aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9) aws-sigv4 (~> 1.9)
@ -92,15 +92,15 @@ GEM
bigdecimal bigdecimal
jmespath (~> 1, >= 1.6.1) jmespath (~> 1, >= 1.6.1)
logger logger
aws-sdk-kms (1.121.0) aws-sdk-kms (1.123.0)
aws-sdk-core (~> 3, >= 3.241.4) aws-sdk-core (~> 3, >= 3.244.0)
aws-sigv4 (~> 1.5) aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.212.0) aws-sdk-s3 (1.218.0)
aws-sdk-core (~> 3, >= 3.241.4) aws-sdk-core (~> 3, >= 3.244.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5) aws-sigv4 (~> 1.5)
aws-sdk-secretsmanager (1.128.0) aws-sdk-secretsmanager (1.129.0)
aws-sdk-core (~> 3, >= 3.241.4) aws-sdk-core (~> 3, >= 3.244.0)
aws-sigv4 (~> 1.5) aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1) aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
@ -116,11 +116,11 @@ GEM
erubi (~> 1.4) erubi (~> 1.4)
parser (>= 2.4) parser (>= 2.4)
smart_properties smart_properties
bigdecimal (4.0.1) bigdecimal (4.1.0)
bindex (0.8.1) bindex (0.8.1)
bootsnap (1.21.1) bootsnap (1.23.0)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (7.1.2) brakeman (8.0.4)
racc racc
builder (3.3.0) builder (3.3.0)
bullet (8.1.0) bullet (8.1.0)
@ -193,7 +193,7 @@ GEM
factory_bot_rails (6.5.1) factory_bot_rails (6.5.1)
factory_bot (~> 6.5) factory_bot (~> 6.5)
railties (>= 6.1.0) railties (>= 6.1.0)
faker (3.6.0) faker (3.6.1)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (2.14.1) faraday (2.14.1)
faraday-net_http (>= 2.0, < 3.5) faraday-net_http (>= 2.0, < 3.5)
@ -203,17 +203,17 @@ GEM
faraday (>= 1, < 3) faraday (>= 1, < 3)
faraday-net_http (3.4.2) faraday-net_http (3.4.2)
net-http (~> 0.5) net-http (~> 0.5)
ferrum (0.17.1) ferrum (0.17.2)
addressable (~> 2.5) addressable (~> 2.5)
base64 (~> 0.2) base64 (~> 0.2)
concurrent-ruby (~> 1.1) concurrent-ruby (~> 1.1)
webrick (~> 1.7) webrick (~> 1.7)
websocket-driver (~> 0.7) websocket-driver (~> 0.7)
ffi (1.17.3-aarch64-linux-gnu) ffi (1.17.4-aarch64-linux-gnu)
ffi (1.17.3-aarch64-linux-musl) ffi (1.17.4-aarch64-linux-musl)
ffi (1.17.3-arm64-darwin) ffi (1.17.4-arm64-darwin)
ffi (1.17.3-x86_64-linux-gnu) ffi (1.17.4-x86_64-linux-gnu)
ffi (1.17.3-x86_64-linux-musl) ffi (1.17.4-x86_64-linux-musl)
foreman (0.90.0) foreman (0.90.0)
thor (~> 1.4) thor (~> 1.4)
geom2d (0.4.1) geom2d (0.4.1)
@ -229,7 +229,7 @@ GEM
retriable (~> 3.1) retriable (~> 3.1)
google-apis-iamcredentials_v1 (0.26.0) google-apis-iamcredentials_v1 (0.26.0)
google-apis-core (>= 0.15.0, < 2.a) google-apis-core (>= 0.15.0, < 2.a)
google-apis-storage_v1 (0.59.0) google-apis-storage_v1 (0.61.0)
google-apis-core (>= 0.15.0, < 2.a) google-apis-core (>= 0.15.0, < 2.a)
google-cloud-core (1.8.0) google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a) google-cloud-env (>= 1.0, < 3.a)
@ -237,8 +237,8 @@ GEM
google-cloud-env (2.3.1) google-cloud-env (2.3.1)
base64 (~> 0.2) base64 (~> 0.2)
faraday (>= 1.0, < 3.a) faraday (>= 1.0, < 3.a)
google-cloud-errors (1.5.0) google-cloud-errors (1.6.0)
google-cloud-storage (1.58.0) google-cloud-storage (1.59.0)
addressable (~> 2.8) addressable (~> 2.8)
digest-crc (~> 0.4) digest-crc (~> 0.4)
google-apis-core (>= 0.18, < 2) google-apis-core (>= 0.18, < 2)
@ -248,7 +248,7 @@ GEM
googleauth (~> 1.9) googleauth (~> 1.9)
mini_mime (~> 1.0) mini_mime (~> 1.0)
google-logging-utils (0.2.0) google-logging-utils (0.2.0)
googleauth (1.16.1) googleauth (1.16.2)
faraday (>= 1.0, < 3.a) faraday (>= 1.0, < 3.a)
google-cloud-env (~> 2.2) google-cloud-env (~> 2.2)
google-logging-utils (~> 0.1) google-logging-utils (~> 0.1)
@ -257,7 +257,7 @@ GEM
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a) signet (>= 0.16, < 2.a)
hashdiff (1.2.1) hashdiff (1.2.1)
hexapdf (1.5.0) hexapdf (1.6.0)
cmdparse (~> 3.0, >= 3.0.3) cmdparse (~> 3.0, >= 3.0.3)
geom2d (~> 0.4, >= 0.4.1) geom2d (~> 0.4, >= 0.4.1)
openssl (>= 2.2.1) openssl (>= 2.2.1)
@ -274,7 +274,7 @@ GEM
rdoc (>= 4.0.0) rdoc (>= 4.0.0)
reline (>= 0.4.2) reline (>= 0.4.2)
jmespath (1.6.2) jmespath (1.6.2)
json (2.19.2) json (2.19.3)
jwt (3.1.2) jwt (3.1.2)
base64 base64
language_server-protocol (3.17.0.5) language_server-protocol (3.17.0.5)
@ -311,7 +311,7 @@ GEM
mini_magick (5.3.1) mini_magick (5.3.1)
logger logger
mini_mime (1.1.5) mini_mime (1.1.5)
minitest (6.0.2) minitest (6.0.3)
drb (~> 2.0) drb (~> 2.0)
prism (~> 1.5) prism (~> 1.5)
msgpack (1.8.0) msgpack (1.8.0)
@ -339,7 +339,7 @@ GEM
nokogiri (1.19.2-x86_64-linux-musl) nokogiri (1.19.2-x86_64-linux-musl)
racc (~> 1.4) racc (~> 1.4)
numo-narray-alt (0.10.3) numo-narray-alt (0.10.3)
oj (3.16.13) oj (3.16.16)
bigdecimal (>= 3.0) bigdecimal (>= 3.0)
ostruct (>= 0.2) ostruct (>= 0.2)
onnxruntime (0.10.1-aarch64-linux) onnxruntime (0.10.1-aarch64-linux)
@ -348,16 +348,17 @@ GEM
ffi ffi
onnxruntime (0.10.1-x86_64-linux) onnxruntime (0.10.1-x86_64-linux)
ffi ffi
openssl (4.0.0) openssl (4.0.1)
orm_adapter (0.5.0) orm_adapter (0.5.0)
os (1.1.4) os (1.1.4)
ostruct (0.6.3) ostruct (0.6.3)
package_json (0.2.0) package_json (0.2.0)
pagy (43.2.8) pagy (43.4.4)
json json
uri
yaml yaml
parallel (1.27.0) parallel (1.28.0)
parser (3.3.10.1) parser (3.3.11.1)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
pg (1.6.3-aarch64-linux) pg (1.6.3-aarch64-linux)
@ -367,8 +368,8 @@ GEM
pg (1.6.3-x86_64-linux-musl) pg (1.6.3-x86_64-linux-musl)
pp (0.6.3) pp (0.6.3)
prettyprint prettyprint
pretender (0.6.0) pretender (1.0.0)
actionpack (>= 7.1) actionpack (>= 7.2)
prettyprint (0.2.0) prettyprint (0.2.0)
prism (1.9.0) prism (1.9.0)
pry (0.16.0) pry (0.16.0)
@ -380,11 +381,11 @@ GEM
psych (5.3.1) psych (5.3.1)
date date
stringio stringio
public_suffix (7.0.2) public_suffix (7.0.5)
puma (7.2.0) puma (7.2.0)
nio4r (~> 2.0) nio4r (~> 2.0)
racc (1.8.1) racc (1.8.1)
rack (3.2.5) rack (3.2.6)
rack-proxy (0.7.7) rack-proxy (0.7.7)
rack rack
rack-session (2.1.1) rack-session (2.1.1)
@ -433,7 +434,7 @@ GEM
erb erb
psych (>= 4.0.0) psych (>= 4.0.0)
tsort tsort
redis-client (0.26.4) redis-client (0.28.0)
connection_pool connection_pool
regexp_parser (2.11.3) regexp_parser (2.11.3)
reline (0.6.3) reline (0.6.3)
@ -447,7 +448,7 @@ GEM
responders (3.2.0) responders (3.2.0)
actionpack (>= 7.0) actionpack (>= 7.0)
railties (>= 7.0) railties (>= 7.0)
retriable (3.1.2) retriable (3.4.1)
rexml (3.4.4) rexml (3.4.4)
rotp (6.3.0) rotp (6.3.0)
rouge (4.7.0) rouge (4.7.0)
@ -460,19 +461,19 @@ GEM
rspec-expectations (3.13.5) rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-mocks (3.13.7) rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0) rspec-support (~> 3.13.0)
rspec-rails (8.0.2) rspec-rails (8.0.4)
actionpack (>= 7.2) actionpack (>= 7.2)
activesupport (>= 7.2) activesupport (>= 7.2)
railties (>= 7.2) railties (>= 7.2)
rspec-core (~> 3.13) rspec-core (>= 3.13.0, < 5.0.0)
rspec-expectations (~> 3.13) rspec-expectations (>= 3.13.0, < 5.0.0)
rspec-mocks (~> 3.13) rspec-mocks (>= 3.13.0, < 5.0.0)
rspec-support (~> 3.13) rspec-support (>= 3.13.0, < 5.0.0)
rspec-support (3.13.6) rspec-support (3.13.7)
rubocop (1.82.1) rubocop (1.86.0)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2) language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0) lint_roller (~> 1.1.0)
@ -480,10 +481,10 @@ GEM
parser (>= 3.3.0.2) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.48.0, < 2.0) rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.49.0) rubocop-ast (1.49.1)
parser (>= 3.3.7.2) parser (>= 3.3.7.2)
prism (~> 1.7) prism (~> 1.7)
rubocop-performance (1.26.1) rubocop-performance (1.26.1)
@ -508,14 +509,14 @@ GEM
rubyzip (>= 3.2.2) rubyzip (>= 3.2.2)
rubyzip (3.2.2) rubyzip (3.2.2)
securerandom (0.4.1) securerandom (0.4.1)
semantic_range (3.1.0) semantic_range (3.1.1)
shakapacker (9.5.0) shakapacker (9.7.0)
activesupport (>= 5.2) activesupport (>= 5.2)
package_json package_json
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 5.2) railties (>= 5.2)
semantic_range (>= 2.3.0) semantic_range (>= 2.3.0)
sidekiq (8.1.0) sidekiq (8.1.2)
connection_pool (>= 3.0.0) connection_pool (>= 3.0.0)
json (>= 2.16.0) json (>= 2.16.0)
logger (>= 1.7.0) logger (>= 1.7.0)
@ -533,22 +534,22 @@ GEM
simplecov-html (0.13.2) simplecov-html (0.13.2)
simplecov_json_formatter (0.1.4) simplecov_json_formatter (0.1.4)
smart_properties (1.17.0) smart_properties (1.17.0)
sqlite3 (2.9.0-aarch64-linux-gnu) sqlite3 (2.9.2-aarch64-linux-gnu)
sqlite3 (2.9.0-aarch64-linux-musl) sqlite3 (2.9.2-aarch64-linux-musl)
sqlite3 (2.9.0-arm64-darwin) sqlite3 (2.9.2-arm64-darwin)
sqlite3 (2.9.0-x86_64-linux-gnu) sqlite3 (2.9.2-x86_64-linux-gnu)
sqlite3 (2.9.0-x86_64-linux-musl) sqlite3 (2.9.2-x86_64-linux-musl)
stringio (3.2.0) stringio (3.2.0)
strip_attributes (2.0.1) strip_attributes (2.0.1)
activemodel (>= 3.0, < 9.0) activemodel (>= 3.0, < 9.0)
strscan (3.1.7) strscan (3.1.8)
thor (1.5.0) thor (1.5.0)
timeout (0.6.1) timeout (0.6.1)
trailblazer-option (0.1.2) trailblazer-option (0.1.2)
trilogy (2.10.0) trilogy (2.12.2)
bigdecimal bigdecimal
tsort (0.2.0) tsort (0.2.0)
turbo-rails (2.0.21) turbo-rails (2.0.23)
actionpack (>= 7.1.0) actionpack (>= 7.1.0)
railties (>= 7.1.0) railties (>= 7.1.0)
twitter_cldr (6.14.0) twitter_cldr (6.14.0)
@ -558,7 +559,7 @@ GEM
tzinfo tzinfo
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
tzinfo-data (1.2025.3) tzinfo-data (1.2026.1)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
uber (0.1.0) uber (0.1.0)
unicode-display_width (3.2.0) unicode-display_width (3.2.0)
@ -569,12 +570,11 @@ GEM
useragent (0.16.11) useragent (0.16.11)
warden (1.2.9) warden (1.2.9)
rack (>= 2.0.9) rack (>= 2.0.9)
web-console (4.2.1) web-console (4.3.0)
actionview (>= 6.0.0) actionview (>= 8.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0) bindex (>= 0.4.0)
railties (>= 6.0.0) railties (>= 8.0.0)
webmock (3.26.1) webmock (3.26.2)
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)

@ -9,7 +9,7 @@ module Api
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@template], records: [@template],
associations: [schema_documents: :preview_images_attachments] associations: [{ schema_documents: :preview_images_attachments }]
).call ).call
cloned_template = Templates::Clone.call( cloned_template = Templates::Clone.call(

@ -3,7 +3,7 @@
class EsignSettingsController < ApplicationController class EsignSettingsController < ApplicationController
DEFAULT_CERT_NAME = 'DocuSeal Self-Host Autogenerated' DEFAULT_CERT_NAME = 'DocuSeal Self-Host Autogenerated'
CertFormRecord = Struct.new(:name, :file, :password, keyword_init: true) do CertFormRecord = Struct.new(:name, :file, :password) do
include ActiveModel::Validations include ActiveModel::Validations
def to_key def to_key

@ -26,7 +26,7 @@ class SubmissionsController < ApplicationController
unless @submission.submitters.all?(&:completed_at?) unless @submission.submitters.all?(&:completed_at?)
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@submission], records: [@submission],
associations: [submitters: :start_form_submission_events] associations: [{ submitters: :start_form_submission_events }]
).call ).call
end end

@ -8,7 +8,7 @@ class TemplatesCloneAndReplaceController < ApplicationController
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@template], records: [@template],
associations: [schema_documents: :preview_images_attachments] associations: [{ schema_documents: :preview_images_attachments }]
).call ).call
cloned_template = Templates::Clone.call(@template, author: current_user) cloned_template = Templates::Clone.call(@template, author: current_user)

@ -12,7 +12,7 @@ class TemplatesCloneController < ApplicationController
def create def create
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@base_template], records: [@base_template],
associations: [schema_documents: :preview_images_attachments] associations: [{ schema_documents: :preview_images_attachments }]
).call ).call
@template = Templates::Clone.call(@base_template, author: current_user, @template = Templates::Clone.call(@base_template, author: current_user,

@ -29,7 +29,7 @@ class TemplatesController < ApplicationController
def edit def edit
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@template], records: [@template],
associations: [schema_documents: [:blob, { preview_images_attachments: :blob }]] associations: [{ schema_documents: [:blob, { preview_images_attachments: :blob }] }]
).call ).call
@template_data = @template_data =

@ -30,7 +30,7 @@ class TemplatesDebugController < ApplicationController
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@template], records: [@template],
associations: [schema_documents: { preview_images_attachments: :blob }] associations: [{ schema_documents: { preview_images_attachments: :blob } }]
).call ).call
@template_data = @template_data =

@ -58,8 +58,8 @@ class TemplatesPreferencesController < ApplicationController
default_expire_at_duration shared_link_2fa default_expire_at request_email_enabled default_expire_at_duration shared_link_2fa default_expire_at request_email_enabled
completed_notification_email_subject completed_notification_email_body completed_notification_email_subject completed_notification_email_body
completed_notification_email_enabled completed_notification_email_attach_audit] + completed_notification_email_enabled completed_notification_email_attach_audit] +
[completed_message: %i[title body], [{ completed_message: %i[title body],
submitters: [%i[uuid request_email_subject request_email_body]], link_form_fields: []] submitters: [%i[uuid request_email_subject request_email_body]], link_form_fields: [] }]
).tap do |attrs| ).tap do |attrs|
attrs[:preferences].delete(:submitters) if params[:request_email_per_submitter] != '1' attrs[:preferences].delete(:submitters) if params[:request_email_per_submitter] != '1'

@ -6,7 +6,7 @@ class TemplatesPreviewController < ApplicationController
def show def show
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [@template], records: [@template],
associations: [schema_documents: { preview_images_attachments: :blob }] associations: [{ schema_documents: { preview_images_attachments: :blob } }]
).call ).call
@template_data = @template_data =

@ -7,8 +7,8 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# body :text not null # body :text not null
# head :text # head :text
# sha1 :text not null # sha1 :string not null
# uuid :uuid not null # uuid :string not null
# created_at :datetime not null # created_at :datetime not null
# updated_at :datetime not null # updated_at :datetime not null
# template_id :bigint not null # template_id :bigint not null

@ -20,7 +20,7 @@
<% end %> <% end %>
</p> </p>
</li> </li>
<% submitter_versions_index = @submission.submitters.preload(:submitter_versions).each_with_object({}) { |s, h| h[s.id] = s.submitter_versions.to_a.sort_by(&:created_at) } %> <% submitter_versions_index = @submission.submitters.preload(:submitter_versions).to_h { |s| [s.id, s.submitter_versions.to_a.sort_by(&:created_at)] } %>
<% @submission.submission_events.order(:event_timestamp).each do |event| %> <% @submission.submission_events.order(:event_timestamp).each do |event| %>
<% submitter = @submission.submitters.find { |e| e.id == event.submitter_id } %> <% submitter = @submission.submitters.find { |e| e.id == event.submitter_id } %>
<% bg_class = event_colors[submitters_uuids.index(submitter.uuid) % event_colors.length] %> <% bg_class = event_colors[submitters_uuids.index(submitter.uuid) % event_colors.length] %>
@ -47,7 +47,7 @@
<% elsif event.event_type == 'invite_party' && (invited_submitter = @submission.submitters.find { |e| e.uuid == event.data['uuid'] }) && (name = @submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name')) %> <% elsif event.event_type == 'invite_party' && (invited_submitter = @submission.submitters.find { |e| e.uuid == event.data['uuid'] }) && (name = @submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name')) %>
<%= t('submission_event_names.invite_party_by_html', invited_submitter_name: [invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' '), submitter_name:) %> <%= t('submission_event_names.invite_party_by_html', invited_submitter_name: [invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' '), submitter_name:) %>
<% elsif event.event_type == 'delegate_form' %> <% elsif event.event_type == 'delegate_form' %>
<% delegate_from = event.data['old_email'].presence || (versions.reverse.find { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone }) %> <% delegate_from = event.data['old_email'].presence || versions.rfind { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone } %>
<%= t('submission_event_names.delegate_form_by_html', from: delegate_from, to: event.data['email']) %> <%= t('submission_event_names.delegate_form_by_html', from: delegate_from, to: event.data['email']) %>
<% elsif event.event_type.include?('send_') %> <% elsif event.event_type.include?('send_') %>
<%= t("submission_event_names.#{event.event_type}_to_html", submitter_name:) %> <%= t("submission_event_names.#{event.event_type}_to_html", submitter_name:) %>

@ -96,7 +96,7 @@
<% submitters_index = @submission.submitters.index_by(&:uuid) %> <% submitters_index = @submission.submitters.index_by(&:uuid) %>
<% submitters_order_index = nil %> <% submitters_order_index = nil %>
<% attachments_index = ActiveStorage::Attachment.where(record: @submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %> <% 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) %> <% page_blob_struct = Struct.new(:url, :metadata) %>
<% 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] %> <% 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| %> <% schema.each do |item| %>
<% document = @submission.schema_documents.find { |e| e.uuid == item['attachment_uuid'] } %> <% document = @submission.schema_documents.find { |e| e.uuid == item['attachment_uuid'] } %>

@ -5,7 +5,7 @@
<% fields_index = Templates.build_field_areas_index(@submitter.submission.template_fields || @submitter.submission.template.fields) %> <% fields_index = Templates.build_field_areas_index(@submitter.submission.template_fields || @submitter.submission.template.fields) %>
<% values = @submitter.submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %> <% values = @submitter.submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %>
<% submitters_index = @submitter.submission.submitters.index_by(&:uuid) %> <% submitters_index = @submitter.submission.submitters.index_by(&:uuid) %>
<% page_blob_struct = Struct.new(:url, :metadata, keyword_init: true) %> <% page_blob_struct = Struct.new(:url, :metadata) %>
<% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %> <% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %>
<% font_scale = 1000.0 / PdfUtils::US_LETTER_W %> <% font_scale = 1000.0 / PdfUtils::US_LETTER_W %>
<% decline_modal_checkbox_uuid = nil %> <% decline_modal_checkbox_uuid = nil %>

@ -49,7 +49,7 @@
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
<%= link_to template_share_link_path(template), class: "absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2", data: { turbo_frame: :modal } do %> <%= link_to template_share_link_path(template), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', data: { turbo_frame: :modal } do %>
<span class="flex items-center justify-center space-x-2"> <span class="flex items-center justify-center space-x-2">
<%= svg_icon('link', class: 'w-4 h-4 md:w-6 md:h-6') %> <%= svg_icon('link', class: 'w-4 h-4 md:w-6 md:h-6') %>
<span><%= t('link') %></span> <span><%= t('link') %></span>

@ -1,3 +1,3 @@
# frozen_string_literal: true # frozen_string_literal: true
Pagy.options[:limit] = 10 Pagy::OPTIONS[:limit] = 10

@ -13,41 +13,41 @@
ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "btree_gin" enable_extension "btree_gin"
enable_extension "plpgsql" enable_extension "pg_catalog.plpgsql"
create_table "access_tokens", force: :cascade do |t| create_table "access_tokens", force: :cascade do |t|
t.bigint "user_id", null: false
t.text "token", null: false
t.text "sha256", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.text "sha256", null: false
t.text "token", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.index ["sha256"], name: "index_access_tokens_on_sha256", unique: true t.index ["sha256"], name: "index_access_tokens_on_sha256", unique: true
t.index ["user_id"], name: "index_access_tokens_on_user_id" t.index ["user_id"], name: "index_access_tokens_on_user_id"
end end
create_table "account_accesses", force: :cascade do |t| create_table "account_accesses", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "user_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.index ["account_id", "user_id"], name: "index_account_accesses_on_account_id_and_user_id", unique: true t.index ["account_id", "user_id"], name: "index_account_accesses_on_account_id_and_user_id", unique: true
end end
create_table "account_configs", force: :cascade do |t| create_table "account_configs", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.string "key", null: false
t.text "value", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "key", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.text "value", null: false
t.index ["account_id", "key"], name: "index_account_configs_on_account_id_and_key", unique: true t.index ["account_id", "key"], name: "index_account_configs_on_account_id_and_key", unique: true
t.index ["account_id"], name: "index_account_configs_on_account_id" t.index ["account_id"], name: "index_account_configs_on_account_id"
end end
create_table "account_linked_accounts", force: :cascade do |t| create_table "account_linked_accounts", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "linked_account_id", null: false
t.text "account_type", null: false t.text "account_type", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.bigint "linked_account_id", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["account_id", "linked_account_id"], name: "idx_on_account_id_linked_account_id_48ab9f79d2", unique: true t.index ["account_id", "linked_account_id"], name: "idx_on_account_id_linked_account_id_48ab9f79d2", unique: true
t.index ["account_id"], name: "index_account_linked_accounts_on_account_id" t.index ["account_id"], name: "index_account_linked_accounts_on_account_id"
@ -55,37 +55,37 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "accounts", force: :cascade do |t| create_table "accounts", force: :cascade do |t|
t.datetime "archived_at"
t.datetime "created_at", null: false
t.string "locale", null: false
t.string "name", null: false t.string "name", null: false
t.string "timezone", null: false t.string "timezone", null: false
t.string "locale", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "uuid", null: false t.string "uuid", null: false
t.datetime "archived_at"
t.index ["uuid"], name: "index_accounts_on_uuid", unique: true t.index ["uuid"], name: "index_accounts_on_uuid", unique: true
end end
create_table "active_storage_attachments", force: :cascade do |t| create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "uuid", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false t.bigint "blob_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "name", null: false
t.bigint "record_id", null: false
t.string "record_type", null: false
t.string "uuid", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "idx_on_record_type_record_id_name_blob_id_0be5805727" t.index ["record_type", "record_id", "name", "blob_id"], name: "idx_on_record_type_record_id_name_blob_id_0be5805727"
t.index ["uuid"], name: "index_active_storage_attachments_on_uuid" t.index ["uuid"], name: "index_active_storage_attachments_on_uuid"
end end
create_table "active_storage_blobs", force: :cascade do |t| create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.string "service_name", null: false
t.bigint "byte_size", null: false t.bigint "byte_size", null: false
t.string "checksum" t.string "checksum"
t.string "content_type"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "filename", null: false
t.string "key", null: false
t.text "metadata"
t.string "service_name", null: false
t.string "uuid" t.string "uuid"
t.index ["checksum"], name: "index_active_storage_blobs_on_checksum" t.index ["checksum"], name: "index_active_storage_blobs_on_checksum"
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
@ -99,26 +99,26 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "completed_documents", force: :cascade do |t| create_table "completed_documents", force: :cascade do |t|
t.bigint "submitter_id", null: false
t.string "sha256", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "sha256", null: false
t.bigint "submitter_id", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["sha256"], name: "index_completed_documents_on_sha256" t.index ["sha256"], name: "index_completed_documents_on_sha256"
t.index ["submitter_id"], name: "index_completed_documents_on_submitter_id" t.index ["submitter_id"], name: "index_completed_documents_on_submitter_id"
end end
create_table "completed_submitters", force: :cascade do |t| create_table "completed_submitters", force: :cascade do |t|
t.bigint "submitter_id", null: false
t.bigint "submission_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "template_id"
t.string "source", null: false
t.integer "sms_count", null: false
t.datetime "completed_at", null: false t.datetime "completed_at", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.boolean "is_first"
t.integer "sms_count", null: false
t.string "source", null: false
t.bigint "submission_id", null: false
t.bigint "submitter_id", null: false
t.bigint "template_id"
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "verification_method" t.string "verification_method"
t.boolean "is_first"
t.index ["account_id", "completed_at"], name: "index_completed_submitters_account_id_completed_at_is_first", where: "(is_first = true)" t.index ["account_id", "completed_at"], name: "index_completed_submitters_account_id_completed_at_is_first", where: "(is_first = true)"
t.index ["account_id", "completed_at"], name: "index_completed_submitters_on_account_id_and_completed_at" t.index ["account_id", "completed_at"], name: "index_completed_submitters_on_account_id_and_completed_at"
t.index ["submission_id"], name: "index_completed_submitters_on_submission_id", unique: true, where: "(is_first = true)" t.index ["submission_id"], name: "index_completed_submitters_on_submission_id", unique: true, where: "(is_first = true)"
@ -126,45 +126,45 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "console1984_commands", force: :cascade do |t| create_table "console1984_commands", force: :cascade do |t|
t.text "statements" t.datetime "created_at", null: false
t.bigint "sensitive_access_id" t.bigint "sensitive_access_id"
t.bigint "session_id", null: false t.bigint "session_id", null: false
t.datetime "created_at", null: false t.text "statements"
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["sensitive_access_id"], name: "index_console1984_commands_on_sensitive_access_id" t.index ["sensitive_access_id"], name: "index_console1984_commands_on_sensitive_access_id"
t.index ["session_id", "created_at", "sensitive_access_id"], name: "on_session_and_sensitive_chronologically" t.index ["session_id", "created_at", "sensitive_access_id"], name: "on_session_and_sensitive_chronologically"
end end
create_table "console1984_sensitive_accesses", force: :cascade do |t| create_table "console1984_sensitive_accesses", force: :cascade do |t|
t.datetime "created_at", null: false
t.text "justification" t.text "justification"
t.bigint "session_id", null: false t.bigint "session_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["session_id"], name: "index_console1984_sensitive_accesses_on_session_id" t.index ["session_id"], name: "index_console1984_sensitive_accesses_on_session_id"
end end
create_table "console1984_sessions", force: :cascade do |t| create_table "console1984_sessions", force: :cascade do |t|
t.text "reason"
t.bigint "user_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.text "reason"
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.index ["created_at"], name: "index_console1984_sessions_on_created_at" t.index ["created_at"], name: "index_console1984_sessions_on_created_at"
t.index ["user_id", "created_at"], name: "index_console1984_sessions_on_user_id_and_created_at" t.index ["user_id", "created_at"], name: "index_console1984_sessions_on_user_id_and_created_at"
end end
create_table "console1984_users", force: :cascade do |t| create_table "console1984_users", force: :cascade do |t|
t.string "username", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "username", null: false
t.index ["username"], name: "index_console1984_users_on_username" t.index ["username"], name: "index_console1984_users_on_username"
end end
create_table "document_generation_events", force: :cascade do |t| create_table "document_generation_events", force: :cascade do |t|
t.bigint "submitter_id", null: false
t.string "event_name", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "event_name", null: false
t.bigint "submitter_id", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["submitter_id", "event_name"], name: "index_document_generation_events_on_submitter_id_and_event_name", unique: true, where: "((event_name)::text = ANY ((ARRAY['start'::character varying, 'complete'::character varying])::text[]))" t.index ["submitter_id", "event_name"], name: "index_document_generation_events_on_submitter_id_and_event_name", unique: true, where: "((event_name)::text = ANY (ARRAY[('start'::character varying)::text, ('complete'::character varying)::text]))"
t.index ["submitter_id"], name: "index_document_generation_events_on_submitter_id" t.index ["submitter_id"], name: "index_document_generation_events_on_submitter_id"
end end
@ -190,31 +190,31 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
create_table "email_events", force: :cascade do |t| create_table "email_events", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.string "emailable_type", null: false t.datetime "created_at", null: false
t.text "data", null: false
t.string "email", null: false
t.bigint "emailable_id", null: false t.bigint "emailable_id", null: false
t.string "emailable_type", null: false
t.datetime "event_datetime", null: false
t.string "event_type", null: false
t.string "message_id", null: false t.string "message_id", null: false
t.string "tag", null: false t.string "tag", null: false
t.string "event_type", null: false
t.string "email", null: false
t.text "data", null: false
t.datetime "event_datetime", null: false
t.datetime "created_at", null: false
t.index ["account_id", "event_datetime"], name: "index_email_events_on_account_id_and_event_datetime" t.index ["account_id", "event_datetime"], name: "index_email_events_on_account_id_and_event_datetime"
t.index ["email"], name: "index_email_events_on_email" t.index ["email"], name: "index_email_events_on_email"
t.index ["email"], name: "index_email_events_on_email_event_types", where: "((event_type)::text = ANY ((ARRAY['bounce'::character varying, 'soft_bounce'::character varying, 'permanent_bounce'::character varying, 'complaint'::character varying, 'soft_complaint'::character varying])::text[]))" t.index ["email"], name: "index_email_events_on_email_event_types", where: "((event_type)::text = ANY (ARRAY[('bounce'::character varying)::text, ('soft_bounce'::character varying)::text, ('permanent_bounce'::character varying)::text, ('complaint'::character varying)::text, ('soft_complaint'::character varying)::text]))"
t.index ["emailable_type", "emailable_id"], name: "index_email_events_on_emailable" t.index ["emailable_type", "emailable_id"], name: "index_email_events_on_emailable"
t.index ["message_id"], name: "index_email_events_on_message_id" t.index ["message_id"], name: "index_email_events_on_message_id"
end end
create_table "email_messages", force: :cascade do |t| create_table "email_messages", force: :cascade do |t|
t.string "uuid", null: false
t.bigint "author_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.text "subject", null: false t.bigint "author_id", null: false
t.text "body", null: false t.text "body", null: false
t.string "sha1", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "sha1", null: false
t.text "subject", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "uuid", null: false
t.index ["account_id"], name: "index_email_messages_on_account_id" t.index ["account_id"], name: "index_email_messages_on_account_id"
t.index ["sha1"], name: "index_email_messages_on_sha1" t.index ["sha1"], name: "index_email_messages_on_sha1"
t.index ["uuid"], name: "index_email_messages_on_uuid" t.index ["uuid"], name: "index_email_messages_on_uuid"
@ -222,30 +222,30 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
create_table "encrypted_configs", force: :cascade do |t| create_table "encrypted_configs", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.string "key", null: false
t.text "value", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "key", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.text "value", null: false
t.index ["account_id", "key"], name: "index_encrypted_configs_on_account_id_and_key", unique: true t.index ["account_id", "key"], name: "index_encrypted_configs_on_account_id_and_key", unique: true
t.index ["account_id"], name: "index_encrypted_configs_on_account_id" t.index ["account_id"], name: "index_encrypted_configs_on_account_id"
end end
create_table "encrypted_user_configs", force: :cascade do |t| create_table "encrypted_user_configs", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "key", null: false
t.text "value", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "key", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.text "value", null: false
t.index ["user_id", "key"], name: "index_encrypted_user_configs_on_user_id_and_key", unique: true t.index ["user_id", "key"], name: "index_encrypted_user_configs_on_user_id_and_key", unique: true
t.index ["user_id"], name: "index_encrypted_user_configs_on_user_id" t.index ["user_id"], name: "index_encrypted_user_configs_on_user_id"
end end
create_table "lock_events", force: :cascade do |t| create_table "lock_events", force: :cascade do |t|
t.string "key", null: false
t.string "event_name", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "event_name", null: false
t.string "key", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["event_name", "key"], name: "index_lock_events_on_event_name_and_key", unique: true, where: "((event_name)::text = ANY ((ARRAY['start'::character varying, 'complete'::character varying])::text[]))" t.index ["event_name", "key"], name: "index_lock_events_on_event_name_and_key", unique: true, where: "((event_name)::text = ANY (ARRAY[('start'::character varying)::text, ('complete'::character varying)::text]))"
t.index ["key"], name: "index_lock_events_on_key" t.index ["key"], name: "index_lock_events_on_key"
end end
@ -262,31 +262,31 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "oauth_access_grants", force: :cascade do |t| create_table "oauth_access_grants", force: :cascade do |t|
t.bigint "resource_owner_id", null: false
t.bigint "application_id", null: false t.bigint "application_id", null: false
t.string "token", null: false t.string "code_challenge"
t.string "code_challenge_method"
t.datetime "created_at", null: false
t.integer "expires_in", null: false t.integer "expires_in", null: false
t.text "redirect_uri", null: false t.text "redirect_uri", null: false
t.string "scopes", default: "", null: false t.bigint "resource_owner_id", null: false
t.datetime "created_at", null: false
t.datetime "revoked_at" t.datetime "revoked_at"
t.string "code_challenge" t.string "scopes", default: "", null: false
t.string "code_challenge_method" t.string "token", null: false
t.index ["application_id"], name: "index_oauth_access_grants_on_application_id" t.index ["application_id"], name: "index_oauth_access_grants_on_application_id"
t.index ["resource_owner_id"], name: "index_oauth_access_grants_on_resource_owner_id" t.index ["resource_owner_id"], name: "index_oauth_access_grants_on_resource_owner_id"
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
end end
create_table "oauth_access_tokens", force: :cascade do |t| create_table "oauth_access_tokens", force: :cascade do |t|
t.bigint "resource_owner_id"
t.bigint "application_id", null: false t.bigint "application_id", null: false
t.string "token", null: false
t.string "refresh_token"
t.integer "expires_in"
t.string "scopes"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "revoked_at" t.integer "expires_in"
t.string "previous_refresh_token", default: "", null: false t.string "previous_refresh_token", default: "", null: false
t.string "refresh_token"
t.bigint "resource_owner_id"
t.datetime "revoked_at"
t.string "scopes"
t.string "token", null: false
t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id" t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id"
t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id" t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
@ -294,25 +294,25 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "oauth_applications", force: :cascade do |t| create_table "oauth_applications", force: :cascade do |t|
t.boolean "confidential", default: true, null: false
t.datetime "created_at", null: false
t.string "name", null: false t.string "name", null: false
t.string "uid", null: false
t.string "secret", null: false
t.text "redirect_uri" t.text "redirect_uri"
t.string "scopes", default: "", null: false t.string "scopes", default: "", null: false
t.boolean "confidential", default: true, null: false t.string "secret", null: false
t.datetime "created_at", null: false t.string "uid", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
end end
create_table "search_entries", force: :cascade do |t| create_table "search_entries", force: :cascade do |t|
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.tsvector "tsvector", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.tsvector "ngram" t.tsvector "ngram"
t.bigint "record_id", null: false
t.string "record_type", null: false
t.tsvector "tsvector", null: false
t.datetime "updated_at", null: false
t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_submission", where: "((record_type)::text = 'Submission'::text)", using: :gin t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_submission", where: "((record_type)::text = 'Submission'::text)", using: :gin
t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_submitter", where: "((record_type)::text = 'Submitter'::text)", using: :gin t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_submitter", where: "((record_type)::text = 'Submitter'::text)", using: :gin
t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_template", where: "((record_type)::text = 'Template'::text)", using: :gin t.index ["account_id", "ngram"], name: "index_search_entries_on_account_id_ngram_template", where: "((record_type)::text = 'Template'::text)", using: :gin
@ -323,15 +323,15 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "submission_events", force: :cascade do |t| create_table "submission_events", force: :cascade do |t|
t.bigint "submission_id", null: false t.bigint "account_id"
t.bigint "submitter_id" t.datetime "created_at", null: false
t.text "data", null: false t.text "data", null: false
t.string "event_type", null: false
t.datetime "event_timestamp", null: false t.datetime "event_timestamp", null: false
t.datetime "created_at", null: false t.string "event_type", null: false
t.bigint "submission_id", null: false
t.bigint "submitter_id"
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "account_id" t.index ["account_id", "created_at"], name: "index_submissions_events_on_sms_event_types", where: "((event_type)::text = ANY (ARRAY[('send_sms'::character varying)::text, ('send_2fa_sms'::character varying)::text]))"
t.index ["account_id", "created_at"], name: "index_submissions_events_on_sms_event_types", where: "((event_type)::text = ANY ((ARRAY['send_sms'::character varying, 'send_2fa_sms'::character varying])::text[]))"
t.index ["account_id"], name: "index_submission_events_on_account_id" t.index ["account_id"], name: "index_submission_events_on_account_id"
t.index ["created_at"], name: "index_submission_events_on_created_at" t.index ["created_at"], name: "index_submission_events_on_created_at"
t.index ["submission_id"], name: "index_submission_events_on_submission_id" t.index ["submission_id"], name: "index_submission_events_on_submission_id"
@ -339,23 +339,23 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "submissions", force: :cascade do |t| create_table "submissions", force: :cascade do |t|
t.bigint "template_id" t.bigint "account_id", null: false
t.bigint "created_by_user_id"
t.datetime "archived_at" t.datetime "archived_at"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.bigint "created_by_user_id"
t.datetime "expire_at"
t.text "name"
t.text "preferences", null: false
t.string "slug", null: false
t.string "source", null: false
t.string "submitters_order", null: false
t.text "template_fields" t.text "template_fields"
t.bigint "template_id"
t.text "template_schema" t.text "template_schema"
t.text "template_submitters" t.text "template_submitters"
t.string "source", null: false t.datetime "updated_at", null: false
t.string "submitters_order", null: false
t.string "slug", null: false
t.text "preferences", null: false
t.bigint "account_id", null: false
t.datetime "expire_at"
t.text "name"
t.text "variables_schema"
t.text "variables" t.text "variables"
t.text "variables_schema"
t.index ["account_id", "id"], name: "index_submissions_on_account_id_and_id" t.index ["account_id", "id"], name: "index_submissions_on_account_id_and_id"
t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id", where: "(archived_at IS NULL)" t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id", where: "(archived_at IS NULL)"
t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id_archived", where: "(archived_at IS NOT NULL)" t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id_archived", where: "(archived_at IS NOT NULL)"
@ -377,26 +377,26 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "submitters", force: :cascade do |t| create_table "submitters", force: :cascade do |t|
t.bigint "submission_id", null: false t.bigint "account_id", null: false
t.string "uuid", null: false
t.string "email"
t.string "slug", null: false
t.text "values", null: false
t.string "ua"
t.string "ip"
t.datetime "sent_at"
t.datetime "opened_at"
t.datetime "completed_at" t.datetime "completed_at"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "declined_at"
t.string "email"
t.string "external_id"
t.string "ip"
t.text "metadata", null: false
t.string "name" t.string "name"
t.datetime "opened_at"
t.string "phone" t.string "phone"
t.string "external_id"
t.text "preferences", null: false t.text "preferences", null: false
t.text "metadata", null: false t.datetime "sent_at"
t.bigint "account_id", null: false t.string "slug", null: false
t.datetime "declined_at" t.bigint "submission_id", null: false
t.string "timezone" t.string "timezone"
t.string "ua"
t.datetime "updated_at", null: false
t.string "uuid", null: false
t.text "values", null: false
t.index ["account_id", "id"], name: "index_submitters_on_account_id_and_id" t.index ["account_id", "id"], name: "index_submitters_on_account_id_and_id"
t.index ["completed_at", "account_id"], name: "index_submitters_on_completed_at_and_account_id" t.index ["completed_at", "account_id"], name: "index_submitters_on_completed_at_and_account_id"
t.index ["email"], name: "index_submitters_on_email" t.index ["email"], name: "index_submitters_on_email"
@ -406,52 +406,52 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "template_accesses", force: :cascade do |t| create_table "template_accesses", force: :cascade do |t|
t.bigint "template_id", null: false
t.bigint "user_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.bigint "template_id", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.index ["template_id", "user_id"], name: "index_template_accesses_on_template_id_and_user_id", unique: true t.index ["template_id", "user_id"], name: "index_template_accesses_on_template_id_and_user_id", unique: true
end end
create_table "template_folders", force: :cascade do |t| create_table "template_folders", force: :cascade do |t|
t.string "name", null: false
t.bigint "author_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.datetime "archived_at" t.datetime "archived_at"
t.bigint "author_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.string "name", null: false
t.bigint "parent_folder_id" t.bigint "parent_folder_id"
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_template_folders_on_account_id" t.index ["account_id"], name: "index_template_folders_on_account_id"
t.index ["author_id"], name: "index_template_folders_on_author_id" t.index ["author_id"], name: "index_template_folders_on_author_id"
t.index ["parent_folder_id"], name: "index_template_folders_on_parent_folder_id" t.index ["parent_folder_id"], name: "index_template_folders_on_parent_folder_id"
end end
create_table "template_sharings", force: :cascade do |t| create_table "template_sharings", force: :cascade do |t|
t.bigint "template_id", null: false
t.bigint "account_id", null: false
t.string "ability", null: false t.string "ability", null: false
t.bigint "account_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.bigint "template_id", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.index ["account_id", "template_id"], name: "index_template_sharings_on_account_id_and_template_id", unique: true t.index ["account_id", "template_id"], name: "index_template_sharings_on_account_id_and_template_id", unique: true
t.index ["template_id"], name: "index_template_sharings_on_template_id" t.index ["template_id"], name: "index_template_sharings_on_template_id"
end end
create_table "templates", force: :cascade do |t| create_table "templates", force: :cascade do |t|
t.string "slug", null: false
t.string "name", null: false
t.text "schema", null: false
t.text "fields", null: false
t.text "submitters", null: false
t.bigint "author_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.datetime "archived_at" t.datetime "archived_at"
t.bigint "author_id", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "source", null: false
t.bigint "folder_id", null: false
t.string "external_id" t.string "external_id"
t.text "fields", null: false
t.bigint "folder_id", null: false
t.string "name", null: false
t.text "preferences", null: false t.text "preferences", null: false
t.text "schema", null: false
t.boolean "shared_link", default: false, null: false t.boolean "shared_link", default: false, null: false
t.string "slug", null: false
t.text "source", null: false
t.text "submitters", null: false
t.datetime "updated_at", null: false
t.text "variables_schema" t.text "variables_schema"
t.index ["account_id", "folder_id", "id"], name: "index_templates_on_account_id_and_folder_id_and_id", where: "(archived_at IS NULL)" t.index ["account_id", "folder_id", "id"], name: "index_templates_on_account_id_and_folder_id_and_id", where: "(archived_at IS NULL)"
t.index ["account_id", "id"], name: "index_templates_on_account_id_and_id_archived", where: "(archived_at IS NOT NULL)" t.index ["account_id", "id"], name: "index_templates_on_account_id_and_id_archived", where: "(archived_at IS NOT NULL)"
@ -463,44 +463,44 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "user_configs", force: :cascade do |t| create_table "user_configs", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "key", null: false
t.text "value", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.string "key", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "user_id", null: false
t.text "value", null: false
t.index ["user_id", "key"], name: "index_user_configs_on_user_id_and_key", unique: true t.index ["user_id", "key"], name: "index_user_configs_on_user_id_and_key", unique: true
t.index ["user_id"], name: "index_user_configs_on_user_id" t.index ["user_id"], name: "index_user_configs_on_user_id"
end end
create_table "users", force: :cascade do |t| create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.string "email", null: false
t.string "role", null: false
t.string "encrypted_password", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.string "reset_password_token" t.datetime "archived_at"
t.datetime "reset_password_sent_at" t.datetime "confirmation_sent_at"
t.datetime "remember_created_at" t.string "confirmation_token"
t.integer "sign_in_count", default: 0, null: false t.datetime "confirmed_at"
t.integer "consumed_timestep"
t.datetime "created_at", null: false
t.datetime "current_sign_in_at" t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip" t.string "current_sign_in_ip"
t.string "last_sign_in_ip" t.string "email", null: false
t.string "encrypted_password", null: false
t.integer "failed_attempts", default: 0, null: false t.integer "failed_attempts", default: 0, null: false
t.string "unlock_token" t.string "first_name"
t.string "last_name"
t.datetime "last_sign_in_at"
t.string "last_sign_in_ip"
t.datetime "locked_at" t.datetime "locked_at"
t.datetime "archived_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "uuid", null: false
t.string "otp_secret"
t.integer "consumed_timestep"
t.boolean "otp_required_for_login", default: false, null: false t.boolean "otp_required_for_login", default: false, null: false
t.string "confirmation_token" t.string "otp_secret"
t.datetime "confirmed_at" t.datetime "remember_created_at"
t.datetime "confirmation_sent_at" t.datetime "reset_password_sent_at"
t.string "reset_password_token"
t.string "role", null: false
t.integer "sign_in_count", default: 0, null: false
t.string "unconfirmed_email" t.string "unconfirmed_email"
t.string "unlock_token"
t.datetime "updated_at", null: false
t.string "uuid", null: false
t.index ["account_id"], name: "index_users_on_account_id" t.index ["account_id"], name: "index_users_on_account_id"
t.index ["email"], name: "index_users_on_email", unique: true t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
@ -509,25 +509,25 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
end end
create_table "webhook_attempts", force: :cascade do |t| create_table "webhook_attempts", force: :cascade do |t|
t.bigint "webhook_event_id", null: false
t.text "response_body"
t.integer "response_status_code", null: false
t.integer "attempt", null: false t.integer "attempt", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.text "response_body"
t.integer "response_status_code", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "webhook_event_id", null: false
t.index ["webhook_event_id"], name: "index_webhook_attempts_on_webhook_event_id" t.index ["webhook_event_id"], name: "index_webhook_attempts_on_webhook_event_id"
end end
create_table "webhook_events", force: :cascade do |t| create_table "webhook_events", force: :cascade do |t|
t.string "uuid", null: false
t.bigint "webhook_url_id", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.datetime "created_at", null: false
t.string "event_type", null: false
t.bigint "record_id", null: false t.bigint "record_id", null: false
t.string "record_type", null: false t.string "record_type", null: false
t.string "event_type", null: false
t.string "status", null: false t.string "status", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "uuid", null: false
t.bigint "webhook_url_id", null: false
t.index ["uuid", "webhook_url_id"], name: "index_webhook_events_on_uuid_and_webhook_url_id", unique: true t.index ["uuid", "webhook_url_id"], name: "index_webhook_events_on_uuid_and_webhook_url_id", unique: true
t.index ["webhook_url_id", "id"], name: "index_webhook_events_error", where: "((status)::text = 'error'::text)" t.index ["webhook_url_id", "id"], name: "index_webhook_events_error", where: "((status)::text = 'error'::text)"
t.index ["webhook_url_id", "id"], name: "index_webhook_events_on_webhook_url_id_and_id" t.index ["webhook_url_id", "id"], name: "index_webhook_events_on_webhook_url_id_and_id"
@ -535,12 +535,12 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
create_table "webhook_urls", force: :cascade do |t| create_table "webhook_urls", force: :cascade do |t|
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.text "url", null: false t.datetime "created_at", null: false
t.text "events", null: false t.text "events", null: false
t.text "secret", null: false
t.string "sha1", null: false t.string "sha1", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.text "secret", null: false t.text "url", null: false
t.index ["account_id"], name: "index_webhook_urls_on_account_id" t.index ["account_id"], name: "index_webhook_urls_on_account_id"
t.index ["sha1"], name: "index_webhook_urls_on_sha1" t.index ["sha1"], name: "index_webhook_urls_on_sha1"
end end

@ -3,7 +3,7 @@
module GenerateCertificate module GenerateCertificate
SIZE = 2**11 SIZE = 2**11
Pkcs12Struct = Struct.new(:certificate, :ca_certs, keyword_init: true) Pkcs12Struct = Struct.new(:certificate, :ca_certs)
module_function module_function

@ -92,7 +92,7 @@ module Params
def in_path(params, path = [], skip_blank: false) def in_path(params, path = [], skip_blank: false)
old_path = @current_path old_path = @current_path
@current_path = [old_path, *path].compact_blank.map(&:to_s).join('.') @current_path = [old_path, *path].compact_blank.join('.')
param = params.dig(*path) param = params.dig(*path)
param = nil if skip_blank && param.blank? param = nil if skip_blank && param.blank?
@ -106,7 +106,7 @@ module Params
old_path = @current_path old_path = @current_path
params.dig(*path)&.each_with_index do |item, index| params.dig(*path)&.each_with_index do |item, index|
@current_path = [old_path, [*path].map(&:to_s).join('.') + "[#{index}]"].compact_blank.join('.') @current_path = [old_path, [*path].join('.') + "[#{index}]"].compact_blank.join('.')
yield item if item yield item if item
end end

@ -106,6 +106,8 @@ module Submissions
return submission if template.variables_schema.present? || return submission if template.variables_schema.present? ||
submission.variables_schema.present? submission.variables_schema.present?
return submission if template.schema.none? { |e| e['dynamic'] }
areas_index = {} areas_index = {}
submission.template_schema = [] submission.template_schema = []

@ -438,8 +438,8 @@ module Submissions
composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0]) composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0])
submitter_versions_index = submission.submitters.preload(:submitter_versions).each_with_object({}) do |s, h| submitter_versions_index = submission.submitters.preload(:submitter_versions).to_h do |s|
h[s.id] = s.submitter_versions.to_a.sort_by(&:created_at) [s.id, s.submitter_versions.to_a.sort_by(&:created_at)]
end end
events_data = submission.submission_events.sort_by(&:event_timestamp).filter_map do |event| events_data = submission.submission_events.sort_by(&:event_timestamp).filter_map do |event|
@ -475,7 +475,7 @@ module Submissions
].join("\n") ].join("\n")
elsif event.event_type == 'delegate_form' elsif event.event_type == 'delegate_form'
from = event.data['old_email'].presence || from = event.data['old_email'].presence ||
versions.reverse.find { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone } versions.rfind { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone }
I18n.t('submission_event_names.delegate_form_by_html', from:, to: event.data['email']) I18n.t('submission_event_names.delegate_form_by_html', from:, to: event.data['email'])
elsif event.event_type.include?('send_') elsif event.event_type.include?('send_')
I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:) I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:)

@ -58,7 +58,7 @@ module Submissions
end end
def build_table_rows(submissions, expires_at: nil) def build_table_rows(submissions, expires_at: nil)
submissions.preload(submitters: [attachments_attachments: :blob, documents_attachments: :blob]) submissions.preload(submitters: [{ attachments_attachments: :blob, documents_attachments: :blob }])
.find_each.map do |submission| .find_each.map do |submission|
submission_data = [] submission_data = []
submitters_count = submission.submitters.size submitters_count = submission.submitters.size

@ -4,6 +4,7 @@ module Submitters
module CreateStampAttachment module CreateStampAttachment
WIDTH = 400 WIDTH = 400
HEIGHT = 200 HEIGHT = 200
LRM = "\u200E"
TRANSPARENT_PIXEL = "\x89PNG\r\n\u001A\n\u0000\u0000\u0000\rIHDR\u0000" \ TRANSPARENT_PIXEL = "\x89PNG\r\n\u001A\n\u0000\u0000\u0000\rIHDR\u0000" \
"\u0000\u0000\u0001\u0000\u0000\u0000\u0001\b\u0004" \ "\u0000\u0000\u0001\u0000\u0000\u0000\u0001\b\u0004" \
@ -83,7 +84,8 @@ module Submitters
name = ERB::Util.html_escape(name) name = ERB::Util.html_escape(name)
role = ERB::Util.html_escape(role) role = ERB::Util.html_escape(role)
text = %(<span size="90">#{digitally_signed_by}:\n<b>#{name}</b>\n#{role}#{time} #{timezone}</span>) text =
%(<span size="90">#{LRM}#{digitally_signed_by}:\n#{LRM}<b>#{name}</b>\n#{LRM}#{role}#{time} #{timezone}</span>)
Vips::Image.text(text, width: WIDTH, height: HEIGHT, wrap: :'word-char') Vips::Image.text(text, width: WIDTH, height: HEIGHT, wrap: :'word-char')
end end

@ -15,9 +15,9 @@ module Submitters
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [submitter], records: [submitter],
associations: if with_documents associations: if with_documents
[documents_attachments: :blob, attachments_attachments: :blob] [{ documents_attachments: :blob, attachments_attachments: :blob }]
elsif with_values elsif with_values
[attachments_attachments: :blob] [{ attachments_attachments: :blob }]
end end
).call ).call

@ -12,7 +12,7 @@ module Submitters
def call(submitter, expires_at: Accounts.link_expires_at(Account.new(id: submitter.account_id))) def call(submitter, expires_at: Accounts.link_expires_at(Account.new(id: submitter.account_id)))
ActiveRecord::Associations::Preloader.new( ActiveRecord::Associations::Preloader.new(
records: [submitter], associations: [documents_attachments: :blob, attachments_attachments: :blob] records: [submitter], associations: [{ documents_attachments: :blob, attachments_attachments: :blob }]
).call ).call
values = build_values_array(submitter, expires_at:) values = build_values_array(submitter, expires_at:)

@ -4,7 +4,7 @@ module Templates
module DetectFields module DetectFields
module_function module_function
TextFieldBox = Struct.new(:x, :y, :w, :h, keyword_init: true) do TextFieldBox = Struct.new(:x, :y, :w, :h) do
def endy def endy
@endy ||= y + h @endy ||= y + h
end end
@ -14,7 +14,7 @@ module Templates
end end
end end
PageNode = Struct.new(:prev, :next, :elem, :page, :attachment_uuid, keyword_init: true) PageNode = Struct.new(:prev, :next, :elem, :page, :attachment_uuid)
DATE_REGEXP = / DATE_REGEXP = /
(?: (?:

@ -4,7 +4,7 @@ module Templates
module ImageToFields module ImageToFields
module_function module_function
Field = Struct.new(:type, :x, :y, :w, :h, :confidence, keyword_init: true) do Field = Struct.new(:type, :x, :y, :w, :h, :confidence) do
def endy def endy
@endy ||= y + h @endy ||= y + h
end end

@ -34,7 +34,7 @@ module Templates
if index.positive? && pdf_fields.present? if index.positive? && pdf_fields.present?
preview_document = template.schema[index - 1] preview_document = template.schema[index - 1]
preview_document_last_field = template.fields.reverse.find do |f| preview_document_last_field = template.fields.rfind do |f|
f['areas']&.any? do |a| f['areas']&.any? do |a|
a['attachment_uuid'] == preview_document[:attachment_uuid] a['attachment_uuid'] == preview_document[:attachment_uuid]
end end

@ -9,10 +9,9 @@ require 'rspec/rails'
require 'capybara/cuprite' require 'capybara/cuprite'
require 'capybara/rspec' require 'capybara/rspec'
require 'webmock/rspec' require 'webmock/rspec'
require 'sidekiq/testing'
require 'signing_form_helper' require 'signing_form_helper'
Sidekiq::Testing.fake! Sidekiq.testing!(:fake)
WebMock.disable_net_connect!(allow_localhost: true) WebMock.disable_net_connect!(allow_localhost: true)
@ -69,11 +68,11 @@ RSpec.configure do |config|
end end
config.before do |example| config.before do |example|
Sidekiq::Testing.inline! if example.metadata[:sidekiq] == :inline Sidekiq.testing!(:inline) if example.metadata[:sidekiq] == :inline
end end
config.after do |example| config.after do |example|
Sidekiq::Testing.fake! if example.metadata[:sidekiq] == :inline Sidekiq.testing!(:fake) if example.metadata[:sidekiq] == :inline
end end
config.before(multitenant: true) do config.before(multitenant: true) do

Loading…
Cancel
Save