diff --git a/app/controllers/api/templates_documents_controller.rb b/app/controllers/api/templates_documents_controller.rb
index 04fdb12c..908b899d 100644
--- a/app/controllers/api/templates_documents_controller.rb
+++ b/app/controllers/api/templates_documents_controller.rb
@@ -22,6 +22,8 @@ module Api
}
)
}
+ rescue Templates::CreateAttachments::PdfEncrypted
+ render json: { error: 'PDF encrypted' }, status: :unprocessable_entity
end
end
end
diff --git a/app/controllers/templates_uploads_controller.rb b/app/controllers/templates_uploads_controller.rb
index 8823eeac..acb2ed38 100644
--- a/app/controllers/templates_uploads_controller.rb
+++ b/app/controllers/templates_uploads_controller.rb
@@ -10,12 +10,7 @@ class TemplatesUploadsController < ApplicationController
def create
url_params = create_file_params_from_url if params[:url].present?
- @template.account = current_account
- @template.author = current_user
- @template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name])
- @template.name = File.basename((url_params || params)[:files].first.original_filename, '.*')
-
- @template.save!
+ save_template!(@template, url_params)
documents = Templates::CreateAttachments.call(@template, url_params || params)
@@ -24,6 +19,8 @@ class TemplatesUploadsController < ApplicationController
@template.update!(schema:)
redirect_to edit_template_path(@template)
+ rescue Templates::CreateAttachments::PdfEncrypted
+ render turbo_stream: turbo_stream.append(params[:form_id], html: helpers.tag.prompt_password)
rescue StandardError => e
Rollbar.error(e) if defined?(Rollbar)
@@ -32,6 +29,17 @@ class TemplatesUploadsController < ApplicationController
private
+ def save_template!(template, url_params)
+ template.account = current_account
+ template.author = current_user
+ template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name])
+ template.name = File.basename((url_params || params)[:files].first.original_filename, '.*')
+
+ template.save!
+
+ template
+ end
+
def create_file_params_from_url
tempfile = Tempfile.new
tempfile.binmode
diff --git a/app/javascript/application.js b/app/javascript/application.js
index c20f0718..9c23a4cf 100644
--- a/app/javascript/application.js
+++ b/app/javascript/application.js
@@ -19,6 +19,7 @@ import SubmittersAutocomplete from './elements/submitter_autocomplete'
import FolderAutocomplete from './elements/folder_autocomplete'
import SignatureForm from './elements/signature_form'
import SubmitForm from './elements/submit_form'
+import PromptPassword from './elements/prompt_password'
import * as TurboInstantClick from './lib/turbo_instant_click'
@@ -51,6 +52,7 @@ window.customElements.define('submitters-autocomplete', SubmittersAutocomplete)
window.customElements.define('folder-autocomplete', FolderAutocomplete)
window.customElements.define('signature-form', SignatureForm)
window.customElements.define('submit-form', SubmitForm)
+window.customElements.define('prompt-password', PromptPassword)
document.addEventListener('turbo:before-fetch-request', encodeMethodIntoRequestBody)
document.addEventListener('turbo:submit-end', async (event) => {
diff --git a/app/javascript/elements/prompt_password.js b/app/javascript/elements/prompt_password.js
new file mode 100644
index 00000000..48561962
--- /dev/null
+++ b/app/javascript/elements/prompt_password.js
@@ -0,0 +1,19 @@
+export default class extends HTMLElement {
+ connectedCallback () {
+ const input = document.createElement('input')
+
+ input.type = 'hidden'
+ input.name = 'password'
+ input.value = prompt('Enter PDF password')
+
+ this.form.append(input)
+
+ this.form.requestSubmit()
+
+ this.remove()
+ }
+
+ get form () {
+ return this.closest('form')
+ }
+}
diff --git a/app/javascript/template_builder/upload.vue b/app/javascript/template_builder/upload.vue
index b0293b6c..49da7762 100644
--- a/app/javascript/template_builder/upload.vue
+++ b/app/javascript/template_builder/upload.vue
@@ -123,9 +123,30 @@ export default {
method: 'POST',
body: JSON.stringify({ blobs }),
headers: { 'Content-Type': 'application/json' }
- }).then(resp => resp.json()).then((data) => {
- this.$emit('success', data)
- this.$refs.input.value = ''
+ }).then((resp) => {
+ if (resp.ok) {
+ resp.json().then((data) => {
+ this.$emit('success', data)
+ this.$refs.input.value = ''
+ })
+ } else if (resp.status === 422) {
+ resp.json().then((data) => {
+ if (data.error === 'PDF encrypted') {
+ this.baseFetch(`/api/templates/${this.templateId}/documents`, {
+ method: 'POST',
+ body: JSON.stringify({ blobs, password: prompt('Enter PDF password') }),
+ headers: { 'Content-Type': 'application/json' }
+ }).then(async (resp) => {
+ if (resp.ok) {
+ this.$emit('success', await resp.json())
+ this.$refs.input.value = ''
+ } else {
+ alert('Wrong password')
+ }
+ })
+ }
+ })
+ }
}).finally(() => {
this.isProcessing = false
})
@@ -133,9 +154,33 @@ export default {
this.baseFetch(`/api/templates/${this.templateId}/documents`, {
method: 'POST',
body: new FormData(this.$refs.form)
- }).then(resp => resp.json()).then((data) => {
- this.$emit('success', data)
- this.$refs.input.value = ''
+ }).then((resp) => {
+ if (resp.ok) {
+ resp.json().then((data) => {
+ this.$emit('success', data)
+ this.$refs.input.value = ''
+ })
+ } else if (resp.status === 422) {
+ resp.json().then((data) => {
+ if (data.error === 'PDF encrypted') {
+ const formData = new FormData(this.$refs.form)
+
+ formData.append('password', prompt('Enter PDF password'))
+
+ this.baseFetch(`/api/templates/${this.templateId}/documents`, {
+ method: 'POST',
+ body: formData
+ }).then(async (resp) => {
+ if (resp.ok) {
+ this.$emit('success', await resp.json())
+ this.$refs.input.value = ''
+ } else {
+ alert('Wrong password')
+ }
+ })
+ }
+ })
+ }
}).finally(() => {
this.isLoading = false
})
diff --git a/app/views/dashboard/index.html.erb b/app/views/dashboard/index.html.erb
index 5dfbe091..9f1bde62 100644
--- a/app/views/dashboard/index.html.erb
+++ b/app/views/dashboard/index.html.erb
@@ -33,7 +33,8 @@
<% end %>
<% if params[:q].blank? && @pagy.pages == 1 && ((@template_folders.size < 10 && @templates.size.zero?) || (@template_folders.size < 7 && @templates.size < 4) || (@template_folders.size < 4 && @templates.size < 7)) %>
- <%= form_for '', url: templates_upload_path, method: :post, class: 'mt-8 block', html: { enctype: 'multipart/form-data' } do %>
+ <%= form_for '', url: templates_upload_path, id: form_id = SecureRandom.uuid, method: :post, class: 'mt-8 block', html: { enctype: 'multipart/form-data' } do %>
+