Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into GO-75/jobs_priority
Browse files Browse the repository at this point in the history
# Conflicts:
#	test/fixtures/message_object_data.yml
#	test/fixtures/message_objects.yml
#	test/system/message_drafts_test.rb
  • Loading branch information
jsuchal committed Nov 16, 2024
2 parents 5f1bd0f + 1e746ee commit 97af0fd
Show file tree
Hide file tree
Showing 95 changed files with 4,973 additions and 201 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ SITE_ADMIN_EMAILS=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOD_JOB_EXECUTION_MODE=
GROVER_NO_SANDBOX=true # must be true for running chromium as root in Docker container
ADMIN_IDS=
LOG_LEVEL=
DB_HOST=
DB_PORT=
DB_USER=
DB_PASSWORD=
AUTO_SYNC_BOXES= # ON / OFF, default OFF
Expand All @@ -23,3 +25,4 @@ UPVS_SSO_SUBJECT=
UPVS_SSO_SP_CERTIFICATE=
UPVS_SSO_SP_PRIVATE_KEY=
UPVS_ENV=
PDF_DISPLAY_URL=
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ ZwIDAQAB
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=1
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=2
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=3
GROVER_NO_SANDBOX=true # must be true for running chromium as root in Docker container
PDF_DISPLAY_URL=
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
FROM ruby:3.3.0

# Install packages
RUN apt-get update && apt-get install -y build-essential nodejs libpq-dev npm fop=1:2.* libsaxon-java libsaxonb-java
RUN apt-get update && apt-get install -y build-essential nodejs libpq-dev npm fop=1:2.* libsaxon-java libsaxonb-java chromium \
&& apt-get -y install libx11-xcb1 libxcomposite1 libasound2 libatk1.0-0 libatk-bridge2.0-0 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6

# Setup FOP to use saxon xslt parser
RUN sed -i '/find_jars/i \
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ gem 'jwt'
gem 'stimulus-rails'
gem 'jsbundling-rails'
gem 'pdf-reader'
gem 'grover'

# Monitoring
gem 'rollbar'
Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ GEM
activesupport
tzinfo
coderay (1.1.3)
combine_pdf (1.0.26)
matrix
ruby-rc4 (>= 0.1.5)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
crack (1.0.0)
Expand Down Expand Up @@ -164,6 +167,9 @@ GEM
fugit (>= 1.1)
railties (>= 6.0.0)
thor (>= 0.14.1)
grover (1.1.11)
combine_pdf (~> 1.0)
nokogiri (~> 1.0)
hashdiff (1.1.0)
hashery (2.1.2)
hashie (5.0.0)
Expand Down Expand Up @@ -512,6 +518,7 @@ DEPENDENCIES
erb_lint
foreman
good_job
grover
htmlbeautifier
importmap-rails
jbuilder
Expand Down
28 changes: 18 additions & 10 deletions app/components/admin/tags/tag_form_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,36 @@
<div class="fixed inset-0 transition-opacity bg-gray-400 bg-opacity-75" aria-hidden="true"></div>
<div class="relative flex items-center justify-center h-full">
<div class="flex flex-col justify-start items-start overflow-hidden rounded-lg bg-white border border-gray-300" style="box-shadow: 1px 1px 4px 0 rgba(0,0,0,0.1);">
<div class="flex justify-start items-center self-stretch flex-grow-0 flex-shrink-0 overflow-hidden gap-4 p-6 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="flex justify-start items-center self-stretch flex-grow-0 flex-shrink-0 overflow-hidden gap-4 p-6 border-t-0 border-r-0 border-b-0 border-l-0 border-gray-200">
<div class="flex flex-col justify-start items-start flex-grow relative">
<p class="self-stretch flex-grow-0 flex-shrink-0 text-xl font-semibold text-left text-gray-900"><%= @tag.new_record? ? "Nový štítok" : "Úprava štítku" %></p>
<p class="flex-grow-0 flex-shrink-0 text-xs text-left text-gray-500">Názov štítku</p>
<h2 class="text-base font-semibold leading-7 text-gray-900"><%= @tag.new_record? ? "Nový štítok" : "Úprava štítku" %></h2>
</div>
<%= render Common::CloseButtonComponent.new(link_to: admin_tenant_tags_path(Current.tenant)) %>
</div>
<%= form_with model: @tag, url: (@tag.new_record? ? admin_tenant_tags_path(Current.tenant) : admin_tenant_tag_path(@tag.tenant, @tag)) do |form| %>
<div class="flex flex-col justify-start items-start self-stretch flex-grow-0 flex-shrink-0 w-400">
<div class="flex justify-start items-center self-stretch flex-grow-0 flex-shrink-0 gap-4 p-6 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="flex flex-col justify-start items-start py-3 self-stretch flex-grow-0 flex-shrink-0 w-400">
<div class="flex justify-start items-center self-stretch flex-grow-0 flex-shrink-0 gap-4 px-6 py-3 border-t-0 border-r-0 border-b-0 border-l-0 border-gray-200">
<div class="flex flex-col justify-start items-start self-stretch flex-grow overflow-hidden gap-2 rounded-md">
<%= form.text_field :name, placeholder: "Názov štítku", class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" %>
<%= form.label :name, "Názov štítku", class: "block text-sm font-medium leading-6 text-gray-900" %>
<div class="flex w-full rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600 sm:max-w-md">
<%= form.text_field :name, class: "block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6" %>
</div>
</div>
</div>
<div class="flex justify-start items-center self-stretch gap-4 p-6 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="flex justify-start items-center self-stretch gap-4 px-6 py-3 border-t-0 border-r-0 border-b-0 border-l-0 border-gray-200">
<div class="flex flex-col justify-start items-start self-stretch flex-grow overflow-hidden gap-2 rounded-md">
<%= form.select :color, helpers.color_select_options, {}, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" %>
<%= form.label :color, "Farba", class: "block text-sm font-medium leading-6 text-gray-900" %>
<div class="mt-2 w-full">
<%= form.select :color, helpers.color_select_options, {}, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6" %>
</div>
</div>
</div>
<div class="flex justify-start items-center self-stretch gap-4 p-6 border-t-0 border-r-0 border-b border-l-0 border-gray-200">
<div class="flex justify-start items-center self-stretch gap-4 px-6 py-3 border-t-0 border-r-0 border-b-0 border-l-0 border-gray-200">
<div class="flex flex-col justify-start items-start self-stretch flex-grow overflow-hidden gap-2 rounded-md">
<%= form.select :icon, helpers.icon_select_options, {}, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" %>
<%= form.label :icon, "Ikonka", class: "block text-sm font-medium leading-6 text-gray-900" %>
<div class="mt-2 w-full">
<%= form.select :icon, helpers.icon_select_options, {}, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6" %>
</div>
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions app/components/common/icon_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class IconComponent < ViewComponent::Base
"cloud-arrow-down" => "M12 9.75v6.75m0 0-3-3m3 3 3-3m-8.25 6a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.233-2.33 3 3 0 0 1 3.758 3.848A3.752 3.752 0 0 1 18 19.5H6.75Z",
"paper-airplane" => "M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5",
"document-arrow-down" => "M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m.75 12 3 3m0 0 3-3m-3 3v-6m-1.5-9H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z",
"document-text" => "M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z",
"folder-arrow-down" => "m9 13.5 3 3m0 0 3-3m-3 3v-6m1.06-4.19-2.12-2.12a1.5 1.5 0 0 0-1.061-.44H4.5A2.25 2.25 0 0 0 2.25 6v12a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18V9a2.25 2.25 0 0 0-2.25-2.25h-5.379a1.5 1.5 0 0 1-1.06-.44Z"
}.freeze

Expand Down
2 changes: 1 addition & 1 deletion app/components/message_draft_body_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@

<% if @message.html_visualization.present? %>
<div class="w-full">
<%= tag.iframe class: "relative border-none overflow-hidden h-full w-full", srcdoc: @message.format_html_visualization, onload: "(
<%= tag.iframe class: "relative border-none overflow-hidden h-full w-full", srcdoc: @message.html_visualization, onload: "(
function(iframe) {
iframe.contentWindow.document.body.style['height'] = 'unset';
iframe.contentWindow.document.body.style['min-height'] = 'unset';
Expand Down
10 changes: 8 additions & 2 deletions app/components/message_state_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<% if @message.form_object&.is_signed? || @message.form_object.present? || @message.authorized? %>
<div class="w-fit flex flex-col gap-1 <%= @classes %>">
<% if @message.form_object&.is_signed? %>
<div class="w-fit flex flex-row gap-1 <%= @classes %>">
<% 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 %>
Expand Down
4 changes: 2 additions & 2 deletions app/components/message_threads_table_row_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
<div class="flex flex-wrap gap-2 text-gray-500 text-xs md:text-base items-center">
<% if @message_thread.sender || @message_thread.recipient %>
<span class="text-left font-normal">
<% if @message_thread.is_outbox && @message_thread.recipient.present? %>
<% if MessageThreadHelper.show_recipient?(@message_thread) %>
Komu: <%= @message_thread.recipient %>
<% elsif !@message_thread.is_outbox && @message_thread.sender.present? %>
<% elsif MessageThreadHelper.show_sender?(@message_thread) %>
Od: <%= @message_thread.sender %>
<% end %>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ def before_render
@trigger_events_list = [
[t('message_created'), 'message_created'],
[t('message_draft_submitted'), 'message_draft_submitted'],
[t('message_object_downloaded'), 'message_object_downloaded'],
]
end
end
7 changes: 6 additions & 1 deletion app/controllers/api/messages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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])
Expand Down
1 change: 0 additions & 1 deletion app/controllers/message_drafts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/message_objects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def show

def download
authorize @message_object

EventBus.publish(:message_object_downloaded, @message_object)

send_data @message_object.content, filename: MessageObjectHelper.displayable_name(@message_object), type: @message_object.mimetype, disposition: :download
end

Expand All @@ -34,6 +37,8 @@ def download_pdf

pdf_content = @message_object.prepare_pdf_visualization
if pdf_content
EventBus.publish(:message_object_downloaded, @message_object)

send_data pdf_content, filename: MessageObjectHelper.pdf_name(@message_object), type: 'application/pdf', disposition: :download
else
redirect_back fallback_location: message_thread_path(@message_object.message.thread), alert: "Obsah nie je možné stiahnuť."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
6 changes: 3 additions & 3 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ def nice_datetime(datetime)
end
end

def nice_datetime_with_time(datetime)
if datetime.today?
def nice_datetime_with_time(datetime, full_date: false)
if datetime.today? && !full_date
l(datetime, format: '%H:%M')
elsif datetime.year == Date.current.year
elsif datetime.year == Date.current.year && !full_date
l(datetime, format: '%e. %b %H:%M')
else
l(datetime, format: '%e. %b %Y %H:%M')
Expand Down
23 changes: 23 additions & 0 deletions app/helpers/fs/message_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Fs::MessageHelper
def self.build_html_visualization(message)
return [ActionController::Base.new.render_to_string('fs/messages/_submission', layout: false, locals: { message: message }), build_html_visualization_from_form(message)].compact.join('<hr>') if message.outbox?

# TODO: Vieme aj lepsie identifikovat? Nejake dalsie typy v tejto kategorii neexistuju?
template = if message.title.in?(['Informácia o podaní', 'Informácia o odmietnutí podania'])
'fs/messages/_delivery_report'
else
'fs/messages/_generic_message'
end

ActionController::Base.new.render_to_string(template, layout: false, locals: { message: message })
end

def self.build_html_visualization_from_form(message)
raise 'Missing Fs::Form XSLT' unless message.form&.xslt_txt
return unless message.form_object&.unsigned_content

template = Nokogiri::XSLT(message.form.xslt_txt)

ActionController::Base.new.render_to_string('fs/messages/_style', layout: false, locals: { message: message }) + ActionController::Base.helpers.simple_format(template.transform(message.form_object.xml_unsigned_content).to_s)
end
end
6 changes: 0 additions & 6 deletions app/helpers/message_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,4 @@ module MessageHelper
def self.export_filename(message)
"#{message.delivered_at.to_date}-sprava-#{message.id}.zip"
end

def format_html_visualization
return ActionController::Base.helpers.simple_format(html_visualization) if is_a?(Fs::MessageDraft)

html_visualization
end
end
9 changes: 9 additions & 0 deletions app/helpers/message_thread_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module MessageThreadHelper
def self.show_recipient?(message_thread)
!message_thread.box.single_recipient? && message_thread.is_outbox && message_thread.recipient.present?
end

def self.show_sender?(message_thread)
message_thread.box.single_recipient? || (!message_thread.is_outbox && message_thread.sender.present?)
end
end
52 changes: 52 additions & 0 deletions app/javascript/controllers/dropzone_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
connect() {
const dropzone = document.getElementById('dropzone');
const fileInput = document.getElementById('content[]');
const fileList = document.getElementById('fileList');

dropzone.addEventListener('dragover', (e) => {
e.preventDefault();
dropzone.classList.add('border-blue-500', 'border-2');
});

dropzone.addEventListener('dragleave', () => {
dropzone.classList.remove('border-blue-500', 'border-2');
});

dropzone.addEventListener('drop', (e) => {
e.preventDefault();
dropzone.classList.remove('border-blue-500', 'border-2');

const files = e.dataTransfer.files;
this.handleFiles(files);
});

fileInput.addEventListener('change', (e) => {
const files = e.target.files;
this.handleFiles(files);
});
}

handleFiles(files) {
const fileInput = document.getElementById('content[]');
fileInput.files = files;

for (const file of files) {
const listItem = document.createElement('div');
listItem.textContent = `${file.name} (${this.formatBytes(file.size)})`;
fileList.appendChild(listItem);
}
}

formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';

const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));

return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
}
3 changes: 3 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ application.register("form", FormController)
import MessageDraftsController from "./message_drafts_controller"
application.register("message-drafts", MessageDraftsController)

import DropzoneController from "./dropzone_controller"
application.register("dropzone", DropzoneController)

import TriStateCheckboxController from "./tri_state_checkbox_controller"
application.register("tri-state-checkbox", TriStateCheckboxController)

Expand Down
18 changes: 18 additions & 0 deletions app/jobs/fs/download_received_message_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Fs
class DownloadReceivedMessageJob < ApplicationJob
def perform(fs_message_id, box:, fs_client: FsEnvironment.fs_client)
raise unless box.is_a?(Fs::Box)
return unless box.syncable?

return if box.messages.where("metadata ->> 'fs_message_id' = ?", fs_message_id).any?

ActiveRecord::Base.transaction do
fs_api = fs_client.api(api_connection: box.api_connection, box: box)

raw_message = fs_api.fetch_received_message(fs_message_id)

Fs::Message.create_inbox_message_with_thread!(raw_message, box: box)
end
end
end
end
Loading

0 comments on commit 97af0fd

Please sign in to comment.