diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index dcecd946f..8fd89a1db 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -24,7 +24,7 @@ def message_drafts @message.save permitted_message_draft_params.fetch(:objects, []).each do |object_params| - message_object = @message.objects.create(object_params.except(:content, :tags)) + message_object = @message.objects.create(object_params.except(:content, :to_be_signed, :tags)) object_params.fetch(:tags, []).each do |tag_name| tag = @tenant.user_signature_tags.find_by(name: tag_name) @@ -33,6 +33,11 @@ def message_drafts end @message.thread.box.tenant.signed_externally_tag!.assign_to_message_object(message_object) if message_object.is_signed + if object_params[:to_be_signed] + @message.tenant.signer_group.signature_requested_from_tag&.assign_to_message_object(message_object) + @message.tenant.signer_group.signature_requested_from_tag&.assign_to_thread(@message.thread) + end + MessageObjectDatum.create( message_object: message_object, blob: Base64.decode64(object_params[:content]) diff --git a/app/controllers/message_drafts_controller.rb b/app/controllers/message_drafts_controller.rb index 9a54a3f1c..ecbaa9c28 100644 --- a/app/controllers/message_drafts_controller.rb +++ b/app/controllers/message_drafts_controller.rb @@ -13,7 +13,6 @@ def submit if @message.submit redirect_to message_thread_path(@message.thread), notice: "Správa bola zaradená na odoslanie" else - # TODO FIX: Tato hlaska sa zobrazuje aj ked je object oznaceny ako to_be_signed, ale nebol este podpisany redirect_to message_thread_path(@message.thread), alert: @message.not_submittable_errors.join(', ') end end diff --git a/app/controllers/message_threads/bulk/message_drafts_controller.rb b/app/controllers/message_threads/bulk/message_drafts_controller.rb index 05fecbad6..9a1a54030 100644 --- a/app/controllers/message_threads/bulk/message_drafts_controller.rb +++ b/app/controllers/message_threads/bulk/message_drafts_controller.rb @@ -9,10 +9,12 @@ def submit message_threads = message_thread_policy_scope.where(id: ids).includes(:messages) message_threads.transaction do submission_results = SubmitMessageDraftsAction.run(message_threads) - if submission_results - redirect_back fallback_location: message_threads_path, notice: "Správy vo vláknach boli zaradené na odoslanie", status: 303 - else + if submission_results.none?(true) + redirect_back fallback_location: message_threads_path, alert: "Vo vláknach sa našli správy, ktoré neboli podpísané všetkými podpismi", status: 303 and return if any_missing_signature?(message_threads) redirect_back fallback_location: message_threads_path, alert: "Vo vláknach sa nenašli žiadne správy na odoslanie", status: 303 + else + redirect_back fallback_location: message_threads_path, alert: "Správy, ktoré neboli podpísané všetkými podpismi neboli zaradené na odoslanie", status: 303 and return if any_missing_signature?(message_threads) + redirect_back fallback_location: message_threads_path, notice: "Správy vo vláknach boli zaradené na odoslanie", status: 303 end end end @@ -41,6 +43,10 @@ def destroy def message_thread_policy_scope policy_scope(MessageThread) end + + def any_missing_signature?(message_threads) + MessageThreadsTag.where(message_thread: message_threads, tag: Current.tenant.tags.signature_requesting).exists? + end end end end diff --git a/app/jobs/upvs/drafts/load_content_job.rb b/app/jobs/upvs/drafts/load_content_job.rb index 9180ffa49..e3a041f65 100644 --- a/app/jobs/upvs/drafts/load_content_job.rb +++ b/app/jobs/upvs/drafts/load_content_job.rb @@ -39,12 +39,16 @@ def load_message_draft_objects(message_draft, objects_path, signed:, to_be_signe mimetype: Utils.file_mimetype_by_name(entry_name: file_name, is_form: is_form), object_type: is_form ? "FORM" : "ATTACHMENT", is_signed: signed, - to_be_signed: to_be_signed, message: message_draft, visualizable: is_form ? false : nil, tags: tags ) + if to_be_signed + message_draft_object.message.tenant.signer_group.signature_requested_from_tag&.assign_to_message_object(message_draft_object) + message_draft_object.message.tenant.signer_group.signature_requested_from_tag&.assign_to_thread(message_draft_object.message.thread) + end + MessageObjectDatum.create( message_object: message_draft_object, blob: File.read(File.join(objects_path, file_name)) diff --git a/app/models/fs/message_draft.rb b/app/models/fs/message_draft.rb index 18b9d9abf..c23776006 100644 --- a/app/models/fs/message_draft.rb +++ b/app/models/fs/message_draft.rb @@ -70,13 +70,12 @@ def self.create_and_validate_with_fs_form(form_files: [], author:, fs_client: Fs form_object = message.objects.create( object_type: 'FORM', name: form_file.original_filename, - mimetype: form_file.content_type, - to_be_signed: fs_form.signature_required + mimetype: form_file.content_type ) form_object.update(is_signed: form_object.asice?) message.thread.box.tenant.signed_externally_tag!.assign_to_message_object(form_object) if form_object.is_signed? - if form_object.to_be_signed && !form_object.is_signed? + if fs_form.signature_required && !form_object.is_signed? message.thread.box.tenant.signer_group.signature_requested_from_tag&.assign_to_message_object(form_object) message.thread.box.tenant.signer_group.signature_requested_from_tag&.assign_to_thread(message.thread) end diff --git a/app/models/message.rb b/app/models/message.rb index c86f7512c..edd77d2ce 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -96,6 +96,10 @@ def authorized? metadata["delivery_notification"] && metadata["authorized"] == true end + def any_objects_with_requested_signature? + MessageObjectsTag.where(message_object: objects, tag: tenant.tags.signature_requesting).exists? + end + # TODO remove UPVS stuff from core domain def form ::Upvs::Form.find_by( diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 2e03797a8..3a651ccd2 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -106,7 +106,7 @@ def created_from_template? end def submittable? - form_object.content.present? && objects.to_be_signed.all? { |o| o.is_signed? } && correctly_created? && valid?(:validate_data) + form_object&.content&.present? && correctly_created? && valid?(:validate_data) && !any_objects_with_requested_signature? end def not_submittable_errors @@ -114,7 +114,7 @@ def not_submittable_errors errors = [] errors << 'Vyplňte obsah správy' unless form_object.content.present? - errors << 'Pred odoslaním podpíšte všetky dokumenty na podpis' unless objects.to_be_signed.all? { |o| o.is_signed? } + errors << 'Pred odoslaním podpíšte všetky dokumenty na podpis' if any_objects_with_requested_signature? errors << 'Obsah správy nie je validný' if invalid? || !valid?(:validate_data) errors << 'Správu bude možné odoslať až po ukončení validácie' if being_validated? diff --git a/app/models/message_object.rb b/app/models/message_object.rb index 33e763609..30215df7a 100644 --- a/app/models/message_object.rb +++ b/app/models/message_object.rb @@ -7,7 +7,6 @@ # mimetype :string # name :string # object_type :string not null -# to_be_signed :boolean default(FALSE), not null # uuid :uuid # visualizable :boolean # created_at :datetime not null @@ -25,8 +24,6 @@ class MessageObject < ApplicationRecord has_one :archived_object, dependent: :destroy scope :unsigned, -> { where(is_signed: false) } - scope :to_be_signed, -> { where(to_be_signed: true) } - scope :should_be_signed, -> { where(to_be_signed: true, is_signed: false) } validates :name, presence: { message: "Name can't be blank" }, on: :validate_data validate :allowed_mimetype?, on: :validate_data @@ -163,11 +160,11 @@ def thread def remove_object_related_tags_from_thread tags.each do |tag| - message.thread.unassign_tag(tag) unless other_thread_objects_include_tag?(tag) + thread.unassign_tag(tag) unless other_thread_objects_include_tag?(tag) end - message.thread.unassign_tag(message.tenant.signed_tag!) unless message.thread.tags.reload.where(type: SignedByTag.to_s).any? - message.thread.unassign_tag(message.tenant.signature_requested_tag!) unless message.thread.tags.reload.where(type: SignatureRequestedFromTag.to_s).any? + thread.unassign_tag(message.tenant.signed_tag!) unless thread.tags.reload.where(type: SignedByTag.to_s).any? + thread.unassign_tag(message.tenant.signature_requested_tag!) unless thread.tags.reload.where(type: SignatureRequestedFromTag.to_s).any? end def other_thread_objects_include_tag?(tag) diff --git a/app/models/tag.rb b/app/models/tag.rb index 9df1e434f..3fcad2b2d 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -39,6 +39,7 @@ class Tag < ApplicationRecord scope :signing_tags, -> { where(type: ["SignedTag", "SignedByTag", "SignatureRequestedTag", "SignatureRequestedFromTag"]) } scope :signed, -> { where(type: ["SignedTag", "SignedByTag", "SignedExternallyTag"]) } scope :signed_by, -> { where(type: "SignedByTag") } + scope :signature_requesting, -> { where(type: "SignatureRequestedFromTag") } scope :signed_internally, -> { where(type: ["SignedTag", "SignedByTag"]) } scope :archived, -> { where(type: ArchivedTag.to_s) } diff --git a/db/migrate/20241029064753_remove_to_be_signed_attribute_from_message_objects.rb b/db/migrate/20241029064753_remove_to_be_signed_attribute_from_message_objects.rb new file mode 100644 index 000000000..50256c12c --- /dev/null +++ b/db/migrate/20241029064753_remove_to_be_signed_attribute_from_message_objects.rb @@ -0,0 +1,5 @@ +class RemoveToBeSignedAttributeFromMessageObjects < ActiveRecord::Migration[7.1] + def change + remove_column :message_objects, :to_be_signed + end +end diff --git a/db/schema.rb b/db/schema.rb index a42c507fa..1b82c0a91 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_10_25_151903) do +ActiveRecord::Schema[7.1].define(version: 2024_10_29_064753) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -387,7 +387,6 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "is_signed" - t.boolean "to_be_signed", default: false, null: false t.boolean "visualizable" t.uuid "uuid" t.index ["message_id"], name: "index_message_objects_on_message_id" diff --git a/public/openapi.yaml b/public/openapi.yaml index 85eff9eba..da517fe51 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -351,7 +351,7 @@ paths: description: Indikátor či je obsah objektu podpísaný type: boolean to_be_signed: - description: Indikátor či obsah objektu má byť podpísaný + description: Indikátor či obsah objektu má byť podpísaný. V prípade hodnoty true je vyžiadaný podpis na danom objekte type: boolean mimetype: description: Typ internetového média v súlade s typom a obsahom objektu diff --git a/test/fixtures/message_object_data.yml b/test/fixtures/message_object_data.yml index b01660fca..b392fe4a5 100644 --- a/test/fixtures/message_object_data.yml +++ b/test/fixtures/message_object_data.yml @@ -8,10 +8,18 @@ two: message_object: ssd_main_general_two_form blob: MyText +main_draft: + message_object: ssd_main_draft_form + blob: predmettext + draft_two: message_object: ssd_main_general_draft_two_form blob: predmettext +draft_three: + message_object: ssd_main_draft_to_be_signed2_draft_form + blob: predmettext + empty_draft: message_object: ssd_main_empty_draft_form blob: diff --git a/test/fixtures/message_objects.yml b/test/fixtures/message_objects.yml index c6e355c1f..7a9739dd4 100644 --- a/test/fixtures/message_objects.yml +++ b/test/fixtures/message_objects.yml @@ -49,6 +49,12 @@ ssd_main_fs_one_form: mimetype: application/x-eform-xml object_type: FORM +ssd_main_draft_form: + message: ssd_main_draft + name: MyString + mimetype: application/x-eform-xml + object_type: FORM + ssd_main_draft_to_be_signed_draft_one_form: uuid: 6a0f716a-c284-4680-ad7e-ed2bde769dd2 message: ssd_main_draft_to_be_signed_draft_one @@ -80,7 +86,7 @@ ssd_main_draft_to_be_signed_draft_two_form: ssd_main_draft_to_be_signed2_draft_form: message: ssd_main_draft_to_be_signed2_draft name: MyString - mimetype: MyString + mimetype: application/x-eform-xml object_type: FORM ssd_main_draft_to_be_signed3_draft_one_form: diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml index e189d0928..e83e75a97 100644 --- a/test/fixtures/messages.yml +++ b/test/fixtures/messages.yml @@ -217,7 +217,7 @@ ssd_main_draft_to_be_signed_draft_two: author: basic ssd_main_draft_to_be_signed2_draft: - type: MessageDraft + type: Upvs::MessageDraft uuid: <%= SecureRandom.uuid %> title: MyStringDraft3 html_visualization: MyString @@ -226,6 +226,13 @@ ssd_main_draft_to_be_signed2_draft: replyable: false metadata: status: created + sktalk_class: EGOV_APPLICATION + posp_id: App.GeneralAgenda + posp_version: 1.9 + message_type: App.GeneralAgenda + correlation_id: <%= SecureRandom.uuid %> + recipient_uri: + ico://sk/12345678 author: basic ssd_main_draft_to_be_signed3_draft: diff --git a/test/integration/upvs_message_drafts_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb index 670dd2eb4..94c1b20c5 100644 --- a/test/integration/upvs_message_drafts_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -43,6 +43,42 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest assert_not_equal Message.count, @before_request_messages_count end + test 'SignatureRestedTag is assigned from SignerGroup if object marked to_be_signed' do + message_params = { + type: 'Upvs::MessageDraft', + title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + }, + objects: [ + { + name: 'Form.xml', + is_signed: false, + to_be_signed: true, + mimetype: 'application/x-eform-xml', + object_type: 'FORM', + content: Base64.encode64(' + + Všeobecný predmet + Všeobecný text +') + } + ] + } + + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair)} ), as: :json + + assert_response :created + assert @box.messages.last.objects.first.tags.include?(@tenant.signer_group.signature_requested_from_tag) + assert @box.messages.last.thread.tags.include?(@tenant.signature_requested_tag!) + end + test 'can upload valid message with tags if they exist' do message_params = { type: 'Upvs::MessageDraft', diff --git a/test/models/message_object_test.rb b/test/models/message_object_test.rb index 7d0f4c043..f3e109145 100644 --- a/test/models/message_object_test.rb +++ b/test/models/message_object_test.rb @@ -206,6 +206,15 @@ class MessageObjectTest < ActiveSupport::TestCase assert_not object.message.thread.tags.include?(tenant.signed_tag!) end + test "before_destroy callback deletes SignatureRequested Tag from message thread (if no more objects with SignatureRequestedFromTag present)" do + message_object = message_objects(:ssd_main_draft_form) + message_thread = message_object.message.thread + + message_object.destroy + + assert_equal false, message_thread.tags.reload.include?(message_thread.tenant.signature_requested_tag!) + end + test "before_destroy callback keeps object related tags for message thread (if another objects with the tag present in the message)" do tenant = tenants(:ssd) signer = users(:basic_two) diff --git a/test/system/message_drafts_test.rb b/test/system/message_drafts_test.rb index c29b01a07..24e8e6cbf 100644 --- a/test/system/message_drafts_test.rb +++ b/test/system/message_drafts_test.rb @@ -56,4 +56,19 @@ class MessageDraftsTest < ApplicationSystemTestCase refute_selector(thread_in_listing_selector(thread_general)) refute_selector(thread_in_listing_selector(thread_issue)) end + + test "message is not submitted and flash message is shown when user tries to send message without requested signatures present" do + message_thread = message_threads(:ssd_main_draft_to_be_signed2) + message_draft = messages(:ssd_main_draft_to_be_signed2_draft) + + visit message_thread_path(message_thread) + + within("#upvs_message_draft_#{message_draft.id}") do + assert_button "Odoslať" + + click_button "Odoslať" + end + + assert_text "Pred odoslaním podpíšte všetky dokumenty na podpis" + end end