diff --git a/app/components/common/removable_tag_component.html.erb b/app/components/common/removable_tag_component.html.erb new file mode 100644 index 000000000..8baf58ec7 --- /dev/null +++ b/app/components/common/removable_tag_component.html.erb @@ -0,0 +1,12 @@ +<% if @tag.visible %> +
+

<%= @tag.name %>

+ <% if @object_tag.deletable %> + <%= button_to url_for(@object_tag), method: :delete, form: { data: { turbo_confirm: "Naozaj odstrániť štítok #{@tag.name} zo správy?" } } do %> + + + + <% end %> + <% end %> +
+<% end %> diff --git a/app/components/common/removable_tag_component.rb b/app/components/common/removable_tag_component.rb new file mode 100644 index 000000000..03804dd9e --- /dev/null +++ b/app/components/common/removable_tag_component.rb @@ -0,0 +1,8 @@ +module Common + class RemovableTagComponent < ViewComponent::Base + def initialize(object_tag) + @object_tag = object_tag + @tag = @object_tag.tag + end + end +end diff --git a/app/components/common/tag_selector_component.rb b/app/components/common/tag_selector_component.rb index 56e9ff734..87ce3c457 100644 --- a/app/components/common/tag_selector_component.rb +++ b/app/components/common/tag_selector_component.rb @@ -1,8 +1,7 @@ module Common class TagSelectorComponent < ViewComponent::Base - def initialize(object, available_tags) + def initialize(object) @object = object - @available_tags = available_tags end end end diff --git a/app/components/common/tag_selector_popup_component.html.erb b/app/components/common/tag_selector_popup_component.html.erb index ebc32135d..beec6244d 100644 --- a/app/components/common/tag_selector_popup_component.html.erb +++ b/app/components/common/tag_selector_popup_component.html.erb @@ -22,13 +22,13 @@ <% @tags.each do |tag|%>
<% if @object.class.name == 'MessageThread' %> - <%= form_with model: [MessageThreadsTag.new(message_thread: @object, tag: tag)], class: "contents" do |form| %> + <%= form_with model: [MessageThreadsTag.new(message_thread: @object, tag: tag)], data: { turbo_frame: '_top' }, class: "contents" do |form| %> <%= form.hidden_field :message_thread_id %> <%= form.hidden_field :tag_id %> <%= form.submit "#{tag.name}" ,class:"text-sm text-left text-blue-600 hover:cursor-pointer" %> <% end %> <% else %> - <%= form_with model: [MessagesTag.new(message: @object, tag: tag)], class: "contents" do |form| %> + <%= form_with model: [MessagesTag.new(message: @object, tag: tag)], data: { turbo_frame: '_top' }, class: "contents" do |form| %> <%= form.hidden_field :message_id %> <%= form.hidden_field :tag_id %> <%= form.submit "#{tag.name}", class:"text-sm text-left text-blue-600 hover:cursor-pointer" %> diff --git a/app/components/message_component.html.erb b/app/components/message_component.html.erb index 0db409fd6..622d3d089 100644 --- a/app/components/message_component.html.erb +++ b/app/components/message_component.html.erb @@ -1,9 +1,9 @@
- <%= render MessageThreadHeaderComponent.new(@message.thread, @available_tags) %> + <%= render MessageThreadHeaderComponent.new(@message.thread, @thread_tags_with_deletable_flag) %>
- <% if @notice %> + <% @notice.each do |type, msg| %> <% end %>
@@ -19,19 +19,10 @@

<%= @message.recipient_name || 'Neznámy' %>

- <% @message.tags.each do |tag| %> - <% if tag.visible %> -
-

<%= tag.name %>

- <%= button_to messages_tag_path(MessagesTag.find_by(message_id: @message.id, tag_id: tag.id)), method: :delete, form: { data: { turbo_confirm: "Naozaj odstrániť štítok #{tag.name} zo správy?" } } do %> - - - - <% end %> -
- <% end %> + <% @message_tags_with_deletable_flag.each do |message_tag| %> + <%= render Common::RemovableTagComponent.new(message_tag) %> <% end %> - <%= render Common::TagSelectorComponent.new(@message, @available_tags) %> + <%= render Common::TagSelectorComponent.new(@message) %>
diff --git a/app/components/message_component.rb b/app/components/message_component.rb index ac35364c2..d3379bdc5 100644 --- a/app/components/message_component.rb +++ b/app/components/message_component.rb @@ -1,9 +1,10 @@ class MessageComponent < ViewComponent::Base renders_many :attachments - def initialize(message:, notice:, available_tags:) + def initialize(message:, notice:, message_tags_with_deletable_flag:, thread_tags_with_deletable_flag:) @message = message @notice = notice - @available_tags = available_tags + @message_tags_with_deletable_flag = message_tags_with_deletable_flag + @thread_tags_with_deletable_flag = thread_tags_with_deletable_flag end end diff --git a/app/components/message_thread_header_component.html.erb b/app/components/message_thread_header_component.html.erb index 9b81614a2..a62a78fe2 100644 --- a/app/components/message_thread_header_component.html.erb +++ b/app/components/message_thread_header_component.html.erb @@ -2,19 +2,10 @@
<%= render MessageThreadRenameComponent.new(message_thread: @message_thread) %>
- <% @message_thread.tags.each do |tag|%> - <% if tag.visible %> -
-

<%= tag.name %>

- <%= button_to message_threads_tag_path(@message_thread.message_threads_tags.find_by(tag_id: tag.id)), method: :delete, form: { data: { turbo_confirm: "Naozaj odstrániť štítok #{tag.name} z vlákna?" } } do %> - - - - <% end %> -
- <% end %> + <% @thread_tags_with_deletable_flag.each do |thread_tag|%> + <%= render Common::RemovableTagComponent.new(thread_tag) %> <% end %> - <%= render Common::TagSelectorComponent.new(@message_thread, @available_tags) %> + <%= render Common::TagSelectorComponent.new(@message_thread) %>
diff --git a/app/components/message_thread_header_component.rb b/app/components/message_thread_header_component.rb index e5190d872..413b03d10 100644 --- a/app/components/message_thread_header_component.rb +++ b/app/components/message_thread_header_component.rb @@ -1,6 +1,6 @@ class MessageThreadHeaderComponent < ViewComponent::Base - def initialize(message_thread, available_tags) + def initialize(message_thread, thread_tags_with_deletable_flag) @message_thread = message_thread - @available_tags = available_tags + @thread_tags_with_deletable_flag = thread_tags_with_deletable_flag end end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 6aa6a1d87..e66d6092c 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -20,6 +20,37 @@ def authorize_delivery_notification def set_message @message = policy_scope(Message).find(params[:id]) @menu = SidebarMenu.new(controller_name, action_name, { message: @message }) + @notice = flash + set_message_tags_with_deletable_flag + set_thread_tags_with_deletable_flag + end + + def set_message_tags_with_deletable_flag + @message_tags_with_deletable_flag = + @message + .messages_tags + .includes(:tag) + .select("messages_tags.*, #{deletable_subquery('tags.id = messages_tags.tag_id').to_sql} as deletable") + .order("tags.name") + end + + def set_thread_tags_with_deletable_flag + @thread_tags_with_deletable_flag = + @message + .thread + .message_threads_tags + .includes(:tag) + .select("message_threads_tags.*, #{deletable_subquery('tags.id = message_threads_tags.tag_id').to_sql} as deletable") + .order('tags.name') + end + + def deletable_subquery(where_clause) + Tag + .joins(:groups, { groups: :group_memberships }) + .where('group_memberships.user_id = ?', Current.user.id) + .where(where_clause) + .arel + .exists end def permit_reply_params diff --git a/app/controllers/messages_tags_controller.rb b/app/controllers/messages_tags_controller.rb index d44c74885..24cc0d175 100644 --- a/app/controllers/messages_tags_controller.rb +++ b/app/controllers/messages_tags_controller.rb @@ -1,12 +1,12 @@ class MessagesTagsController < ApplicationController - before_action :set_messages_tag, only: %i[ destroy ] + before_action :set_messages_tag, only: %i[destroy] def create @messages_tag = MessagesTag.new(messages_tag_params) authorize @messages_tag if @messages_tag.save - redirect_back fallback_location:"/", notice: "Tag was successfully added" + redirect_back fallback_location: "/", notice: "Tag was successfully added" else render :new, status: :unprocessable_entity end @@ -15,7 +15,7 @@ def create def destroy authorize @messages_tag @messages_tag.destroy - redirect_back fallback_location:"/", notice: "Tag was successfully removed" + redirect_back fallback_location: '/', notice: 'Tag was successfully removed' end private diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 2634c1208..55d4f9777 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -10,10 +10,7 @@ def get_available authorize [Tag] set_object @tenant = Current.tenant - @tags = - @tenant.tags.where.not(id: @object.tags.ids).where(visible: true) - .where(id: TagGroup.select(:tag_id).joins(:group, :tag, group: :users).where(group: { tenant_id: @tenant.id }, tag: { tenant_id: @tenant.id }, users: { id: Current.user.id })) - respond_to { |format| format.html } + @tags = @tenant.tags.where.not(id: @object.tags.ids).where(visible: true) end private diff --git a/app/models/govbox/message.rb b/app/models/govbox/message.rb index 266a63fac..469354036 100644 --- a/app/models/govbox/message.rb +++ b/app/models/govbox/message.rb @@ -48,9 +48,10 @@ def self.create_message_with_thread!(govbox_message) delivered_at: govbox_message.delivered_at ) - self.create_message_tag(message, govbox_message) - message.save! + + self.create_message_tag(message, govbox_message) + message end diff --git a/app/models/message.rb b/app/models/message.rb index 5ef35a2ae..6cb219533 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -20,6 +20,7 @@ class Message < ApplicationRecord has_and_belongs_to_many :tags + has_many :messages_tags, dependent: :destroy belongs_to :thread, class_name: 'MessageThread', foreign_key: :message_thread_id belongs_to :author, class_name: 'User', foreign_key: :author_id, optional: true has_many :objects, class_name: 'MessageObject', dependent: :destroy diff --git a/app/policies/messages_tag_policy.rb b/app/policies/messages_tag_policy.rb index 67ab0ff9f..0f4436d11 100644 --- a/app/policies/messages_tag_policy.rb +++ b/app/policies/messages_tag_policy.rb @@ -13,38 +13,24 @@ def resolve if @user.site_admin? scope.all else - # TODO: toto zrejme nestaci, potrebujeme obmedzit aj na konkretneho usera a jeho boxy - scope.includes(:message, :tag).where(message: {tenant_id: Current.tenant.id}, tag: {tenant_id: Current.tenant.id}) + scope.joins(:message, :tag).where(message: Pundit.policy_scope(user, Message), tag: Pundit.policy_scope(user, Tag)) end end end - def index - true - end - - def show? - true - end - def create? - true - end - - def new? - create? - end + return false unless Pundit.policy_scope(user, Message).find_by(id: @messages_tag.message_id) + return false unless @messages_tag.tag.tenant == Current.tenant - def update? true end - def edit? - update? - end - def destroy? + return false unless @messages_tag + return false unless Pundit.policy_scope(user, Message).find_by(id: @messages_tag.message_id) + return false unless Pundit.policy_scope(user, Tag).find_by(id: @messages_tag.tag_id) + return false unless @messages_tag.tag.tenant == Current.tenant + true end end - diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb index 851ce633d..50fc8f4bf 100644 --- a/app/views/messages/show.html.erb +++ b/app/views/messages/show.html.erb @@ -1,5 +1,5 @@ <%= render TW::FlashComponent.new(flash: flash) %> -<%= render MessageComponent.new(message: @message, notice: @notice, available_tags: @available_tags) do |component| %> +<%= render MessageComponent.new(message: @message, notice: @notice, message_tags_with_deletable_flag: @message_tags_with_deletable_flag, thread_tags_with_deletable_flag: @thread_tags_with_deletable_flag) do |component| %> <% @message.objects.each do |message_object| %> <% component.with_attachment do %> <% render MessageAttachmentComponent.new(message_attachment: message_object) %>