diff --git a/app/components/message_state_component.html.erb b/app/components/message_state_component.html.erb
index b142f2482..447e2aa77 100644
--- a/app/components/message_state_component.html.erb
+++ b/app/components/message_state_component.html.erb
@@ -1,11 +1,17 @@
<% if @message.form_object&.is_signed? || @message.form_object.present? || @message.authorized? %>
-
- <% if @message.form_object&.is_signed? %>
+
+ <% if @message.form_object&.tags&.signed_by&.any? %>
+ <% @message.form_object.tags.signed_by.each do |tag| %>
+ <%= render Common::BadgeComponent.new(tag.name, "green", "fingerprint") %>
+ <% end %>
+ <% elsif @message.form_object&.is_signed? %>
<%= render Common::BadgeComponent.new("Podpísané", "green", "fingerprint") %>
<% end %>
+
<% if @message.authorized? %>
<%= render Common::BadgeComponent.new("Prevzatá doručenka", "purple") %>
<% end %>
+
<% if @message.thread.archived? %>
<%= render ArchivedObjectTagComponent.new(@message.form_object&.archived_object) %>
<% end %>
diff --git a/app/jobs/govbox/process_message_job.rb b/app/jobs/govbox/process_message_job.rb
index 02ce40d19..65ac73700 100644
--- a/app/jobs/govbox/process_message_job.rb
+++ b/app/jobs/govbox/process_message_job.rb
@@ -10,8 +10,6 @@ def perform(govbox_message)
processed_message = ::Message.where(type: [nil, 'Message']).where(uuid: govbox_message.message_id).joins(:thread).where(thread: { box_id: govbox_message.box.id }).take
ActiveRecord::Base.transaction do
- destroy_associated_message_draft(govbox_message)
-
message = Govbox::Message.create_message_with_thread!(govbox_message)
mark_delivery_notification_authorized(govbox_message)
@@ -24,11 +22,6 @@ def perform(govbox_message)
private
- def destroy_associated_message_draft(govbox_message)
- message_draft = Upvs::MessageDraft.where(uuid: govbox_message.message_id).joins(:thread).where(thread: { box_id: govbox_message.box.id }).take
- message_draft&.destroy
- end
-
def mark_delivery_notification_authorized(govbox_message)
return unless govbox_message.delivery_notification
diff --git a/app/jobs/govbox/submit_message_draft_job.rb b/app/jobs/govbox/submit_message_draft_job.rb
index 6615204da..d265b8417 100644
--- a/app/jobs/govbox/submit_message_draft_job.rb
+++ b/app/jobs/govbox/submit_message_draft_job.rb
@@ -51,7 +51,7 @@ def build_objects(message_draft)
objects = []
message_draft.objects.each do |object|
objects << {
- id: SecureRandom.uuid,
+ id: object.uuid,
name: object.name,
encoding: "Base64",
signed: object.is_signed,
diff --git a/app/models/govbox/message.rb b/app/models/govbox/message.rb
index fb48bb937..1de014cbd 100644
--- a/app/models/govbox/message.rb
+++ b/app/models/govbox/message.rb
@@ -27,11 +27,13 @@ class Govbox::Message < ApplicationRecord
def self.create_message_with_thread!(govbox_message)
message = nil
+ message_draft = Upvs::MessageDraft.where(uuid: govbox_message.message_id).joins(:thread).where(thread: { box_id: govbox_message.box.id }).take
MessageThread.with_advisory_lock!(govbox_message.correlation_id, transaction: true, timeout_seconds: 10) do
message = create_message(govbox_message)
- message.thread = govbox_message.box.message_threads.find_or_create_by_merge_uuid!(
+ message.thread = message_draft&.thread
+ message.thread ||= govbox_message.box.message_threads.find_or_create_by_merge_uuid!(
box: govbox_message.box,
merge_uuid: govbox_message.correlation_id,
title: message.metadata.dig("delivery_notification", "consignment", "subject").presence || message.title,
@@ -40,10 +42,17 @@ def self.create_message_with_thread!(govbox_message)
message.save!
+ create_message_objects(message, govbox_message.payload)
+
add_upvs_related_tags(message, govbox_message)
- end
- create_message_objects(message, govbox_message.payload)
+ if message_draft
+ copy_tags_from_draft(message, message_draft)
+ message_draft.destroy
+ end
+
+ MessageObject.mark_message_objects_externally_signed(message.objects)
+ end
EventBus.publish(:message_thread_created, message.thread) if message.thread.previously_new_record?
EventBus.publish(:message_created, message)
@@ -103,15 +112,14 @@ def self.create_message_objects(message, raw_message)
raw_message["objects"].each do |raw_object|
message_object_type = raw_object["class"]
visualizable = (message_object_type == "FORM" && message.html_visualization.present?) ? true : nil
- tags = raw_object["signed"] ? [message.thread.box.tenant.signed_externally_tag!] : []
message_object = message.objects.create!(
+ uuid: raw_object["id"],
name: raw_object["name"],
mimetype: raw_object["mime_type"],
is_signed: raw_object["signed"],
object_type: message_object_type,
- visualizable: visualizable,
- tags: tags
+ visualizable: visualizable
)
if raw_object["encoding"] == "Base64"
@@ -140,6 +148,15 @@ def self.add_upvs_related_tags(message, govbox_message)
add_delivery_notification_tag(message) if message.can_be_authorized?
end
+ def self.copy_tags_from_draft(message, message_draft)
+ message_draft.objects.map do |message_draft_object|
+ message_object = message.objects.find_by(uuid: message_draft_object.uuid)
+ message_draft_object.tags.signed.each { |tag| message_object.assign_tag(tag) }
+ end
+
+ (message_draft.tags.simple + message_draft.tags.signed).each { |tag| message.assign_tag(tag) }
+ end
+
def self.add_delivery_notification_tag(message)
message.add_cascading_tag(delivery_notification_tag(message))
end
diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb
index 5dbd4839d..2e03797a8 100644
--- a/app/models/message_draft.rb
+++ b/app/models/message_draft.rb
@@ -79,7 +79,6 @@ def update_content(parameters)
def submit
raise NotImplementedError
end
-
def draft?
true
end
diff --git a/app/models/message_object.rb b/app/models/message_object.rb
index 08579fd15..33e763609 100644
--- a/app/models/message_object.rb
+++ b/app/models/message_object.rb
@@ -8,6 +8,7 @@
# name :string
# object_type :string not null
# to_be_signed :boolean default(FALSE), not null
+# uuid :uuid
# visualizable :boolean
# created_at :datetime not null
# updated_at :datetime not null
@@ -57,6 +58,14 @@ def self.create_message_objects(message, objects)
end
end
+ def self.mark_message_objects_externally_signed(objects)
+ objects.find_each do |object|
+ next unless object.is_signed?
+
+ object.assign_tag(object.message.tenant.signed_externally_tag!) unless object.tags.signed_internally.present?
+ end
+ end
+
def mark_signed_by_user(user)
assign_tag(user.signed_by_tag)
unassign_tag(user.signature_requested_from_tag)
@@ -117,6 +126,7 @@ def assign_tag(tag)
end
def fill_missing_info
+ update(uuid: SecureRandom.uuid) unless uuid.present?
update(name: name + Utils.file_extension_by_mimetype(mimetype).to_s) if Utils.file_name_without_extension?(self)
update(mimetype: Utils.file_mimetype_by_name(entry_name: name)) if mimetype == Utils::OCTET_STREAM_MIMETYPE
end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 3f28c1fc1..9df1e434f 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -37,6 +37,9 @@ class Tag < ApplicationRecord
scope :simple, -> { where(type: SimpleTag.to_s) }
scope :visible, -> { where(visible: true) }
scope :signing_tags, -> { where(type: ["SignedTag", "SignedByTag", "SignatureRequestedTag", "SignatureRequestedFromTag"]) }
+ scope :signed, -> { where(type: ["SignedTag", "SignedByTag", "SignedExternallyTag"]) }
+ scope :signed_by, -> { where(type: "SignedByTag") }
+ scope :signed_internally, -> { where(type: ["SignedTag", "SignedByTag"]) }
scope :archived, -> { where(type: ArchivedTag.to_s) }
after_update_commit ->(tag) { EventBus.publish(:tag_renamed, tag) if previous_changes.key?("name") }
diff --git a/db/migrate/20240927104543_add_uuid_to_message_objects.rb b/db/migrate/20240927104543_add_uuid_to_message_objects.rb
new file mode 100644
index 000000000..a535f4a20
--- /dev/null
+++ b/db/migrate/20240927104543_add_uuid_to_message_objects.rb
@@ -0,0 +1,5 @@
+class AddUuidToMessageObjects < ActiveRecord::Migration[7.1]
+ def change
+ add_column :message_objects, :uuid, :uuid
+ end
+end
diff --git a/db/migrate/20241025151903_update_index_on_uuid_message_thread_id_to_messages.rb b/db/migrate/20241025151903_update_index_on_uuid_message_thread_id_to_messages.rb
new file mode 100644
index 000000000..92362e8c1
--- /dev/null
+++ b/db/migrate/20241025151903_update_index_on_uuid_message_thread_id_to_messages.rb
@@ -0,0 +1,8 @@
+class UpdateIndexOnUuidMessageThreadIdToMessages < ActiveRecord::Migration[7.1]
+ def change
+ remove_index :messages, name: 'index_messages_on_uuid_and_message_thread_id'
+
+ add_unique_constraint :messages, [:uuid, :message_thread_id], deferrable: :deferred
+ end
+end
+
diff --git a/db/schema.rb b/db/schema.rb
index b22c56b6d..a42c507fa 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_08_20_143244) do
+ActiveRecord::Schema[7.1].define(version: 2024_10_25_151903) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
@@ -389,6 +389,7 @@
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"
end
@@ -486,6 +487,7 @@
t.index ["author_id"], name: "index_messages_on_author_id"
t.index ["import_id"], name: "index_messages_on_import_id"
t.index ["message_thread_id"], name: "index_messages_on_message_thread_id"
+ t.unique_constraint ["uuid", "message_thread_id"], deferrable: :deferred
end
create_table "messages_tags", force: :cascade do |t|
diff --git a/test/fixtures/govbox/messages.yml b/test/fixtures/govbox/messages.yml
index ac834c646..1ba47166f 100644
--- a/test/fixtures/govbox/messages.yml
+++ b/test/fixtures/govbox/messages.yml
@@ -139,6 +139,39 @@ ssd_referring_to_outbox_message:
class: MyClass
content: MyContent
+ssd_general_created_from_draft:
+ message_id: 9b1b718a-c06c-487c-86c2-b68b8606aa5c
+ correlation_id: 7a364355-882c-41d2-b1b3-e215644f805b
+ edesk_message_id: 7
+ delivered_at: <%= DateTime.current %>
+ edesk_class: TEST
+ folder: ssd_sent
+ payload:
+ message_id: 9b1b718a-c06c-487c-86c2-b68b8606aa5c
+ subject: Title is not shown
+ sender_name: MySender
+ sender_uri: MySenderURIq
+ recipient_name: MyRecipient
+ delivered_at: <%= DateTime.current.to_s %>
+ original_html: Reply to something
+ objects:
+ - id: 6a0f716a-c284-4680-ad7e-ed2bde769dd2
+ name: MyString
+ mime_type: MyString
+ class: FORM
+ content: MyContent
+ - id: af0e1c11-d226-45b7-8816-a5c24e139d35
+ name: Attachment
+ mime_type: MyString
+ class: ATTACHMENT
+ content: MyContent
+ - id: 57c9954c-93e2-470c-833c-fd2bc6d8c70f
+ name: Attachment2
+ mime_type: MyString
+ signed: true
+ class: ATTACHMENT
+ content: MyContent
+
ssd_without_recipient_name:
message_id: <%= SecureRandom.uuid %>
correlation_id: <%= SecureRandom.uuid %>
diff --git a/test/fixtures/message_objects.yml b/test/fixtures/message_objects.yml
index 4358c11f6..c6e355c1f 100644
--- a/test/fixtures/message_objects.yml
+++ b/test/fixtures/message_objects.yml
@@ -50,17 +50,27 @@ ssd_main_fs_one_form:
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
name: MyString
mimetype: MyString
object_type: FORM
ssd_main_draft_to_be_signed_draft_one_attachment:
+ uuid: af0e1c11-d226-45b7-8816-a5c24e139d35
message: ssd_main_draft_to_be_signed_draft_one
name: Attachment
mimetype: MyString
object_type: ATTACHMENT
+ssd_main_draft_to_be_signed_draft_one_attachment2:
+ uuid: 57c9954c-93e2-470c-833c-fd2bc6d8c70f
+ message: ssd_main_draft_to_be_signed_draft_one
+ name: Attachment2
+ mimetype: MyString
+ is_signed: true
+ object_type: ATTACHMENT
+
ssd_main_draft_to_be_signed_draft_two_form:
message: ssd_main_draft_to_be_signed_draft_two
name: MyString
diff --git a/test/fixtures/message_objects_tags.yml b/test/fixtures/message_objects_tags.yml
index 7def4cd62..c77cdc905 100644
--- a/test/fixtures/message_objects_tags.yml
+++ b/test/fixtures/message_objects_tags.yml
@@ -4,6 +4,10 @@ ssd_main_draft_to_be_signed_draft_one_form_signature_requested:
message_object: ssd_main_draft_to_be_signed_draft_one_form
tag: ssd_signer_user_signature_requested
+ssd_main_draft_to_be_signed_draft_one_attachment2_signed_ssd_signer:
+ message_object: ssd_main_draft_to_be_signed_draft_one_attachment2
+ tag: ssd_signer_user_signed
+
ssd_main_draft_to_be_signed_draft_two_form_signature_requested:
message_object: ssd_main_draft_to_be_signed_draft_two_form
tag: ssd_signer_user_signature_requested
diff --git a/test/fixtures/message_thread_merge_identifiers.yml b/test/fixtures/message_thread_merge_identifiers.yml
index 73d80505d..5951701c6 100644
--- a/test/fixtures/message_thread_merge_identifiers.yml
+++ b/test/fixtures/message_thread_merge_identifiers.yml
@@ -19,3 +19,8 @@ ssd_main_issue_one:
message_thread: ssd_main_issue
uuid: <%= SecureRandom.uuid %>
box: ssd_main
+
+ssd_main_draft_to_be_signed:
+ message_thread: ssd_main_draft_to_be_signed
+ uuid: 7a364355-882c-41d2-b1b3-e215644f805b
+ box: ssd_main
diff --git a/test/fixtures/message_threads_tags.yml b/test/fixtures/message_threads_tags.yml
index 2110dbcc1..28b65ed05 100644
--- a/test/fixtures/message_threads_tags.yml
+++ b/test/fixtures/message_threads_tags.yml
@@ -64,6 +64,18 @@ ssd_main_draft_to_be_signed_ssd_signer_user_signature_requested:
message_thread: ssd_main_draft_to_be_signed
tag: ssd_signer_user_signature_requested
+ssd_main_draft_to_be_signed_ssd_signer_user_signed:
+ message_thread: ssd_main_draft_to_be_signed
+ tag: ssd_signer_user_signed
+
+ssd_main_draft_to_be_signed_ssd_signed:
+ message_thread: ssd_main_draft_to_be_signed
+ tag: ssd_signed
+
+ssd_main_draft_to_be_signed_ssd_submitted:
+ message_thread: ssd_main_draft_to_be_signed
+ tag: ssd_submitted
+
ssd_main_draft_to_be_signed2_finance:
message_thread: ssd_main_draft_to_be_signed2
tag: ssd_finance
diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml
index 1c2dce92d..e189d0928 100644
--- a/test/fixtures/messages.yml
+++ b/test/fixtures/messages.yml
@@ -186,8 +186,8 @@ ssd_main_collapsed_two:
collapsed: true
ssd_main_draft_to_be_signed_draft_one:
- type: MessageDraft
- uuid: <%= SecureRandom.uuid %>
+ type: Upvs::MessageDraft
+ uuid: 9b1b718a-c06c-487c-86c2-b68b8606aa5c
title: Title is not shown
html_visualization: Reply to something
delivered_at: 2023-05-18 16:18:26
@@ -195,6 +195,7 @@ ssd_main_draft_to_be_signed_draft_one:
replyable: false
metadata:
status: created
+ correlation_id: 7a364355-882c-41d2-b1b3-e215644f805b
author: basic
ssd_main_draft_to_be_signed_draft_two:
@@ -203,7 +204,7 @@ ssd_main_draft_to_be_signed_draft_two:
title: MyStringDraft2
html_visualization: MyString
delivered_at: 2023-05-18 16:18:26
- thread: ssd_main_draft_to_be_signed
+ thread: ssd_main_draft_to_be_signed2
replyable: false
metadata:
status: created
diff --git a/test/models/govbox/message_test.rb b/test/models/govbox/message_test.rb
index 69a5eea08..b73a07764 100644
--- a/test/models/govbox/message_test.rb
+++ b/test/models/govbox/message_test.rb
@@ -1,7 +1,7 @@
require "test_helper"
class Govbox::MessageTest < ActiveSupport::TestCase
- test "should create message, its objects and not visible tag" do
+ test "#create_message_with_thread! should create message, its objects and not visible tag" do
govbox_message = govbox_messages(:one)
Govbox::Message.create_message_with_thread!(govbox_message)
@@ -29,7 +29,27 @@ class Govbox::MessageTest < ActiveSupport::TestCase
assert_equal message.tags.first, message.thread.tags.simple.first
end
- test "should take name from box as recipient_name if no recipient_name in govbox message" do
+ test "#create_message_with_thread! migrates tags from associated MessageDraft" do
+ govbox_message = govbox_messages(:ssd_general_created_from_draft)
+
+ Govbox::Message.create_message_with_thread!(govbox_message)
+
+ message = Message.last
+
+ # Simple and Signed tags copied to MessageThread
+ assert ['Finance', 'Podpísané', 'Podpísané: Signer user'].map { |tag_name| message.thread.tags.include?(tag_name) }
+
+ # No SignatureRequested, Submiited tags copied to MessageThread
+ assert message.thread.tags.where(type: ['SignatureRequestedTag', 'SignatureRequestedFromTag', 'Submitted']).none?
+
+ # Signed tags copied to MessageObjects
+ assert message.objects.find_by(name: 'Attachment2').tags.include?(tags(:ssd_signer_user_signed))
+
+ # No SignatureRequested tags copied to MessageObjects
+ assert message.form_object.tags.where(type: ['SignatureRequestedTag', 'SignatureRequestedFromTag']).none?
+ end
+
+ test "#create_message_with_thread! should take name from box as recipient_name if no recipient_name in govbox message" do
govbox_message = govbox_messages(:ssd_without_recipient_name)
Govbox::Message.create_message_with_thread!(govbox_message)
@@ -41,7 +61,7 @@ class Govbox::MessageTest < ActiveSupport::TestCase
assert_equal message.recipient_name, "SSD main"
end
- test "should include general agenda subject in message title" do
+ test "#create_message_with_thread! should include general agenda subject in message title" do
govbox_message = govbox_messages(:ssd_general_agenda)
Govbox::Message.create_message_with_thread!(govbox_message)
@@ -51,7 +71,7 @@ class Govbox::MessageTest < ActiveSupport::TestCase
assert_equal message.title, "Všeobecná Agenda - Rozhodnutie ..."
end
- test "should not create new tag if already exists" do
+ test "#create_message_with_thread! should not create new tag if already exists" do
govbox_message = govbox_messages(:one)
tag = SimpleTag.create!(external_name: "slovensko.sk:#{govbox_message.folder.name}", name: "slovensko.sk:#{govbox_message.folder.name}", tenant: govbox_message.folder.box.tenant, visible: false)
@@ -66,7 +86,7 @@ class Govbox::MessageTest < ActiveSupport::TestCase
assert_equal tag, message.thread.tags.simple.first
end
- test "should not duplicate message thread tags" do
+ test "#create_message_with_thread! should not duplicate message thread tags" do
govbox_message1 = govbox_messages(:one)
govbox_message2 = govbox_messages(:three)
@@ -88,7 +108,7 @@ class Govbox::MessageTest < ActiveSupport::TestCase
assert_equal tag, message2.thread.tags.simple.first
end
- test "should not use delivery notification title for message thread title" do
+ test "#create_message_with_thread! should not use delivery notification title for message thread title" do
govbox_message = govbox_messages(:solver_delivery_notification)
Govbox::Message.create_message_with_thread!(govbox_message)