2023-06-30 01:26:13 +03:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
|
|
module Accounts
|
2026-05-26 21:49:04 +03:00
|
|
|
LINK_EXPIRES_AT = ENV.fetch('FILE_URLS_EXPIRE_MINUTES', '40').to_i.minutes
|
2025-08-31 16:40:18 +03:00
|
|
|
|
2023-06-30 01:26:13 +03:00
|
|
|
module_function
|
|
|
|
|
|
2023-07-12 01:24:25 +03:00
|
|
|
def create_duplicate(account)
|
|
|
|
|
new_account = account.dup
|
|
|
|
|
|
|
|
|
|
new_user = account.users.first.dup
|
|
|
|
|
|
2023-10-14 21:19:21 +03:00
|
|
|
new_user.uuid = SecureRandom.uuid
|
2023-07-12 01:24:25 +03:00
|
|
|
new_user.account = new_account
|
|
|
|
|
new_user.encrypted_password = SecureRandom.hex
|
2024-10-16 12:16:20 +03:00
|
|
|
new_user.email = "#{SecureRandom.hex}@docuseal.com"
|
2023-07-12 01:24:25 +03:00
|
|
|
|
|
|
|
|
account.templates.each do |template|
|
|
|
|
|
new_template = template.dup
|
|
|
|
|
|
|
|
|
|
new_template.account = new_account
|
2023-07-14 22:33:42 +03:00
|
|
|
new_template.slug = SecureRandom.base58(14)
|
2023-07-12 01:24:25 +03:00
|
|
|
|
2023-12-30 00:37:03 +02:00
|
|
|
new_template.archived_at = nil
|
2023-07-12 01:24:25 +03:00
|
|
|
new_template.save!
|
|
|
|
|
|
|
|
|
|
Templates::CloneAttachments.call(template: new_template, original_template: template)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
new_user.save!(validate: false)
|
2023-10-14 21:19:21 +03:00
|
|
|
new_account.templates.update_all(folder_id: new_account.default_template_folder.id)
|
2023-07-12 01:24:25 +03:00
|
|
|
|
|
|
|
|
new_account
|
|
|
|
|
end
|
|
|
|
|
|
2024-05-26 20:51:02 +03:00
|
|
|
def users_count(account)
|
|
|
|
|
rel = User.where(account_id: account.id).or(
|
|
|
|
|
User.where(account_id: account.account_linked_accounts
|
|
|
|
|
.where.not(account_type: :testing)
|
|
|
|
|
.select(:linked_account_id))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
rel.where.not(account: account.linked_accounts.where.not(archived_at: nil))
|
|
|
|
|
.where.not(role: :integration).active.count
|
|
|
|
|
end
|
|
|
|
|
|
2024-01-20 23:53:14 +02:00
|
|
|
def find_or_create_testing_user(account)
|
2024-03-11 14:55:50 +02:00
|
|
|
user = User.where(role: :admin).order(:id).find_by(account: account.testing_accounts)
|
2024-01-20 23:53:14 +02:00
|
|
|
|
|
|
|
|
return user if user
|
|
|
|
|
|
|
|
|
|
testing_account = account.dup.tap { |a| a.name = "Testing - #{a.name}" }
|
2024-04-06 01:20:02 +03:00
|
|
|
testing_account.uuid = SecureRandom.uuid
|
2024-01-20 23:53:14 +02:00
|
|
|
|
|
|
|
|
ApplicationRecord.transaction do
|
|
|
|
|
account.testing_accounts << testing_account
|
|
|
|
|
|
2025-08-08 16:33:19 +03:00
|
|
|
original_email = account.users.order(:id).first.email
|
|
|
|
|
test_email = generate_unique_test_email(original_email)
|
|
|
|
|
|
2024-01-20 23:53:14 +02:00
|
|
|
testing_account.users.create!(
|
2025-08-08 16:33:19 +03:00
|
|
|
email: test_email,
|
2024-01-20 23:53:14 +02:00
|
|
|
first_name: 'Testing',
|
|
|
|
|
last_name: 'Environment',
|
|
|
|
|
password: SecureRandom.hex,
|
|
|
|
|
role: :admin
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2025-08-08 16:33:19 +03:00
|
|
|
def generate_unique_test_email(original_email)
|
|
|
|
|
base_email = original_email.sub('@', '+test@')
|
|
|
|
|
|
|
|
|
|
return base_email unless User.exists?(email: base_email)
|
|
|
|
|
|
|
|
|
|
(1..3).each do |i|
|
|
|
|
|
test_email = original_email.sub('@', "+test#{i}@")
|
|
|
|
|
|
|
|
|
|
return test_email unless User.exists?(email: test_email)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
timestamp = Time.current.to_i
|
|
|
|
|
|
|
|
|
|
original_email.sub('@', "+test#{timestamp}@")
|
|
|
|
|
end
|
|
|
|
|
|
2023-07-14 22:33:42 +03:00
|
|
|
def create_default_template(account)
|
|
|
|
|
template = Template.find(1)
|
|
|
|
|
|
|
|
|
|
new_template = Template.find(1).dup
|
|
|
|
|
new_template.account_id = account.id
|
|
|
|
|
new_template.slug = SecureRandom.base58(14)
|
2023-09-22 02:20:38 +03:00
|
|
|
new_template.folder = account.default_template_folder
|
2023-07-14 22:33:42 +03:00
|
|
|
|
|
|
|
|
new_template.save!
|
|
|
|
|
|
2025-06-06 23:14:17 +03:00
|
|
|
SearchEntries.enqueue_reindex(new_template)
|
|
|
|
|
|
2023-07-14 22:33:42 +03:00
|
|
|
Templates::CloneAttachments.call(template: new_template, original_template: template)
|
|
|
|
|
|
|
|
|
|
new_template
|
|
|
|
|
end
|
|
|
|
|
|
2025-12-19 11:55:25 +02:00
|
|
|
def load_recipient_form_fields(_account)
|
|
|
|
|
[]
|
|
|
|
|
end
|
|
|
|
|
|
2023-08-31 01:12:24 +03:00
|
|
|
def load_signing_pkcs(account)
|
|
|
|
|
cert_data =
|
2023-06-30 20:31:17 +03:00
|
|
|
if Docuseal.multitenant?
|
2024-05-01 23:40:09 +03:00
|
|
|
data = EncryptedConfig.find_by(account:, key: EncryptedConfig::ESIGN_CERTS_KEY)&.value
|
|
|
|
|
|
|
|
|
|
return Docuseal.default_pkcs if data.blank?
|
|
|
|
|
|
|
|
|
|
data
|
2023-06-30 20:31:17 +03:00
|
|
|
else
|
2024-09-13 22:37:11 +03:00
|
|
|
return Docuseal.default_pkcs if Docuseal::CERTS.present?
|
|
|
|
|
|
2024-01-20 23:53:14 +02:00
|
|
|
EncryptedConfig.find_by(account:, key: EncryptedConfig::ESIGN_CERTS_KEY)&.value ||
|
|
|
|
|
EncryptedConfig.find_by(key: EncryptedConfig::ESIGN_CERTS_KEY).value
|
2023-06-30 20:31:17 +03:00
|
|
|
end
|
|
|
|
|
|
2023-08-31 01:12:24 +03:00
|
|
|
if (default_cert = cert_data['custom']&.find { |e| e['status'] == 'default' })
|
2024-09-26 10:58:32 +03:00
|
|
|
if default_cert['name'] == Docuseal::AATL_CERT_NAME
|
|
|
|
|
Docuseal.default_pkcs
|
|
|
|
|
else
|
|
|
|
|
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(default_cert['data']), default_cert['password'].to_s)
|
|
|
|
|
end
|
2023-08-31 01:12:24 +03:00
|
|
|
else
|
|
|
|
|
GenerateCertificate.load_pkcs(cert_data)
|
|
|
|
|
end
|
2023-06-30 20:31:17 +03:00
|
|
|
end
|
|
|
|
|
|
2023-12-02 18:14:33 +02:00
|
|
|
def load_timeserver_url(account)
|
|
|
|
|
if Docuseal.multitenant?
|
|
|
|
|
Docuseal::TIMESERVER_URL
|
|
|
|
|
else
|
2023-12-04 12:47:19 +02:00
|
|
|
url = EncryptedConfig.find_by(account:, key: EncryptedConfig::TIMESTAMP_SERVER_URL_KEY)&.value
|
|
|
|
|
|
|
|
|
|
unless Docuseal.multitenant?
|
|
|
|
|
url ||=
|
|
|
|
|
Account.order(:id).first.encrypted_configs.find_by(key: EncryptedConfig::TIMESTAMP_SERVER_URL_KEY)&.value
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
url
|
2023-12-02 18:14:33 +02:00
|
|
|
end.presence
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-08 00:12:50 +03:00
|
|
|
def load_trusted_certs(account)
|
|
|
|
|
cert_data =
|
|
|
|
|
if Docuseal.multitenant?
|
|
|
|
|
value = EncryptedConfig.find_by(account:, key: EncryptedConfig::ESIGN_CERTS_KEY)&.value || {}
|
|
|
|
|
|
|
|
|
|
Docuseal::CERTS.merge(value)
|
2024-09-13 22:37:11 +03:00
|
|
|
elsif Docuseal::CERTS.present?
|
|
|
|
|
Docuseal::CERTS
|
2024-08-08 00:12:50 +03:00
|
|
|
else
|
|
|
|
|
EncryptedConfig.find_by(key: EncryptedConfig::ESIGN_CERTS_KEY)&.value || {}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
default_pkcs = GenerateCertificate.load_pkcs(cert_data)
|
|
|
|
|
|
2024-09-26 10:58:32 +03:00
|
|
|
custom_certs = cert_data.fetch('custom', []).filter_map do |e|
|
|
|
|
|
next if e['data'].blank?
|
|
|
|
|
|
2024-08-08 00:12:50 +03:00
|
|
|
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
[default_pkcs.certificate,
|
|
|
|
|
*default_pkcs.ca_certs,
|
|
|
|
|
*custom_certs.map(&:certificate),
|
|
|
|
|
*custom_certs.flat_map(&:ca_certs).compact,
|
|
|
|
|
*Docuseal.trusted_certs]
|
|
|
|
|
end
|
|
|
|
|
|
2024-04-13 11:51:47 +03:00
|
|
|
def can_send_emails?(_account, **_params)
|
2023-06-30 20:31:17 +03:00
|
|
|
return true if Docuseal.multitenant?
|
2026-03-27 12:56:52 +02:00
|
|
|
return true if Rails.env.development?
|
2023-08-11 18:32:43 +03:00
|
|
|
return true if ENV['SMTP_ADDRESS'].present?
|
2023-06-30 20:31:17 +03:00
|
|
|
|
2023-10-28 00:42:17 +03:00
|
|
|
EncryptedConfig.exists?(key: EncryptedConfig::EMAIL_SMTP_KEY)
|
2023-06-30 20:31:17 +03:00
|
|
|
end
|
|
|
|
|
|
2025-01-28 18:32:32 +02:00
|
|
|
def can_send_invitation_emails?(_account)
|
|
|
|
|
true
|
|
|
|
|
end
|
|
|
|
|
|
2023-06-30 01:26:13 +03:00
|
|
|
def normalize_timezone(timezone)
|
|
|
|
|
tzinfo = TZInfo::Timezone.get(ActiveSupport::TimeZone::MAPPING[timezone] || timezone)
|
|
|
|
|
|
|
|
|
|
::ActiveSupport::TimeZone.all.find { |e| e.tzinfo == tzinfo }&.name || timezone
|
2023-09-21 10:36:21 +03:00
|
|
|
rescue TZInfo::InvalidTimezoneIdentifier
|
|
|
|
|
'UTC'
|
2023-06-30 01:26:13 +03:00
|
|
|
end
|
2025-08-31 16:40:18 +03:00
|
|
|
|
|
|
|
|
def link_expires_at(account)
|
|
|
|
|
return if AccountConfig.find_or_initialize_by(account: account,
|
|
|
|
|
key: AccountConfig::DOWNLOAD_LINKS_EXPIRE_KEY).value == false
|
|
|
|
|
|
|
|
|
|
LINK_EXPIRES_AT.from_now
|
|
|
|
|
end
|
2023-06-30 01:26:13 +03:00
|
|
|
end
|