diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 11e9b3e7..af784ba2 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -112,7 +112,9 @@ module Api submissions = submissions.where(slug: params[:slug]) if params[:slug].present? if params[:template_folder].present? - submissions = submissions.joins(template: :folder).where(folder: { name: params[:template_folder] }) + folder = TemplateFolder.accessible_by(current_ability).find_by(name: params[:template_folder]) + + submissions = folder ? submissions.joins(:template).where(template: { folder_id: folder.id }) : submissions.none end if params.key?(:archived) diff --git a/app/controllers/api/templates_controller.rb b/app/controllers/api/templates_controller.rb index a36732a3..2af022e7 100644 --- a/app/controllers/api/templates_controller.rb +++ b/app/controllers/api/templates_controller.rb @@ -93,7 +93,12 @@ module Api templates = templates.where(external_id: params[:application_key]) if params[:application_key].present? templates = templates.where(external_id: params[:external_id]) if params[:external_id].present? templates = templates.where(slug: params[:slug]) if params[:slug].present? - templates = templates.joins(:folder).where(folder: { name: params[:folder] }) if params[:folder].present? + + if params[:folder].present? + folder = TemplateFolder.accessible_by(current_ability).find_by(name: params[:folder]) + + templates = folder ? templates.where(folder:) : templates.none + end templates end diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 16b5fc2d..0c9e3632 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -5,8 +5,12 @@ class ErrorsController < ActionController::Base 'This feature is available in Pro Edition: https://www.docuseal.com/pricing' ENTERPRISE_PATHS = [ + '/submissions/html', + '/api/submissions/html', '/templates/html', '/api/templates/html', + '/submissions/pdf', + '/api/submissions/pdf', '/templates/pdf', '/api/templates/pdf', '/templates/doc', diff --git a/app/controllers/search_entries_reindex_controller.rb b/app/controllers/search_entries_reindex_controller.rb new file mode 100644 index 00000000..afbe60b2 --- /dev/null +++ b/app/controllers/search_entries_reindex_controller.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class SearchEntriesReindexController < ApplicationController + def create + authorize!(:manage, EncryptedConfig) + + ReindexAllSearchEntriesJob.perform_async + + AccountConfig.find_or_initialize_by(account_id: Account.minimum(:id), key: :fulltext_search) + .update!(value: true) + + Docuseal.instance_variable_set(:@fulltext_search, nil) + + redirect_back(fallback_location: settings_account_path, + notice: "Started building search index. Visit #{root_url}jobs/busy to check progress.") + end +end diff --git a/app/controllers/send_submission_email_controller.rb b/app/controllers/send_submission_email_controller.rb index ef6ff62b..45852360 100644 --- a/app/controllers/send_submission_email_controller.rb +++ b/app/controllers/send_submission_email_controller.rb @@ -11,11 +11,16 @@ class SendSubmissionEmailController < ApplicationController def create if params[:template_slug] - @submitter = Submitter.completed.joins(submission: :template).find_by!(email: params[:email].to_s.downcase, - template: { slug: params[:template_slug] }) + template = Template.find_by!(slug: params[:template_slug]) + + @submitter = + Submitter.completed.where(submission: template.submissions).find_by!(email: params[:email].to_s.downcase) elsif params[:submission_slug] - @submitter = Submitter.completed.joins(:submission).find_by(email: params[:email].to_s.downcase, - submission: { slug: params[:submission_slug] }) + submission = Submission.find_by(slug: params[:submission_slug]) + + if submission + @submitter = Submitter.completed.find_by(submission: submission, email: params[:email].to_s.downcase) + end return redirect_to submissions_preview_completed_path(params[:submission_slug], status: :error) unless @submitter else @@ -24,14 +29,18 @@ class SendSubmissionEmailController < ApplicationController RateLimit.call("send-email-#{@submitter.id}", limit: 2, ttl: 5.minutes) - unless EmailEvent.exists?(tag: :submitter_documents_copy, email: @submitter.email, emailable: @submitter, - event_type: :send, created_at: SEND_DURATION.ago..Time.current) - SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later! - end + SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later! unless already_sent?(@submitter) respond_to do |f| f.html { render :success } f.json { head :ok } end end + + private + + def already_sent?(submitter) + EmailEvent.exists?(tag: :submitter_documents_copy, email: submitter.email, emailable: submitter, + event_type: :send, created_at: SEND_DURATION.ago..Time.current) + end end diff --git a/app/controllers/setup_controller.rb b/app/controllers/setup_controller.rb index 9b49b1f8..778255bc 100644 --- a/app/controllers/setup_controller.rb +++ b/app/controllers/setup_controller.rb @@ -34,6 +34,7 @@ class SetupController < ApplicationController { key: EncryptedConfig::ESIGN_CERTS_KEY, value: GenerateCertificate.call.transform_values(&:to_pem) } ] @account.encrypted_configs.create!(encrypted_configs) + @account.account_configs.create!(key: :fulltext_search, value: true) if SearchEntry.table_exists? Docuseal.refresh_default_url_options! diff --git a/app/controllers/submitters_autocomplete_controller.rb b/app/controllers/submitters_autocomplete_controller.rb index 70f02747..efbb110a 100644 --- a/app/controllers/submitters_autocomplete_controller.rb +++ b/app/controllers/submitters_autocomplete_controller.rb @@ -22,7 +22,7 @@ class SubmittersAutocompleteController < ApplicationController def search_submitters(submitters) if SELECT_COLUMNS.include?(params[:field]) - if Docuseal.fulltext_search?(current_user) + if Docuseal.fulltext_search? Submitters.fulltext_search_field(current_user, submitters, params[:q], params[:field]) else column = Submitter.arel_table[params[:field].to_sym] diff --git a/app/controllers/template_folders_autocomplete_controller.rb b/app/controllers/template_folders_autocomplete_controller.rb index c3b621bc..120fe8dc 100644 --- a/app/controllers/template_folders_autocomplete_controller.rb +++ b/app/controllers/template_folders_autocomplete_controller.rb @@ -6,7 +6,9 @@ class TemplateFoldersAutocompleteController < ApplicationController LIMIT = 100 def index - template_folders = @template_folders.joins(:templates).where(templates: { archived_at: nil }).distinct + templates_query = Template.accessible_by(current_ability).where(archived_at: nil) + + template_folders = @template_folders.where(id: templates_query.select(:folder_id)) template_folders = TemplateFolders.search(template_folders, params[:q]).limit(LIMIT) render json: template_folders.as_json(only: %i[name archived_at]) diff --git a/app/controllers/templates_dashboard_controller.rb b/app/controllers/templates_dashboard_controller.rb index af47d179..51922c48 100644 --- a/app/controllers/templates_dashboard_controller.rb +++ b/app/controllers/templates_dashboard_controller.rb @@ -36,6 +36,8 @@ class TemplatesDashboardController < ApplicationController end @pagy, @templates = pagy_auto(@templates, limit:) + + load_related_submissions if params[:q].present? && @templates.blank? end end @@ -100,4 +102,19 @@ class TemplatesDashboardController < ApplicationController template_folders.order(id: :desc) end end + + def load_related_submissions + @related_submissions = Submission.accessible_by(current_ability) + .left_joins(:template) + .where(archived_at: nil) + .where(templates: { archived_at: nil }) + .preload(:template_accesses, :created_by_user, + template: :author, + submitters: :start_form_submission_events) + + @related_submissions = Submissions.search(current_user, @related_submissions, params[:q]) + .order(id: :desc) + + @related_submissions_pagy, @related_submissions = pagy_auto(@related_submissions, limit: 5) + end end diff --git a/app/controllers/templates_preferences_controller.rb b/app/controllers/templates_preferences_controller.rb index 8f820e3f..e2ec9ee3 100644 --- a/app/controllers/templates_preferences_controller.rb +++ b/app/controllers/templates_preferences_controller.rb @@ -25,7 +25,7 @@ class TemplatesPreferencesController < ApplicationController documents_copy_email_attach_documents documents_copy_email_reply_to completed_notification_email_attach_documents completed_redirect_url validate_unique_submitters - submitters_order require_phone_2fa + require_all_submitters submitters_order require_phone_2fa default_expire_at_duration default_expire_at completed_notification_email_subject completed_notification_email_body diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index e36a3c61..5df396d8 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -1052,6 +1052,12 @@ export default { field.readonly = true } + if (type === 'datenow') { + field.type = 'date' + field.readonly = true + field.default_value = '{{date}}' + } + if (type === 'date') { field.preferences = { format: this.defaultDateFormat @@ -1450,6 +1456,12 @@ export default { } } + if (field.type === 'datenow') { + field.type = 'date' + field.readonly = true + field.default_value = '{{date}}' + } + if (['stamp', 'heading'].includes(field.type)) { field.readonly = true } diff --git a/app/javascript/template_builder/field_type.vue b/app/javascript/template_builder/field_type.vue index df0bd488..1ccaf5cb 100644 --- a/app/javascript/template_builder/field_type.vue +++ b/app/javascript/template_builder/field_type.vue @@ -51,7 +51,7 @@