mirror of
https://github.com/docusealco/docuseal.git
synced 2026-08-07 07:14:43 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c4cbd86f7 | |||
| eaedaa96bb | |||
| bd7ad5fce8 | |||
| 759dac1b70 | |||
| 38577c6235 | |||
| b24fff0f55 | |||
| 9e0efeb092 | |||
| 41152f90fc |
@@ -51,6 +51,15 @@ Style/NumericPredicate:
|
||||
Style/MinMaxComparison:
|
||||
Enabled: false
|
||||
|
||||
Style/EmptyClassDefinition:
|
||||
Enabled: false
|
||||
|
||||
Style/OneClassPerFile:
|
||||
Enabled: false
|
||||
|
||||
Layout/MultilineMethodCallIndentation:
|
||||
Enabled: false
|
||||
|
||||
Naming/PredicateMethod:
|
||||
Enabled: false
|
||||
|
||||
|
||||
+7
-10
@@ -2,20 +2,17 @@ FROM ruby:4.0.1-alpine AS download
|
||||
|
||||
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-Bold.ttf && \
|
||||
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://github.com/Maxattax97/gnu-freefont/raw/master/ttf/FreeSans.ttf && \
|
||||
wget https://github.com/impallari/DancingScript/raw/master/OFL.txt && \
|
||||
wget https://raw.githubusercontent.com/impallari/DancingScript/master/OFL.txt && \
|
||||
wget https://raw.githubusercontent.com/notofonts/noto-fonts/refs/heads/main/LICENSE && \
|
||||
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" && \
|
||||
mkdir -p /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
|
||||
|
||||
ENV RAILS_ENV=production
|
||||
@@ -51,7 +48,7 @@ ENV OPENSSL_CONF=/etc/openssl_legacy.cnf
|
||||
|
||||
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
|
||||
|
||||
@@ -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 .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 --from=download /fonts/FreeSans.ttf /usr/share/fonts/freefont
|
||||
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 /pdfium-linux/lib/libpdfium.so /usr/lib/libpdfium.so
|
||||
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=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/ && \
|
||||
chown -R docuseal:docuseal /app/tmp/cache
|
||||
|
||||
|
||||
+66
-66
@@ -1,7 +1,7 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
action_text-trix (2.1.17)
|
||||
action_text-trix (2.1.18)
|
||||
railties
|
||||
actioncable (8.1.3)
|
||||
actionpack (= 8.1.3)
|
||||
@@ -75,16 +75,16 @@ GEM
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
addressable (2.8.8)
|
||||
addressable (2.8.9)
|
||||
public_suffix (>= 2.0.2, < 8.0)
|
||||
annotaterb (4.20.0)
|
||||
annotaterb (4.22.0)
|
||||
activerecord (>= 6.0.0)
|
||||
activesupport (>= 6.0.0)
|
||||
arabic-letter-connector (0.1.1)
|
||||
ast (2.4.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1209.0)
|
||||
aws-sdk-core (3.241.4)
|
||||
aws-partitions (1.1233.0)
|
||||
aws-sdk-core (3.244.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
@@ -92,15 +92,15 @@ GEM
|
||||
bigdecimal
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
logger
|
||||
aws-sdk-kms (1.121.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sdk-kms (1.123.0)
|
||||
aws-sdk-core (~> 3, >= 3.244.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.212.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sdk-s3 (1.218.0)
|
||||
aws-sdk-core (~> 3, >= 3.244.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-secretsmanager (1.128.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sdk-secretsmanager (1.129.0)
|
||||
aws-sdk-core (~> 3, >= 3.244.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.12.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
@@ -116,11 +116,11 @@ GEM
|
||||
erubi (~> 1.4)
|
||||
parser (>= 2.4)
|
||||
smart_properties
|
||||
bigdecimal (4.0.1)
|
||||
bigdecimal (4.1.0)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.21.1)
|
||||
bootsnap (1.23.0)
|
||||
msgpack (~> 1.2)
|
||||
brakeman (7.1.2)
|
||||
brakeman (8.0.4)
|
||||
racc
|
||||
builder (3.3.0)
|
||||
bullet (8.1.0)
|
||||
@@ -193,7 +193,7 @@ GEM
|
||||
factory_bot_rails (6.5.1)
|
||||
factory_bot (~> 6.5)
|
||||
railties (>= 6.1.0)
|
||||
faker (3.6.0)
|
||||
faker (3.6.1)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
faraday (2.14.1)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
@@ -203,17 +203,17 @@ GEM
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.4.2)
|
||||
net-http (~> 0.5)
|
||||
ferrum (0.17.1)
|
||||
ferrum (0.17.2)
|
||||
addressable (~> 2.5)
|
||||
base64 (~> 0.2)
|
||||
concurrent-ruby (~> 1.1)
|
||||
webrick (~> 1.7)
|
||||
websocket-driver (~> 0.7)
|
||||
ffi (1.17.3-aarch64-linux-gnu)
|
||||
ffi (1.17.3-aarch64-linux-musl)
|
||||
ffi (1.17.3-arm64-darwin)
|
||||
ffi (1.17.3-x86_64-linux-gnu)
|
||||
ffi (1.17.3-x86_64-linux-musl)
|
||||
ffi (1.17.4-aarch64-linux-gnu)
|
||||
ffi (1.17.4-aarch64-linux-musl)
|
||||
ffi (1.17.4-arm64-darwin)
|
||||
ffi (1.17.4-x86_64-linux-gnu)
|
||||
ffi (1.17.4-x86_64-linux-musl)
|
||||
foreman (0.90.0)
|
||||
thor (~> 1.4)
|
||||
geom2d (0.4.1)
|
||||
@@ -229,7 +229,7 @@ GEM
|
||||
retriable (~> 3.1)
|
||||
google-apis-iamcredentials_v1 (0.26.0)
|
||||
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-cloud-core (1.8.0)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
@@ -237,8 +237,8 @@ GEM
|
||||
google-cloud-env (2.3.1)
|
||||
base64 (~> 0.2)
|
||||
faraday (>= 1.0, < 3.a)
|
||||
google-cloud-errors (1.5.0)
|
||||
google-cloud-storage (1.58.0)
|
||||
google-cloud-errors (1.6.0)
|
||||
google-cloud-storage (1.59.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-core (>= 0.18, < 2)
|
||||
@@ -248,7 +248,7 @@ GEM
|
||||
googleauth (~> 1.9)
|
||||
mini_mime (~> 1.0)
|
||||
google-logging-utils (0.2.0)
|
||||
googleauth (1.16.1)
|
||||
googleauth (1.16.2)
|
||||
faraday (>= 1.0, < 3.a)
|
||||
google-cloud-env (~> 2.2)
|
||||
google-logging-utils (~> 0.1)
|
||||
@@ -257,7 +257,7 @@ GEM
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
hashdiff (1.2.1)
|
||||
hexapdf (1.5.0)
|
||||
hexapdf (1.6.0)
|
||||
cmdparse (~> 3.0, >= 3.0.3)
|
||||
geom2d (~> 0.4, >= 0.4.1)
|
||||
openssl (>= 2.2.1)
|
||||
@@ -274,7 +274,7 @@ GEM
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
json (2.19.2)
|
||||
json (2.19.3)
|
||||
jwt (3.1.2)
|
||||
base64
|
||||
language_server-protocol (3.17.0.5)
|
||||
@@ -311,7 +311,7 @@ GEM
|
||||
mini_magick (5.3.1)
|
||||
logger
|
||||
mini_mime (1.1.5)
|
||||
minitest (6.0.2)
|
||||
minitest (6.0.3)
|
||||
drb (~> 2.0)
|
||||
prism (~> 1.5)
|
||||
msgpack (1.8.0)
|
||||
@@ -339,7 +339,7 @@ GEM
|
||||
nokogiri (1.19.2-x86_64-linux-musl)
|
||||
racc (~> 1.4)
|
||||
numo-narray-alt (0.10.3)
|
||||
oj (3.16.13)
|
||||
oj (3.16.16)
|
||||
bigdecimal (>= 3.0)
|
||||
ostruct (>= 0.2)
|
||||
onnxruntime (0.10.1-aarch64-linux)
|
||||
@@ -348,16 +348,17 @@ GEM
|
||||
ffi
|
||||
onnxruntime (0.10.1-x86_64-linux)
|
||||
ffi
|
||||
openssl (4.0.0)
|
||||
openssl (4.0.1)
|
||||
orm_adapter (0.5.0)
|
||||
os (1.1.4)
|
||||
ostruct (0.6.3)
|
||||
package_json (0.2.0)
|
||||
pagy (43.2.8)
|
||||
pagy (43.4.4)
|
||||
json
|
||||
uri
|
||||
yaml
|
||||
parallel (1.27.0)
|
||||
parser (3.3.10.1)
|
||||
parallel (1.28.0)
|
||||
parser (3.3.11.1)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
pg (1.6.3-aarch64-linux)
|
||||
@@ -367,8 +368,8 @@ GEM
|
||||
pg (1.6.3-x86_64-linux-musl)
|
||||
pp (0.6.3)
|
||||
prettyprint
|
||||
pretender (0.6.0)
|
||||
actionpack (>= 7.1)
|
||||
pretender (1.0.0)
|
||||
actionpack (>= 7.2)
|
||||
prettyprint (0.2.0)
|
||||
prism (1.9.0)
|
||||
pry (0.16.0)
|
||||
@@ -380,11 +381,11 @@ GEM
|
||||
psych (5.3.1)
|
||||
date
|
||||
stringio
|
||||
public_suffix (7.0.2)
|
||||
public_suffix (7.0.5)
|
||||
puma (7.2.0)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.8.1)
|
||||
rack (3.2.5)
|
||||
rack (3.2.6)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-session (2.1.1)
|
||||
@@ -433,7 +434,7 @@ GEM
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
tsort
|
||||
redis-client (0.26.4)
|
||||
redis-client (0.28.0)
|
||||
connection_pool
|
||||
regexp_parser (2.11.3)
|
||||
reline (0.6.3)
|
||||
@@ -447,7 +448,7 @@ GEM
|
||||
responders (3.2.0)
|
||||
actionpack (>= 7.0)
|
||||
railties (>= 7.0)
|
||||
retriable (3.1.2)
|
||||
retriable (3.4.1)
|
||||
rexml (3.4.4)
|
||||
rotp (6.3.0)
|
||||
rouge (4.7.0)
|
||||
@@ -460,19 +461,19 @@ GEM
|
||||
rspec-expectations (3.13.5)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-mocks (3.13.7)
|
||||
rspec-mocks (3.13.8)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (8.0.2)
|
||||
rspec-rails (8.0.4)
|
||||
actionpack (>= 7.2)
|
||||
activesupport (>= 7.2)
|
||||
railties (>= 7.2)
|
||||
rspec-core (~> 3.13)
|
||||
rspec-expectations (~> 3.13)
|
||||
rspec-mocks (~> 3.13)
|
||||
rspec-support (~> 3.13)
|
||||
rspec-support (3.13.6)
|
||||
rubocop (1.82.1)
|
||||
rspec-core (>= 3.13.0, < 5.0.0)
|
||||
rspec-expectations (>= 3.13.0, < 5.0.0)
|
||||
rspec-mocks (>= 3.13.0, < 5.0.0)
|
||||
rspec-support (>= 3.13.0, < 5.0.0)
|
||||
rspec-support (3.13.7)
|
||||
rubocop (1.86.0)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
@@ -480,10 +481,10 @@ GEM
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.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)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.49.0)
|
||||
rubocop-ast (1.49.1)
|
||||
parser (>= 3.3.7.2)
|
||||
prism (~> 1.7)
|
||||
rubocop-performance (1.26.1)
|
||||
@@ -508,14 +509,14 @@ GEM
|
||||
rubyzip (>= 3.2.2)
|
||||
rubyzip (3.2.2)
|
||||
securerandom (0.4.1)
|
||||
semantic_range (3.1.0)
|
||||
shakapacker (9.5.0)
|
||||
semantic_range (3.1.1)
|
||||
shakapacker (9.7.0)
|
||||
activesupport (>= 5.2)
|
||||
package_json
|
||||
rack-proxy (>= 0.6.1)
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
sidekiq (8.1.0)
|
||||
sidekiq (8.1.2)
|
||||
connection_pool (>= 3.0.0)
|
||||
json (>= 2.16.0)
|
||||
logger (>= 1.7.0)
|
||||
@@ -533,22 +534,22 @@ GEM
|
||||
simplecov-html (0.13.2)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
smart_properties (1.17.0)
|
||||
sqlite3 (2.9.0-aarch64-linux-gnu)
|
||||
sqlite3 (2.9.0-aarch64-linux-musl)
|
||||
sqlite3 (2.9.0-arm64-darwin)
|
||||
sqlite3 (2.9.0-x86_64-linux-gnu)
|
||||
sqlite3 (2.9.0-x86_64-linux-musl)
|
||||
sqlite3 (2.9.2-aarch64-linux-gnu)
|
||||
sqlite3 (2.9.2-aarch64-linux-musl)
|
||||
sqlite3 (2.9.2-arm64-darwin)
|
||||
sqlite3 (2.9.2-x86_64-linux-gnu)
|
||||
sqlite3 (2.9.2-x86_64-linux-musl)
|
||||
stringio (3.2.0)
|
||||
strip_attributes (2.0.1)
|
||||
activemodel (>= 3.0, < 9.0)
|
||||
strscan (3.1.7)
|
||||
strscan (3.1.8)
|
||||
thor (1.5.0)
|
||||
timeout (0.6.1)
|
||||
trailblazer-option (0.1.2)
|
||||
trilogy (2.10.0)
|
||||
trilogy (2.12.2)
|
||||
bigdecimal
|
||||
tsort (0.2.0)
|
||||
turbo-rails (2.0.21)
|
||||
turbo-rails (2.0.23)
|
||||
actionpack (>= 7.1.0)
|
||||
railties (>= 7.1.0)
|
||||
twitter_cldr (6.14.0)
|
||||
@@ -558,7 +559,7 @@ GEM
|
||||
tzinfo
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
tzinfo-data (1.2025.3)
|
||||
tzinfo-data (1.2026.1)
|
||||
tzinfo (>= 1.0.0)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (3.2.0)
|
||||
@@ -569,12 +570,11 @@ GEM
|
||||
useragent (0.16.11)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
web-console (4.2.1)
|
||||
actionview (>= 6.0.0)
|
||||
activemodel (>= 6.0.0)
|
||||
web-console (4.3.0)
|
||||
actionview (>= 8.0.0)
|
||||
bindex (>= 0.4.0)
|
||||
railties (>= 6.0.0)
|
||||
webmock (3.26.1)
|
||||
railties (>= 8.0.0)
|
||||
webmock (3.26.2)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
|
||||
@@ -9,7 +9,7 @@ module Api
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: :preview_images_attachments]
|
||||
associations: [{ schema_documents: :preview_images_attachments }]
|
||||
).call
|
||||
|
||||
cloned_template = Templates::Clone.call(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class EsignSettingsController < ApplicationController
|
||||
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
|
||||
|
||||
def to_key
|
||||
|
||||
@@ -26,7 +26,7 @@ class SubmissionsController < ApplicationController
|
||||
unless @submission.submitters.all?(&:completed_at?)
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@submission],
|
||||
associations: [submitters: :start_form_submission_events]
|
||||
associations: [{ submitters: :start_form_submission_events }]
|
||||
).call
|
||||
end
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class TemplatesCloneAndReplaceController < ApplicationController
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: :preview_images_attachments]
|
||||
associations: [{ schema_documents: :preview_images_attachments }]
|
||||
).call
|
||||
|
||||
cloned_template = Templates::Clone.call(@template, author: current_user)
|
||||
|
||||
@@ -12,7 +12,7 @@ class TemplatesCloneController < ApplicationController
|
||||
def create
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@base_template],
|
||||
associations: [schema_documents: :preview_images_attachments]
|
||||
associations: [{ schema_documents: :preview_images_attachments }]
|
||||
).call
|
||||
|
||||
@template = Templates::Clone.call(@base_template, author: current_user,
|
||||
|
||||
@@ -29,7 +29,7 @@ class TemplatesController < ApplicationController
|
||||
def edit
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: [:blob, { preview_images_attachments: :blob }]]
|
||||
associations: [{ schema_documents: [:blob, { preview_images_attachments: :blob }] }]
|
||||
).call
|
||||
|
||||
@template_data =
|
||||
|
||||
@@ -30,7 +30,7 @@ class TemplatesDebugController < ApplicationController
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: { preview_images_attachments: :blob }]
|
||||
associations: [{ schema_documents: { preview_images_attachments: :blob } }]
|
||||
).call
|
||||
|
||||
@template_data =
|
||||
|
||||
@@ -58,8 +58,8 @@ class TemplatesPreferencesController < ApplicationController
|
||||
default_expire_at_duration shared_link_2fa default_expire_at request_email_enabled
|
||||
completed_notification_email_subject completed_notification_email_body
|
||||
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
||||
[completed_message: %i[title body],
|
||||
submitters: [%i[uuid request_email_subject request_email_body]], link_form_fields: []]
|
||||
[{ completed_message: %i[title body],
|
||||
submitters: [%i[uuid request_email_subject request_email_body]], link_form_fields: [] }]
|
||||
).tap do |attrs|
|
||||
attrs[:preferences].delete(:submitters) if params[:request_email_per_submitter] != '1'
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ class TemplatesPreviewController < ApplicationController
|
||||
def show
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: { preview_images_attachments: :blob }]
|
||||
associations: [{ schema_documents: { preview_images_attachments: :blob } }]
|
||||
).call
|
||||
|
||||
@template_data =
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
# id :bigint not null, primary key
|
||||
# body :text not null
|
||||
# head :text
|
||||
# sha1 :text not null
|
||||
# uuid :uuid not null
|
||||
# sha1 :string not null
|
||||
# uuid :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# template_id :bigint not null
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<% end %>
|
||||
</p>
|
||||
</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| %>
|
||||
<% submitter = @submission.submitters.find { |e| e.id == event.submitter_id } %>
|
||||
<% 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')) %>
|
||||
<%= 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' %>
|
||||
<% 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']) %>
|
||||
<% elsif event.event_type.include?('send_') %>
|
||||
<%= t("submission_event_names.#{event.event_type}_to_html", submitter_name:) %>
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
<% 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) %>
|
||||
<% 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] %>
|
||||
<% schema.each do |item| %>
|
||||
<% 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) %>
|
||||
<% values = @submitter.submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %>
|
||||
<% 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) %>
|
||||
<% font_scale = 1000.0 / PdfUtils::US_LETTER_W %>
|
||||
<% decline_modal_checkbox_uuid = nil %>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% 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">
|
||||
<%= svg_icon('link', class: 'w-4 h-4 md:w-6 md:h-6') %>
|
||||
<span><%= t('link') %></span>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Pagy.options[:limit] = 10
|
||||
Pagy::OPTIONS[:limit] = 10
|
||||
|
||||
+165
-165
@@ -13,41 +13,41 @@
|
||||
ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "btree_gin"
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
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.text "sha256", null: false
|
||||
t.text "token", 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 ["user_id"], name: "index_access_tokens_on_user_id"
|
||||
end
|
||||
|
||||
create_table "account_accesses", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "user_id", null: false
|
||||
t.datetime "created_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
|
||||
end
|
||||
|
||||
create_table "account_configs", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.string "key", null: false
|
||||
t.text "value", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.string "key", 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"], name: "index_account_configs_on_account_id"
|
||||
end
|
||||
|
||||
create_table "account_linked_accounts", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.bigint "linked_account_id", null: false
|
||||
t.text "account_type", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.bigint "linked_account_id", 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"], name: "index_account_linked_accounts_on_account_id"
|
||||
@@ -55,37 +55,37 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
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 "timezone", null: false
|
||||
t.string "locale", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "uuid", null: false
|
||||
t.datetime "archived_at"
|
||||
t.index ["uuid"], name: "index_accounts_on_uuid", unique: true
|
||||
end
|
||||
|
||||
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.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 ["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"
|
||||
end
|
||||
|
||||
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.string "checksum"
|
||||
t.string "content_type"
|
||||
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.index ["checksum"], name: "index_active_storage_blobs_on_checksum"
|
||||
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
|
||||
|
||||
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.string "sha256", null: false
|
||||
t.bigint "submitter_id", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["sha256"], name: "index_completed_documents_on_sha256"
|
||||
t.index ["submitter_id"], name: "index_completed_documents_on_submitter_id"
|
||||
end
|
||||
|
||||
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 "template_id"
|
||||
t.string "source", null: false
|
||||
t.integer "sms_count", null: false
|
||||
t.datetime "completed_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.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_on_account_id_and_completed_at"
|
||||
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
|
||||
|
||||
create_table "console1984_commands", force: :cascade do |t|
|
||||
t.text "statements"
|
||||
t.datetime "created_at", null: false
|
||||
t.bigint "sensitive_access_id"
|
||||
t.bigint "session_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.text "statements"
|
||||
t.datetime "updated_at", null: false
|
||||
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"
|
||||
end
|
||||
|
||||
create_table "console1984_sensitive_accesses", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.text "justification"
|
||||
t.bigint "session_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["session_id"], name: "index_console1984_sensitive_accesses_on_session_id"
|
||||
end
|
||||
|
||||
create_table "console1984_sessions", force: :cascade do |t|
|
||||
t.text "reason"
|
||||
t.bigint "user_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.text "reason"
|
||||
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 ["user_id", "created_at"], name: "index_console1984_sessions_on_user_id_and_created_at"
|
||||
end
|
||||
|
||||
create_table "console1984_users", force: :cascade do |t|
|
||||
t.string "username", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "username", null: false
|
||||
t.index ["username"], name: "index_console1984_users_on_username"
|
||||
end
|
||||
|
||||
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.string "event_name", null: false
|
||||
t.bigint "submitter_id", 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"
|
||||
end
|
||||
|
||||
@@ -190,31 +190,31 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
|
||||
create_table "email_events", force: :cascade do |t|
|
||||
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.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 "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 ["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 ["message_id"], name: "index_email_events_on_message_id"
|
||||
end
|
||||
|
||||
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.text "subject", null: false
|
||||
t.bigint "author_id", null: false
|
||||
t.text "body", null: false
|
||||
t.string "sha1", 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.string "uuid", null: false
|
||||
t.index ["account_id"], name: "index_email_messages_on_account_id"
|
||||
t.index ["sha1"], name: "index_email_messages_on_sha1"
|
||||
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|
|
||||
t.bigint "account_id", null: false
|
||||
t.string "key", null: false
|
||||
t.text "value", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.string "key", 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"], name: "index_encrypted_configs_on_account_id"
|
||||
end
|
||||
|
||||
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.string "key", 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"], name: "index_encrypted_user_configs_on_user_id"
|
||||
end
|
||||
|
||||
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.string "event_name", null: false
|
||||
t.string "key", 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"
|
||||
end
|
||||
|
||||
@@ -262,31 +262,31 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
create_table "oauth_access_grants", force: :cascade do |t|
|
||||
t.bigint "resource_owner_id", null: false
|
||||
t.bigint "application_id", null: false
|
||||
t.string "token", null: false
|
||||
t.integer "expires_in", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.string "scopes", default: "", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "revoked_at"
|
||||
t.string "code_challenge"
|
||||
t.string "code_challenge_method"
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "expires_in", null: false
|
||||
t.text "redirect_uri", null: false
|
||||
t.bigint "resource_owner_id", null: false
|
||||
t.datetime "revoked_at"
|
||||
t.string "scopes", default: "", null: false
|
||||
t.string "token", null: false
|
||||
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 ["token"], name: "index_oauth_access_grants_on_token", unique: true
|
||||
end
|
||||
|
||||
create_table "oauth_access_tokens", force: :cascade do |t|
|
||||
t.bigint "resource_owner_id"
|
||||
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 "revoked_at"
|
||||
t.integer "expires_in"
|
||||
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 ["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"
|
||||
@@ -294,25 +294,25 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
create_table "oauth_applications", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.string "uid", null: false
|
||||
t.string "secret", null: false
|
||||
t.text "redirect_uri"
|
||||
t.string "scopes", default: "", null: false
|
||||
t.boolean "confidential", default: true, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.string "name", null: false
|
||||
t.text "redirect_uri"
|
||||
t.string "scopes", default: "", null: false
|
||||
t.string "secret", null: false
|
||||
t.string "uid", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
|
||||
end
|
||||
|
||||
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.tsvector "tsvector", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
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_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
|
||||
@@ -323,15 +323,15 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
create_table "submission_events", force: :cascade do |t|
|
||||
t.bigint "account_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.text "data", null: false
|
||||
t.datetime "event_timestamp", null: false
|
||||
t.string "event_type", null: false
|
||||
t.bigint "submission_id", null: false
|
||||
t.bigint "submitter_id"
|
||||
t.text "data", null: false
|
||||
t.string "event_type", null: false
|
||||
t.datetime "event_timestamp", null: false
|
||||
t.datetime "created_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, '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)::text, ('send_2fa_sms'::character varying)::text]))"
|
||||
t.index ["account_id"], name: "index_submission_events_on_account_id"
|
||||
t.index ["created_at"], name: "index_submission_events_on_created_at"
|
||||
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
|
||||
|
||||
create_table "submissions", force: :cascade do |t|
|
||||
t.bigint "template_id"
|
||||
t.bigint "created_by_user_id"
|
||||
t.bigint "account_id", null: false
|
||||
t.datetime "archived_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "template_fields"
|
||||
t.text "template_schema"
|
||||
t.text "template_submitters"
|
||||
t.string "source", 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.bigint "created_by_user_id"
|
||||
t.datetime "expire_at"
|
||||
t.text "name"
|
||||
t.text "variables_schema"
|
||||
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.bigint "template_id"
|
||||
t.text "template_schema"
|
||||
t.text "template_submitters"
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "variables"
|
||||
t.text "variables_schema"
|
||||
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_archived", where: "(archived_at IS NOT NULL)"
|
||||
@@ -377,26 +377,26 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
create_table "submitters", force: :cascade do |t|
|
||||
t.bigint "submission_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.bigint "account_id", null: false
|
||||
t.datetime "completed_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "name"
|
||||
t.string "phone"
|
||||
t.string "external_id"
|
||||
t.text "preferences", null: false
|
||||
t.text "metadata", null: false
|
||||
t.bigint "account_id", 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.datetime "opened_at"
|
||||
t.string "phone"
|
||||
t.text "preferences", null: false
|
||||
t.datetime "sent_at"
|
||||
t.string "slug", null: false
|
||||
t.bigint "submission_id", null: false
|
||||
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 ["completed_at", "account_id"], name: "index_submitters_on_completed_at_and_account_id"
|
||||
t.index ["email"], name: "index_submitters_on_email"
|
||||
@@ -406,52 +406,52 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
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.bigint "template_id", 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
|
||||
end
|
||||
|
||||
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.datetime "archived_at"
|
||||
t.bigint "author_id", 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.datetime "updated_at", null: false
|
||||
t.index ["account_id"], name: "index_template_folders_on_account_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"
|
||||
end
|
||||
|
||||
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.bigint "account_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.bigint "template_id", 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 ["template_id"], name: "index_template_sharings_on_template_id"
|
||||
end
|
||||
|
||||
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.datetime "archived_at"
|
||||
t.bigint "author_id", 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.text "fields", null: false
|
||||
t.bigint "folder_id", null: false
|
||||
t.string "name", null: false
|
||||
t.text "preferences", null: false
|
||||
t.text "schema", 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.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)"
|
||||
@@ -463,44 +463,44 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
end
|
||||
|
||||
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.string "key", 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"], name: "index_user_configs_on_user_id"
|
||||
end
|
||||
|
||||
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.string "reset_password_token"
|
||||
t.datetime "reset_password_sent_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.integer "sign_in_count", default: 0, null: false
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "last_sign_in_ip"
|
||||
t.integer "failed_attempts", default: 0, null: false
|
||||
t.string "unlock_token"
|
||||
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.datetime "confirmation_sent_at"
|
||||
t.string "confirmation_token"
|
||||
t.datetime "confirmed_at"
|
||||
t.datetime "confirmation_sent_at"
|
||||
t.integer "consumed_timestep"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "current_sign_in_at"
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "email", null: false
|
||||
t.string "encrypted_password", null: false
|
||||
t.integer "failed_attempts", default: 0, null: false
|
||||
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.boolean "otp_required_for_login", default: false, null: false
|
||||
t.string "otp_secret"
|
||||
t.datetime "remember_created_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 "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 ["email"], name: "index_users_on_email", 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
|
||||
|
||||
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.datetime "created_at", null: false
|
||||
t.text "response_body"
|
||||
t.integer "response_status_code", 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"
|
||||
end
|
||||
|
||||
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.datetime "created_at", null: false
|
||||
t.string "event_type", null: false
|
||||
t.bigint "record_id", null: false
|
||||
t.string "record_type", null: false
|
||||
t.string "event_type", null: false
|
||||
t.string "status", null: false
|
||||
t.datetime "created_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 ["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"
|
||||
@@ -535,12 +535,12 @@ ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
|
||||
|
||||
create_table "webhook_urls", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.text "url", null: false
|
||||
t.text "events", null: false
|
||||
t.string "sha1", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "events", null: false
|
||||
t.text "secret", null: false
|
||||
t.string "sha1", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "url", null: false
|
||||
t.index ["account_id"], name: "index_webhook_urls_on_account_id"
|
||||
t.index ["sha1"], name: "index_webhook_urls_on_sha1"
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
module GenerateCertificate
|
||||
SIZE = 2**11
|
||||
|
||||
Pkcs12Struct = Struct.new(:certificate, :ca_certs, keyword_init: true)
|
||||
Pkcs12Struct = Struct.new(:certificate, :ca_certs)
|
||||
|
||||
module_function
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ module Params
|
||||
def in_path(params, path = [], skip_blank: false)
|
||||
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 = nil if skip_blank && param.blank?
|
||||
@@ -106,7 +106,7 @@ module Params
|
||||
old_path = @current_path
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
@@ -106,6 +106,8 @@ module Submissions
|
||||
return submission if template.variables_schema.present? ||
|
||||
submission.variables_schema.present?
|
||||
|
||||
return submission if template.schema.none? { |e| e['dynamic'] }
|
||||
|
||||
areas_index = {}
|
||||
submission.template_schema = []
|
||||
|
||||
|
||||
@@ -438,8 +438,8 @@ module Submissions
|
||||
|
||||
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|
|
||||
h[s.id] = s.submitter_versions.to_a.sort_by(&:created_at)
|
||||
submitter_versions_index = submission.submitters.preload(:submitter_versions).to_h do |s|
|
||||
[s.id, s.submitter_versions.to_a.sort_by(&:created_at)]
|
||||
end
|
||||
|
||||
events_data = submission.submission_events.sort_by(&:event_timestamp).filter_map do |event|
|
||||
@@ -475,7 +475,7 @@ module Submissions
|
||||
].join("\n")
|
||||
elsif event.event_type == 'delegate_form'
|
||||
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'])
|
||||
elsif event.event_type.include?('send_')
|
||||
I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:)
|
||||
|
||||
@@ -58,7 +58,7 @@ module Submissions
|
||||
end
|
||||
|
||||
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|
|
||||
submission_data = []
|
||||
submitters_count = submission.submitters.size
|
||||
|
||||
@@ -4,6 +4,7 @@ module Submitters
|
||||
module CreateStampAttachment
|
||||
WIDTH = 400
|
||||
HEIGHT = 200
|
||||
LRM = "\u200E"
|
||||
|
||||
TRANSPARENT_PIXEL = "\x89PNG\r\n\u001A\n\u0000\u0000\u0000\rIHDR\u0000" \
|
||||
"\u0000\u0000\u0001\u0000\u0000\u0000\u0001\b\u0004" \
|
||||
@@ -83,7 +84,8 @@ module Submitters
|
||||
name = ERB::Util.html_escape(name)
|
||||
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')
|
||||
end
|
||||
|
||||
@@ -15,9 +15,9 @@ module Submitters
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [submitter],
|
||||
associations: if with_documents
|
||||
[documents_attachments: :blob, attachments_attachments: :blob]
|
||||
[{ documents_attachments: :blob, attachments_attachments: :blob }]
|
||||
elsif with_values
|
||||
[attachments_attachments: :blob]
|
||||
[{ attachments_attachments: :blob }]
|
||||
end
|
||||
).call
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ module Submitters
|
||||
|
||||
def call(submitter, expires_at: Accounts.link_expires_at(Account.new(id: submitter.account_id)))
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [submitter], associations: [documents_attachments: :blob, attachments_attachments: :blob]
|
||||
records: [submitter], associations: [{ documents_attachments: :blob, attachments_attachments: :blob }]
|
||||
).call
|
||||
|
||||
values = build_values_array(submitter, expires_at:)
|
||||
|
||||
@@ -4,7 +4,7 @@ module Templates
|
||||
module DetectFields
|
||||
module_function
|
||||
|
||||
TextFieldBox = Struct.new(:x, :y, :w, :h, keyword_init: true) do
|
||||
TextFieldBox = Struct.new(:x, :y, :w, :h) do
|
||||
def endy
|
||||
@endy ||= y + h
|
||||
end
|
||||
@@ -14,7 +14,7 @@ module Templates
|
||||
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 = /
|
||||
(?:
|
||||
|
||||
@@ -4,7 +4,7 @@ module Templates
|
||||
module ImageToFields
|
||||
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
|
||||
@endy ||= y + h
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ module Templates
|
||||
|
||||
if index.positive? && pdf_fields.present?
|
||||
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|
|
||||
a['attachment_uuid'] == preview_document[:attachment_uuid]
|
||||
end
|
||||
|
||||
@@ -9,10 +9,9 @@ require 'rspec/rails'
|
||||
require 'capybara/cuprite'
|
||||
require 'capybara/rspec'
|
||||
require 'webmock/rspec'
|
||||
require 'sidekiq/testing'
|
||||
require 'signing_form_helper'
|
||||
|
||||
Sidekiq::Testing.fake!
|
||||
Sidekiq.testing!(:fake)
|
||||
|
||||
WebMock.disable_net_connect!(allow_localhost: true)
|
||||
|
||||
@@ -69,11 +68,11 @@ RSpec.configure do |config|
|
||||
end
|
||||
|
||||
config.before do |example|
|
||||
Sidekiq::Testing.inline! if example.metadata[:sidekiq] == :inline
|
||||
Sidekiq.testing!(:inline) if example.metadata[:sidekiq] == :inline
|
||||
end
|
||||
|
||||
config.after do |example|
|
||||
Sidekiq::Testing.fake! if example.metadata[:sidekiq] == :inline
|
||||
Sidekiq.testing!(:fake) if example.metadata[:sidekiq] == :inline
|
||||
end
|
||||
|
||||
config.before(multitenant: true) do
|
||||
|
||||
Reference in New Issue
Block a user