From cc57a8c354dd0e344fd71378473cfa5ac24256ea Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 5 Mar 2024 11:12:23 +0100 Subject: [PATCH 01/40] Do not validate nested message objects mime_type (allow any mimetype inside asice) --- app/models/nested_message_object.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/nested_message_object.rb b/app/models/nested_message_object.rb index e2deb4a4c..007e6fbfc 100644 --- a/app/models/nested_message_object.rb +++ b/app/models/nested_message_object.rb @@ -14,7 +14,6 @@ class NestedMessageObject < ApplicationRecord belongs_to :message_object, inverse_of: :nested_message_objects validates :name, presence: true, on: :validate_data - validate :allowed_mime_type?, on: :validate_data def self.create_from_message_object(message_object) return unless message_object.asice? From b88b6e0ceef19cf576c24f64832302dfd001337e Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 5 Mar 2024 11:13:03 +0100 Subject: [PATCH 02/40] Add Upvs::Form, Upvs::ServiceWithForm for SZCO registration --- db/seeds.rb | 3423 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3423 insertions(+) diff --git a/db/seeds.rb b/db/seeds.rb index 53cfccfba..5c8c7a14b 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -94,6 +94,12 @@ name: "Exekučné konanie - Návrh na vykonanie exekúcie", schema_url: 'http://schemas.gov.sk/form/00166073.RESS_Exekucne_konanie_Navrh_na_vykonanie_exekucie.sk/1.24' ) +Upvs::ServiceWithForm.find_or_create_by!( + institution_uri: 'ico://sk/83369722', + institution_name: 'Test OVM 83369722 - firmaren', + name: "Ohlasovanie voľnej, remeselnej a viazanej živnosti - fyzická osoba", + schema_url: 'http://schemas.gov.sk/form/JKM_ZROHLAS_FO/1.5' +) Upvs::MessageTemplate.find_or_create_by!( name: 'Všeobecná agenda', @@ -36698,3 +36704,3420 @@ document_type: related_document[:document_type] ) end + +szco_registration_form = Upvs::Form.find_or_create_by!( + identifier: "JKM_ZROHLAS_FO", + version: "1.5", + message_type: "sluzba_egov_1097" +) +szco_registration_form_related_docs = [ + { + language: "sk", + document_type: "CLS_F_XSD_EDOC", + data: <<~XSD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XSD + }, + { + language: "sk", + document_type: "CLS_F_XSLT_TXT_SGN", + data: <<~XSLT + + + + + + Ohlásenie/žiadosť o vydanie osvedčenia o živnostenskom oprávnení - formulár pre fyzickú osobu / Notification/request for issuing of Trade authorisation - form for natural person + + + + + Žiadateľ / Applicant + + + + + + + + + + + + + + + + Obchodné meno / Business name: + + + + + + + + + IČO / Company identification number: : + + + + + + + + + Telefón / Telephone: + + + + + + + + + E-mail / E-mail: + + + + + + Podnikateľ / Entrepreneur + + + + + + + + + + + + + + Bydlisko podnikateľa / Residential address of businessman + + + + Miesto podnikania / Place of business + + + + + + + Obchodné meno / Business name: + + + + + + + + IČO / Company identification number: : + + + + + + + + Poisťovňa, v ktorej je fyzická osoba prihlásená na povinné zdravotné poistenie / where a natural person is registered in the system of mandatory health insurance: + + + + + + + + + Telefón / Telephone: + + + + + + + + + Fax / Fax: + + + + + + + + + E-mail / E-mail: + + + + + + + Adresa pre doručovanie písomností / Adress for deliveries of documents + + + + + Štát / State: + + + + + + + Štát / State: + + + + + + + Okres / County: + + + + + + + Okres / County: + + + + + + + Obec / City: + + + + + + + Obec / City: + + + + + + + Ulica / Street: + + + + + + + Súpisné číslo / Number: + + + + + + + Orientačné číslo / Number: + + + + + + + PSČ / Postcode: + + + + + + + Telefón / Telephone: + + + + + + + Fax / Fax: + + + + + + + E-mail / E-mail: + + + + + + Splnomocnenec FO / Authorised representative - natural person + + + + + + Splnomocnenec PO / Authorised representative - legal person + + + + + + + + + + + + IČO / Company identification number: : + + + + + + + + + Obchodné meno / Business name: + + + + + + Zahraničná osoba / Foreign person + + + + + + + + + + + + + + + Podnik zahraničnej osoby / business of the foreign person: + + + + + + + + + + + Organizačná zložka podniku zahraničnej osoby / organisational unit of the foreign person: + + + + + + + + + + + Označenie / Name: + + + + + + + Adresa pobytu na území Slovenskej republiky / Residential address within the territory of the Slovak Republic + + + + + Štát / State: + + + + + + + Štát / State: + + + + + + + Okres / County: + + + + + + + Okres / County: + + + + + + + Obec / City: + + + + + + + Obec / City: + + + + + + + Ulica / Street: + + + + + + + Súpisné číslo / Number: + + + + + + + Orientačné číslo / Number: + + + + + + + PSČ / Postcode: + + + + + + + Telefón / Telephone: + + + + + + + Fax / Fax: + + + + + + + E-mail / E-mail: + + + + + + + Adresa miesta činnosti podniku zahraničnej osoby alebo miesta činnosti organizačnej zložky podniku zahraničnej osoby na území Slovenskej republiky (povinný údaj) / Address of place of business of the foreign person or address of place of business of the organisational unit of the foreign person within the territory of the Slovak Republic (obligatory data) + + + + + Štát / State: + + + + + + + Štát / State: + + + + + + + Okres / County: + + + + + + + Okres / County: + + + + + + + Obec / City: + + + + + + + Obec / City: + + + + + + + Ulica / Street: + + + + + + + Súpisné číslo / Number: + + + + + + + Orientačné číslo / Number: + + + + + + + PSČ / Postcode: + + + + + + + Telefón / Telephone: + + + + + + + Fax / Fax: + + + + + + + E-mail / E-mail: + + + + + + + Údaje o vedúcom podniku zahraničnej osoby/organizačnej zložky podniku zahraničnej osoby v SR / Data about a manager of the foreign person/the organisational unit of the foreign person in the Slovak Republic + + + + + + + + Ostatné údaje / Other data + + + + + + + Odbornú spôsobilosť preukazujem nasledovnými dokladmi / I prove professional qualification by following documents: + + + + + + + + Oprávnenie užívať nehnuteľnosť (miesto podnikania, miesto činnosti podniku zahraničnej osoby, alebo miesto činnosti organizačnej zložky podniku zahraničnej osoby) preukazujem / I prove my beneficial ownership of the estate (place of business, place of business of the foreign person or place of business of the organisational unit of the foreign person) by: + + + + + + + + Predkladám návrh na prvý zápis do obchodného registra prostredníctvom JKM / I file the first petition for entry into the Company Register via Point of Single Contact: + + + + + + + + + + LegalFormCodeJKM: + + + + + + Remeselné a viazané živnosti / Crafts and regulated trades + + + + + + + + + + + + Predmet podnikania / Line of business: + + + + + + Predmet podnikania / Line of business: + + + + + + + + Rozsah poskytovanej služby podľa dokladu o odbornej kvalifikácií / The scope of service provided according to certificate of professional qualification: + + + + + + + + Deň začatia živnosti / Day of commencement of the trade: + + + + + + + + + + Deň ukončenia podnikania / Day of termination of the trade: + + + + + + + + + Zodpovedný zástupca / Authorised representative + + + + + + Prevádzkareň / Establishment + + + + + + + + + Typ prevádzkarne / Type establishment: + + + + + + Voľné živnosti / Unregulated trade + + + + + + + + + + Predmet podnikania / Line of business: + + + + + + Predmet podnikania / Line of business: + + + + + + + + Deň začatia živnosti / Day of commencement of the trade: + + + + + + + + + + Deň ukončenia podnikania / Day of termination of the trade: + + + + + + + + + Prevádzkareň / Establishment + + + + + + + + + Typ prevádzkarne / Type establishment: + + + + + + Prihláška na verejné povinné zdravotné poistenie / Application for public mandatory health insurance + + + + + + + + + + + + Obchodné meno zdravotnej poisťovne, do ktorej sa prihláška podáva / The business name of the health insurance company, to which application is submitted: + + + + + + + + Dátum podania prihlášky / Date of submission of application: + + + + + + + + + + Čas podania prihlášky / Time of submission of application: + + + + + + + + Číslo identifikačnej karty, alebo číslo pasu cudzinca / Number of identification card or number of passport of the foreign person: + + + + + + + + S trvalým pobytom na území Slovenskej republiky / with residential address within the territory of the Slovak Republic: + + + + + + + + + + Bez trvalého pobytu na území Slovenskej republiky, vykonávajúca na území Slovenskej republiky samostatnú zárobkovú činnosť / without residential address within the territory of the Slovak Republic acting as self-employed within the territory of the Slovak Republic: + + + + + + + + Tuzemský účet / Domestic account + + + + + + + IBAN: + + + + + + Zahraničný účet / External account + + + + + + + IBAN: + + + + + + Iná organizačná jednotka ako prevádzkareň / Organizational unit different from establishment + + + + + + + + + Označenie / Type: + + + + + + Predložené doklady / Submitted documents + + + + + + + Doklad preukazujúci odbornú spôsobilosť / Document proving professional qualification: + + + + + + + + + + Oprávnenie užívať nehnuteľnosť / Document proving the beneficial ownership of the real estate: + + + + + + + + + + Výpis z registra trestov osôb, ktoré nie sú štátnymi občanmi Slovenskej republiky / Extract from the criminal records of persons who are not citizens of the Slovak Republic: + + + + + + + + + + Súhlas zodpovedného zástupcu / Consent of an authorised representative: + + + + + + + + + + Splnomocnenie na zastupovanie / Authorised letter for representation of the natural person: + + + + + + + + + Vyhlasujem, že všetky údaje uvedené v tomto ohlásení a všetky prílohy priložené k ohláseniu živnosti sú pravdivé, že žiadny osobitný zákon mi neobmedzuje alebo nevylučuje prevádzkovať živnosť, a že na môj majetok nebol zrušený konkurz a ani nebol návrh na konkurz zamietnutý pre nedostatok majetku, že mi súdom ani správnym orgánom nebol uložený zákaz činnosti týkajúci sa vykonávania živnosti / I declare that all information provided in this declaration and all annexes attached to the trade declaration are true, that no special law restricts or excludes me from carrying on trade and that my assets are not subject to cancelled bankruptcy proceedings and no bankruptcy petition filed against me has been rejected due to lack of assets, and that I have not been prohibited by a court or an administrative authority to pursue a trade: + + + + + + + + Ostatné / Others + + + + + + + Dňa / Date: + + + + + + + + + + + Titul pred / Title (in front of name): + + + + + + + Titul pred / Title (in front of name): + + + + + + + Meno / Name: + + + + + + + Priezvisko / Surname: + + + + + + + Rodné priezvisko / Maiden surname: + + + + + + + Titul za / Title (after name): + + + + + + + Titul za / Title (after name): + + + + + + + Rodné číslo / Birth identification number: + + + + + + + Dátum narodenia / Date of birth: + + + + + + + + + Štátna príslušnosť / Nationality: + + + + + + + Pobyt na území SR do / Residential status in SK until: + + + + + + + + + Iný identifikačný údaj, ak rodné číslo v SR nie je pridelené / Other identification data, if the birth number in the Slovak Republic is not assigned : + + : + + + + + + + + + Štát / State: + + + + + + + Štát / State: + + + + + + + Okres / County: + + + + + + + Okres / County: + + + + + + + Obec / City: + + + + + + + Obec / City: + + + + + + + Ulica / Street: + + + + + + + Súpisné číslo / Number: + + + + + + + Orientačné číslo / Number: + + + + + + + PSČ / Postcode: + + + + + + + Telefón / Telephone: + + + + + + + Fax / Fax: + + + + + + + E-mail / E-mail: + + + + + + + + + Register (iná evidencia) v ktorom je zahraničná právnická osoba zapísaná / Register (other record) in which the foreign legal person is registered : + + + + + + + + + Číslo zápisu / Registration number : + + + + + + + + + Deň vzniku funkcie / Day of appointment: + + + + + + + + + + + Deň zániku funkcie a jeho oprávnenia / The date of termination of function and its authorization: + + + + + + + + + + + + + + + + + + + + + + + Áno + + + Nie + + + Áno + + + Nie + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XSLT + }, + { + language: "sk", + document_type: "CLS_F_XSLT_HTML", + data: <<~XSLT + + + + + + + + JKM - OHLASENIE FO + + + + + +
+ +
+ + +
+ +
+
+
Ohlásenie/žiadosť o vydanie osvedčenia o živnostenskom oprávnení - formulár pre fyzickú osobu / Notification/request for issuing of Trade authorisation - form for natural person
+
+ + + + + + + + + + + + + + + +
+
+ +
+ +
+
Tuzemský účet / Domestic account
+
+
+ +
+
+ +
+ +
+
Zahraničný účet / External account
+
+
+ +
+
+ +
+
+
Splnomocnenec FO / Authorised representative - natural person
+
+ + +
+
+ +
+
+
Splnomocnenec PO / Authorised representative - legal person
+
+ + +
+
+ +
+ +
+ + + + +
+
 
+
+ +
+
+ +
+
+
Iná organizačná jednotka ako prevádzkareň / Organizational unit different from establishment
+
+ + +
+
+ +
+
+
Žiadateľ / Applicant
+
+ + + +
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+
+
+
+ +
+ + +
+ + + + +
+
 
+
+
+
+ +
+
+
Ostatné údaje / Other data
+
+ + + + +
+
+ +
+
+
Voľné živnosti / Unregulated trade
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ + + +
+
+ +
+
+
Prevádzkareň / Establishment
+
+ + +
+
+ +
+
+
Predložené doklady / Submitted documents
+
+ + + + + +
+
+ +
+
+
Zahraničná osoba / Foreign person
+
+ + + + + + + + +
+
+ +
+
+
Údaje o vedúcom podniku zahraničnej osoby/organizačnej zložky podniku zahraničnej osoby v SR / Data about a manager of the foreign person/the organisational unit of the foreign person in the Slovak Republic
+
+ + + + +
+
+ +
+
+
Prihláška na verejné povinné zdravotné poistenie / Application for public mandatory health insurance
+
+ + + + + + +
+
+ +
+
+
Remeselné a viazané živnosti / Crafts and regulated trades
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ + + + + + +
+
+ +
+
+
Zodpovedný zástupca / Authorised representative
+
+ +
+
+ +
+
+
Prevádzkareň / Establishment
+
+ + +
+
+ +
+
+
Ostatné / Others
+
+ +
+
+ +
+
+
Podnikateľ / Entrepreneur
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+
+
Miesto podnikania / Place of business
+
+ +
+ + +
+ + + + +
+
 
+
+
+
+ + +
+
+
Bydlisko podnikateľa / Residential address of businessman
+
+ +
+
+ + +
+ + + + + + +
+
 
+
+
+ +
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+
+
+ +
+
+
Adresa pre doručovanie písomností / Adress for deliveries of documents
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+
+
+ +
+
+
Adresa pobytu na území Slovenskej republiky / Residential address within the territory of the Slovak Republic
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+
+
+ +
+
+
Adresa miesta činnosti podniku zahraničnej osoby alebo miesta činnosti organizačnej zložky podniku zahraničnej osoby na území Slovenskej republiky (povinný údaj) / Address of place of business of the foreign person or address of place of business of the organisational unit of the foreign person within the territory of the Slovak Republic (obligatory data)
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+
+
+ +
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + + + +
+
 
+
+ +
+ + + + +
+
 
+
+ +
+ + + + + + +
+
 
+
+ +
+ + + + : + + +
+
 
+
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + +
+ + + + + + +
+
 
+
+
+ + + + + + + + + + + + + + + + + + Áno + + + Nie + + + Áno + + + Nie + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ XSLT + } +] +szco_registration_form_related_docs.each do |related_document| + Upvs::FormRelatedDocument.find_or_create_by!( + form: szco_registration_form, + data: related_document[:data], + language: related_document[:language], + document_type: related_document[:document_type] + ) +end From 3407927274d762c20635b0e490e8839dc739b472 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 5 Mar 2024 12:32:16 +0100 Subject: [PATCH 03/40] Add API to create UPVS messages --- .../api/upvs/messages_controller.rb | 94 +++++++++++++++++++ app/controllers/api_controller.rb | 4 +- app/controllers/message_drafts_controller.rb | 1 + config/routes.rb | 4 + 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 app/controllers/api/upvs/messages_controller.rb diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb new file mode 100644 index 000000000..517295f38 --- /dev/null +++ b/app/controllers/api/upvs/messages_controller.rb @@ -0,0 +1,94 @@ +class Api::Upvs::MessagesController < ApiController + before_action :set_box + + def create + @message = MessageDraft.create(message_params) + @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( + box: @box, + merge_uuid: @message.metadata['correlation_id'], + title: @message.title, + delivered_at: @message.delivered_at + ) + @message.save + + permitted_params[:objects].each do |object_params| + message_object = @message.objects.create(object_params.except(:content)) + + MessageObjectDatum.create( + message_object: message_object, + blob: Base64.decode64(object_params[:content]) + ) + end + + if @message.valid?(:validate_data) + @message.metadata['status'] = 'created' + @message.save + + head :created + else + @message.metadata['status'] = 'invalid' + @message.save + + render_unprocessable_entity(@message.errors.messages.values.join(', ')) + end + end + + private + + def set_box + @box = Box.find_by(uri: permitted_params[:sender_uri]) + end + + def message_params + permitted_message_params = permitted_params + { + delivered_at: Time.now, + outbox: true, + # recipient_name: TODO search name in UPVS dataset, + replyable: false, + sender_name: @box.name, + title: permitted_message_params['title'], + uuid: permitted_message_params['message_id'], + metadata: { + correlation_id: permitted_message_params['correlation_id'], + reference_id: permitted_message_params['reference_id'], + sender_uri: permitted_message_params['sender_uri'], + recipient_uri: permitted_message_params['recipient_uri'], + sender_business_reference: permitted_message_params['sender_business_reference'], + recipient_business_reference: permitted_message_params['recipient_business_reference'], + posp_id: permitted_message_params['posp_id'], + posp_version: permitted_message_params['posp_version'], + message_type: permitted_message_params['message_type'], + status: 'being_loaded' + } + } + end + + def permitted_params + params.permit( + :message_id, + :correlation_id, + :reference_id, + :sender_uri, + :recipient_uri, + :sender_business_reference, + :recipient_business_reference, + :posp_id, + :posp_version, + :message_type, + :title, + objects: [ + :name, + :is_signed, + :to_be_signed, + :mimetype, + :object_type, + :content, + ] + ) + end + + def authenticate_user + @tenant = ApiEnvironment.tenant_token_authenticator.verify_token(authenticity_token) + end +end diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index bd3062204..84cf02ccc 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -89,7 +89,7 @@ def render_service_unavailable_error render status: :service_unavailable, json: { message: "Service unavailable" } end - def render_unprocessable_entity(exception) - render status: :unprocessable_entity, json: { message: exception.message } + def render_unprocessable_entity(message) + render status: :unprocessable_entity, json: { message: message } end end diff --git a/app/controllers/message_drafts_controller.rb b/app/controllers/message_drafts_controller.rb index e273718b0..fd8907a64 100644 --- a/app/controllers/message_drafts_controller.rb +++ b/app/controllers/message_drafts_controller.rb @@ -78,6 +78,7 @@ def submit redirect_to message_thread_path(@message.thread), notice: "Správa bola zaradená na odoslanie" else # TODO: prisposobit chybovu hlasku aj importovanym draftom + # 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: "Vyplňte obsah správy" end end diff --git a/config/routes.rb b/config/routes.rb index 0ab4b1d67..96ec99971 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -201,6 +201,10 @@ end end + namespace :upvs do + resources :messages, only: [:create] + end + resources :message_threads, only: [:show] resources :messages, only: [:show] end From 32327f902eae5ef8138a129339fa2eca6046b53b Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 5 Mar 2024 13:08:48 +0100 Subject: [PATCH 04/40] Update API specification --- public/openapi.yaml | 135 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/public/openapi.yaml b/public/openapi.yaml index b91f5315f..f15c2e52d 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -132,6 +132,141 @@ paths: security: - "Tenant_Token": [] + /api/upvs/messages: + post: + tags: [ Správy ] + summary: Vytvorí novú správu vrátane jej objektov + description: | + Vytvorí novú správu vrátane jej objektov. + requestBody: + content: + application/json: + schema: + type: object + properties: + message_id: + description: Identifikátor správy + type: string + format: uuid + correlation_id: + description: Identifikátor vlákna správ + type: string + format: uuid + reference_id: + description: Identifikátor správy, na ktorú sa správa (odpoveď) viaže + type: string + format: uuid + recipient_uri: + description: Identifikátor prijímateľa správy + type: string + format: uri + example: ico://sk/83369510 + sender_uri: + description: Identifikátor odosielateľa správy + type: string + format: uri + example: ico://sk/83369526 + posp_id: + description: Identifikátor formulára + type: string + example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk + posp_version: + description: Verzia formulára + type: string + example: "1.11" + message_type: + description: Typ správy + type: string + example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk + sender_business_reference: + description: Spisová značka odosielateľa elektronickej správy + type: string + example: "1234567" + recipient_business_reference: + description: Spisová značka prijímateľa elektronickej správy + type: string + example: EX1234/2000 + title: + description: Predmet správy + type: string + example: Žaloba + objects: + description: Objekty správy + type: array + items: + type: object + properties: + name: + description: Názov objektu + type: string + nullable: true + is_signed: + description: Indikátor či je obsah objektu podpísaný + type: boolean + to_be_signed: + description: Indikátor či obsah objektu má byť podpísaný + type: boolean + mimetype: + description: Typ internetového média v súlade s typom a obsahom objektu + type: string + enum: + - application/x-eform-xml + - application/xml + - application/msword + - application/pdf + - application/vnd.etsi.asic-e+zip + - application/vnd.etsi.asic-s+zip + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/x-xades_zep + - application/x-zip-compressed + - image/jpg + - image/jpeg + - image/png + - image/tiff + object_type: + description: Typ objektu + type: string + format: + enum: [ FORM, ATTACHMENT ] + content: + description: Obsah objektu zakódovaný podľa Base64 + type: string + required: + - mimetype + - is_signed + - object_type + - content + example: + - name: form.asice + description: Formulár + is_signed: true + mimetype: application/vnd.etsi.asic-e+zip + object_type: FORM + content: base64 asice content + - name: priloha1.asice + description: Príloha 1 + is_signed: true + mimetype: application/vnd.etsi.asic-e+zip + form: false + content: base64 asice content + required: + - message_id + - correlation_id + - recipient_uri + - sender_uri + - posp_id + - posp_version + - message_type + - title + - objects + responses: + 201: + description: Úspešné vytvorenie správy + 422: + description: Nevalidný obsah správy + security: + - "Tenant_Token": [ ] + /api/site_admin/tenant/: post: tags: [Správa tenantov (Administrácia)] From 44ecf205f3dad127a264f310903bb1b03753d0c2 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Fri, 8 Mar 2024 12:35:45 +0100 Subject: [PATCH 05/40] Upgrade MessageDrafts validations & Add test for UPVS drafts API --- .../api/upvs/messages_controller.rb | 9 +- app/controllers/api_controller.rb | 4 + app/lib/utils.rb | 1 + app/models/message.rb | 2 +- app/models/message_draft.rb | 44 +- app/models/message_object.rb | 8 +- app/models/upvs/message_template.rb | 4 +- config/locales/en.yml | 7 + config/locales/sk.yml | 2 + public/openapi.yaml | 1 + test/fixtures/messages.yml | 2 + test/integration/upvs_messages_api_test.rb | 731 ++++++++++++++++++ 12 files changed, 797 insertions(+), 18 deletions(-) create mode 100644 test/integration/upvs_messages_api_test.rb diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index 517295f38..46f1fea0f 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -1,7 +1,10 @@ class Api::Upvs::MessagesController < ApiController before_action :set_box + before_action :set_en_locale def create + render_unprocessable_entity('Invalid Sender Uri') and return unless @box + @message = MessageDraft.create(message_params) @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( box: @box, @@ -9,6 +12,8 @@ def create title: @message.title, delivered_at: @message.delivered_at ) + + render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? @message.save permitted_params[:objects].each do |object_params| @@ -22,15 +27,15 @@ def create if @message.valid?(:validate_data) @message.metadata['status'] = 'created' - @message.save head :created else @message.metadata['status'] = 'invalid' - @message.save render_unprocessable_entity(@message.errors.messages.values.join(', ')) end + + @message.save end private diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 84cf02ccc..955cc5fd6 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -92,4 +92,8 @@ def render_service_unavailable_error def render_unprocessable_entity(message) render status: :unprocessable_entity, json: { message: message } end + + def set_en_locale + I18n.locale = :en + end end diff --git a/app/lib/utils.rb b/app/lib/utils.rb index 5a6c9c49b..bb14b9933 100644 --- a/app/lib/utils.rb +++ b/app/lib/utils.rb @@ -3,6 +3,7 @@ module Utils UUID_PATTERN = %r{\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z} EXTENSIONS_ALLOW_LIST = %w(pdf xml asice asics xzep zip txt doc docx jpg jpeg png tif tiff) + MIMETYPES_ALLOW_LIST = %w(application/x-eform-xml application/xml application/msword application/pdf application/vnd.etsi.asic-e+zip application/vnd.etsi.asic-s+zip application/vnd.openxmlformats-officedocument.wordprocessingml.document application/x-xades_zep application/x-zip-compressed image/jpg image/jpeg image/png image/tiff) def file_directory(file_path) File.dirname(file_path) diff --git a/app/models/message.rb b/app/models/message.rb index c43a7e838..f7cdabd8e 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -114,7 +114,7 @@ def visualization end def all_metadata - metadata.merge(template&.metadata || {}) + metadata&.merge(template&.metadata || {}) end def template diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 680cbe276..8db3303dc 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -24,6 +24,12 @@ class MessageDraft < Message belongs_to :import, class_name: 'MessageDraftsImport', optional: true + validates :uuid, presence: { message: "Message ID can't be blank" } + validates :uuid, format: { with: Utils::UUID_PATTERN, message: 'Message ID must be UUID' } + validates :title, presence: { message: "Title can't be blank" } + validates :delivered_at, presence: true + validate :validate_correlation_id + after_create do add_cascading_tag(thread.box.tenant.draft_tag!) end @@ -49,7 +55,6 @@ class MessageDraft < Message end with_options on: :validate_data do |message_draft| - message_draft.validates :uuid, format: { with: Utils::UUID_PATTERN }, allow_blank: false message_draft.validate :validate_metadata message_draft.validate :validate_form message_draft.validate :validate_objects @@ -156,7 +161,12 @@ def create_form_object # TODO remove UPVS stuff from core domain def validate_form - raise "Disallowed form" unless ::Upvs::ServiceWithFormAllowRule.form_services(all_metadata).any? + return if errors[:metadata].any? + + unless ::Upvs::ServiceWithFormAllowRule.form_services(all_metadata).where(institution_uri: metadata['recipient_uri']).any? + errors.add(:base, :disallowed_form_for_recipient) + return + end raise "Missing XSD schema" unless upvs_form&.xsd_schema @@ -168,7 +178,7 @@ def validate_form document = Nokogiri::XML(document.children.first.children.first.children.first.to_xml) if document.children.first.name == 'XMLDataContainer' - schema = Nokogiri::XML::Schema(upvs_form.xsd_schema) + schema = Nokogiri::XML::Schema(upvs_form&.xsd_schema) form_errors += schema.validate(document) errors.add(:base, :invalid_form) if form_errors.any? @@ -177,7 +187,10 @@ def validate_form private def validate_objects - errors.add(:objects, "No objects found for draft") if objects.size == 0 + if objects.size == 0 + errors.add(:objects, "Message contains no objects") + return + end objects.each do |object| object.valid?(:validate_data) @@ -185,16 +198,25 @@ def validate_objects end forms = objects.select { |o| o.form? } - errors.add(:objects, "Draft has to contain exactly one form") if forms.size != 1 + errors.add(:objects, "Message has to contain exactly one form object") if forms.size != 1 + end + + # TODO remove UPVS stuff from core domain + def validate_correlation_id + if all_metadata&.dig("correlation_id") + errors.add(:metadata, "Correlation ID must be UUID") unless all_metadata.dig("correlation_id").match?(Utils::UUID_PATTERN) + else + errors.add(:metadata, "No correlation ID") + end end def validate_metadata - errors.add(:metadata, "No recipient URI") unless all_metadata["recipient_uri"].present? - errors.add(:metadata, "No posp ID") unless all_metadata["posp_id"].present? - errors.add(:metadata, "No posp version") unless all_metadata["posp_version"].present? - errors.add(:metadata, "No message type") unless all_metadata["message_type"].present? - errors.add(:metadata, "No correlation ID") unless all_metadata["correlation_id"].present? - errors.add(:metadata, "Correlation ID must be UUID") unless all_metadata["correlation_id"]&.match?(Utils::UUID_PATTERN) + errors.add(:metadata, "No recipient URI") unless all_metadata&.dig("recipient_uri") + errors.add(:metadata, "No posp ID") unless all_metadata&.dig("posp_id") + errors.add(:metadata, "No posp version") unless all_metadata&.dig("posp_version") + errors.add(:metadata, "No message type") unless all_metadata&.dig("message_type") + + errors.add(:metadata, "Reference ID must be UUID") if all_metadata&.dig("reference_id") && !all_metadata&.dig("reference_id")&.match?(Utils::UUID_PATTERN) end def validate_with_message_template diff --git a/app/models/message_object.rb b/app/models/message_object.rb index dd0152187..72ae16fe0 100644 --- a/app/models/message_object.rb +++ b/app/models/message_object.rb @@ -25,7 +25,7 @@ class MessageObject < ApplicationRecord scope :to_be_signed, -> { where(to_be_signed: true) } scope :should_be_signed, -> { where(to_be_signed: true, is_signed: false) } - validates :name, presence: true, on: :validate_data + validates :name, presence: { message: "Name can't be blank" }, on: :validate_data validate :allowed_mime_type?, on: :validate_data after_update ->(message_object) { EventBus.publish(:message_object_changed, message_object) } @@ -110,7 +110,11 @@ def downloadable_archived_object? private def allowed_mime_type? - errors.add(:mime_type, "of #{name} object is disallowed, allowed_mime_types: #{Utils::EXTENSIONS_ALLOW_LIST.join(", ")}") unless mimetype + if mimetype + errors.add(:mime_type, "MimeType of #{name} object is disallowed, allowed mimetypes: #{Utils::MIMETYPES_ALLOW_LIST.join(", ")}") unless Utils::MIMETYPES_ALLOW_LIST.include?(mimetype) + else + errors.add(:mime_type, "MimeType of #{name} object is disallowed, allowed file types: #{Utils::EXTENSIONS_ALLOW_LIST.join(", ")}") + end end def has_tag?(tag) diff --git a/app/models/upvs/message_template.rb b/app/models/upvs/message_template.rb index 752b9ea81..dd621b456 100644 --- a/app/models/upvs/message_template.rb +++ b/app/models/upvs/message_template.rb @@ -82,8 +82,8 @@ def create_message_reply(message, original_message:, author:) data: { Predmet: message_title }, - recipient_uri: original_message.metadata["sender_uri"], - correlation_id: original_message.metadata["correlation_id"], + recipient_uri: original_message.metadata&.dig("sender_uri"), + correlation_id: original_message.metadata&.dig("correlation_id"), reference_id: original_message.uuid, original_message_id: original_message.id, status: 'created' diff --git a/config/locales/en.yml b/config/locales/en.yml index fa8bab9ee..38609e91b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -32,3 +32,10 @@ en: hello: "Hello world" no_message_object_name: "File without name" + activerecord: + errors: + format: "%{attribute} %{message}" + messages: + disallowed_form_for_recipient: "Recipient does not accept the form type" + invalid_form: "Form XSD validation failed" + invalid: "%{attribute} is not valid" diff --git a/config/locales/sk.yml b/config/locales/sk.yml index da226b0e8..420d23877 100644 --- a/config/locales/sk.yml +++ b/config/locales/sk.yml @@ -14,6 +14,8 @@ sk: errors: messages: record_invalid: "Validácia neúspešná: %{errors}" + disallowed_form: "Daný typ formulára nie je povolený" + disallowed_form_for_recipient: "Prijímateľ neprijíma tento typ formulára" invalid_form: "Formulár nie je validný voči XSD" models: api_connection: diff --git a/public/openapi.yaml b/public/openapi.yaml index f15c2e52d..4684e3865 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -232,6 +232,7 @@ paths: description: Obsah objektu zakódovaný podľa Base64 type: string required: + - name - mimetype - is_signed - object_type diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml index dff72f5f9..6b09fd958 100644 --- a/test/fixtures/messages.yml +++ b/test/fixtures/messages.yml @@ -12,6 +12,8 @@ ssd_main_general_one: replyable: false metadata: authorized: true + sender_uri: SenderURI + correlation_id: <%= SecureRandom.uuid %> delivery_notification: delivery_period_end_at: <%= DateTime.current - 1.day %> diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb new file mode 100644 index 000000000..14d778356 --- /dev/null +++ b/test/integration/upvs_messages_api_test.rb @@ -0,0 +1,731 @@ +require "test_helper" + +class ThreadsApiTest < ActionDispatch::IntegrationTest + setup do + @key_pair = OpenSSL::PKey::RSA.new File.read 'test/fixtures/tenant_test_cert.pem' + @tenant = tenants(:ssd) + end + + test 'can upload valid message' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :created + end + + test 'marks message invalid unless title present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "Title can't be blank", json_response['message'] + end + + test 'marks message invalid unless no box for given sender URI present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'NonExistentURI', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Invalid Sender Uri', json_response['message'] + end + + test 'marks message invalid unless recipient in white list' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/87654321', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Recipient does not accept the form type', json_response['message'] + end + + test 'marks message invalid unless form type in white list' do + message_params = { + posp_id: '00166073.MSSR_ORSR_Poziadanie_o_vyhotovenie_kopie_listiny_ulozenej_v_zbierke_listin.sk', + posp_version: '1.53', + message_type: 'ks_340702', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/87654321', + title: 'Požiadanie o vyhotovenie kópie listiny uloženej v zbierke zákonom ustanovených listín obchodného registra', + objects: [ + { + name: 'Form.xml', + is_signed: false, + to_be_signed: true, + mimetype: 'application/x-eform-xml', + object_type: 'FORM', + content: Base64.encode64(' + + + + 1000401 + + electronic + v elektronickej podobe + + + + + + + MSSR-ORSR-LegalPerson + + 53509285 + J.J.Solar s. r. o. (IČO: 53509285, spisová značka: Sro/48243/T) + eyJ2YWx1ZSI6IjUzNTA5Mjg1IiwidGV4dCI6IkouSi5Tb2xhciBzLiByLiBv + LiAoScSMTzogNTM1MDkyODUsIHNwaXNvdsOhIHpuYcSNa2E6IFNyby80ODI0 + My9UKSIsInRpdGxlIjoiMTg4IEphbMWhb3bDqSIsImRlc2NyIjoie1wib2Rk + aWVsXCI6MyxcInZsb3prYVwiOjQ4MjQzLFwic3VkXCI6N30iLCJuYW1lIjoi + Si5KLlNvbGFyIHMuIHIuIG8uIChJxIxPOiA1MzUwOTI4NSwgc3Bpc292w6Eg + em5hxI1rYTogU3JvLzQ4MjQzL1QpIiwiY29kZSI6IjUzNTA5Mjg1In0= + + + + + + 188 Jalšové + + + + true + 1 + Zakladateľská listina + + + true + 3 + Vyhlásenie správcu vkladu + + + + + + + lucia.janikova@slovensko.digital + + + + ') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Recipient does not accept the form type', json_response['message'] + end + + test 'marks message invalid unless form is valid XML' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 & Poznamka +') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Form XSD validation failed', json_response['message'] + end + + test 'marks message invalid unless form valid against XSD' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 + Poznamocka +') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Form XSD validation failed', json_response['message'] + end + + test 'marks message invalid unless Message ID present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + + assert_equal "Message ID can't be blank, Message ID must be UUID", json_response['message'] + + end + + test 'marks message invalid unless Message ID in valid format' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: '123', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "Message ID can't be blank, Message ID must be UUID", json_response['message'] + end + + test 'marks message invalid unless Correlation ID present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "No correlation ID", json_response['message'] + end + + test 'marks message invalid unless Recipient URI present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "No recipient URI", json_response['message'] + end + + test 'marks message invalid unless Posp ID present' do + message_params = { + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "No posp ID", json_response['message'] + end + + test 'marks message invalid unless Posp version present' do + message_params = { + posp_id: 'App.GeneralAgenda', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "No posp version", json_response['message'] + end + + test 'marks message invalid unless Message Type present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "No message type", json_response['message'] + end + + test 'marks message invalid unless Reference ID in valid format' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + reference_id: '12345', + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "Reference ID must be UUID", json_response['message'] + end + + test 'marks message invalid unless at least one message object present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + objects: [] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Message contains no objects', json_response['message'] + end + + test 'marks message invalid unless form object present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + objects: [ + { + name: 'Attachment.xml', + is_signed: false, + mimetype: 'application/xml', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Message has to contain exactly one form object', json_response['message'] + end + + test 'marks message invalid unless exactly one form object present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 +') + }, + { + name: 'Attachment.xml', + is_signed: false, + mimetype: 'application/xml', + object_type: 'FORM', + content: Base64.encode64('Hello!') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Message has to contain exactly one form object', json_response['message'] + end + + test 'marks message invalid unless object name present' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 +') + }, + { + is_signed: false, + mimetype: 'application/xml', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal "Objects is not valid, Name can't be blank", json_response['message'] + end + + test 'marks message invalid unless object mimetype in white list' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 +') + }, + { + name: 'Attachment.txt', + is_signed: false, + mimetype: 'text/plain', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') + } + ] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Objects is not valid, MimeType of Attachment.txt object is disallowed, allowed mimetypes: application/x-eform-xml, application/xml, application/msword, application/pdf, application/vnd.etsi.asic-e+zip, application/vnd.etsi.asic-s+zip, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-xades_zep, application/x-zip-compressed, image/jpg, image/jpeg, image/png, image/tiff', json_response['message'] + end +end + From acb6de5ab983258995c53dfbc3012444df24f5ab Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Fri, 8 Mar 2024 12:41:14 +0100 Subject: [PATCH 06/40] Upgrade box selection --- .../api/upvs/messages_controller.rb | 2 +- test/fixtures/boxes.yml | 2 +- test/integration/upvs_messages_api_test.rb | 33 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index 46f1fea0f..a28d0e750 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -41,7 +41,7 @@ def create private def set_box - @box = Box.find_by(uri: permitted_params[:sender_uri]) + @box = @tenant.boxes.find_by(uri: permitted_params[:sender_uri]) end def message_params diff --git a/test/fixtures/boxes.yml b/test/fixtures/boxes.yml index 63b74e399..6e2281529 100644 --- a/test/fixtures/boxes.yml +++ b/test/fixtures/boxes.yml @@ -16,7 +16,7 @@ ssd_other: solver_main: name: Solver main - uri: MyString2 + uri: SolverMainURI tenant: solver short_name: MY1 api_connection: govbox_api_api_connection1 diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb index 14d778356..bd1dea4b2 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_messages_api_test.rb @@ -103,6 +103,39 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal 'Invalid Sender Uri', json_response['message'] end + test 'marks message invalid if given sender URI for box in another tenant' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SolverMainURI', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Invalid Sender Uri', json_response['message'] + end + test 'marks message invalid unless recipient in white list' do message_params = { posp_id: 'App.GeneralAgenda', From 62caa48a9e08609d35d896062ebe7621696b97fb Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Fri, 8 Mar 2024 12:49:27 +0100 Subject: [PATCH 07/40] Update ApiController --- app/controllers/api_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 955cc5fd6..3f2aba174 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -1,5 +1,6 @@ class ApiController < ActionController::API before_action :authenticate_user + before_action :set_sk_locale around_action :wrap_in_request_logger rescue_from JWT::DecodeError do |error| @@ -96,4 +97,8 @@ def render_unprocessable_entity(message) def set_en_locale I18n.locale = :en end + + def set_sk_locale + I18n.locale = :sk + end end From 92e284fabab7f84a6bc875ec9544319734724afe Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Fri, 8 Mar 2024 15:23:03 +0100 Subject: [PATCH 08/40] Add ::Upvs::MessageDrafts --- .../message_thread_component.html.erb | 2 +- ...message_thread_log_item_component.html.erb | 2 +- .../api/upvs/messages_controller.rb | 2 +- app/models/message_draft.rb | 22 +++++----- app/models/upvs/message_draft.rb | 44 +++++++++++++++++++ test/integration/upvs_messages_api_test.rb | 38 +--------------- 6 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 app/models/upvs/message_draft.rb diff --git a/app/components/message_thread_component.html.erb b/app/components/message_thread_component.html.erb index 708d87f48..ac723c45c 100644 --- a/app/components/message_thread_component.html.erb +++ b/app/components/message_thread_component.html.erb @@ -4,7 +4,7 @@
<%= render Common::FlashComponent.new %> <% @thread_messages.each do |message| %> - <% if message.type == 'MessageDraft' %> + <% if message.draft? %> <%# TODO find a better way for handling focus than `message.id == @thread_last_message_draft_id` %> <%= render MessageDraftComponent.new(message: message, signable: Current.user.signer?, is_last: message.id == @thread_last_message_draft_id) %> <% elsif message.collapsed? %> diff --git a/app/components/message_thread_log_item_component.html.erb b/app/components/message_thread_log_item_component.html.erb index 0191785d7..64de428c5 100644 --- a/app/components/message_thread_log_item_component.html.erb +++ b/app/components/message_thread_log_item_component.html.erb @@ -7,7 +7,7 @@
- <% if @message.type == 'MessageDraft' %> + <% if @message.draft? %> <%= render Icons::PencilSquareComponent.new(css_classes: "w-5 h-5 text-gray-600") %> <% elsif @message.collapsed %> <%= render Icons::CogEightToothComponent.new(css_classes: "w-5 h-5 text-gray-600") %> diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index a28d0e750..f0a2cd072 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -5,7 +5,7 @@ class Api::Upvs::MessagesController < ApiController def create render_unprocessable_entity('Invalid Sender Uri') and return unless @box - @message = MessageDraft.create(message_params) + @message = ::Upvs::MessageDraft.create(message_params) @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( box: @box, merge_uuid: @message.metadata['correlation_id'], diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 8db3303dc..93670526b 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -24,11 +24,9 @@ class MessageDraft < Message belongs_to :import, class_name: 'MessageDraftsImport', optional: true - validates :uuid, presence: { message: "Message ID can't be blank" } - validates :uuid, format: { with: Utils::UUID_PATTERN, message: 'Message ID must be UUID' } + validate :validate_uuid validates :title, presence: { message: "Title can't be blank" } validates :delivered_at, presence: true - validate :validate_correlation_id after_create do add_cascading_tag(thread.box.tenant.draft_tag!) @@ -186,6 +184,15 @@ def validate_form end private + + def validate_uuid + if uuid + errors.add(:metadata, "UUID must be in UUID format") unless uuid.match?(Utils::UUID_PATTERN) + else + errors.add(:metadata, "UUID can't be blank") + end + end + def validate_objects if objects.size == 0 errors.add(:objects, "Message contains no objects") @@ -201,15 +208,6 @@ def validate_objects errors.add(:objects, "Message has to contain exactly one form object") if forms.size != 1 end - # TODO remove UPVS stuff from core domain - def validate_correlation_id - if all_metadata&.dig("correlation_id") - errors.add(:metadata, "Correlation ID must be UUID") unless all_metadata.dig("correlation_id").match?(Utils::UUID_PATTERN) - else - errors.add(:metadata, "No correlation ID") - end - end - def validate_metadata errors.add(:metadata, "No recipient URI") unless all_metadata&.dig("recipient_uri") errors.add(:metadata, "No posp ID") unless all_metadata&.dig("posp_id") diff --git a/app/models/upvs/message_draft.rb b/app/models/upvs/message_draft.rb new file mode 100644 index 000000000..53f7f4c09 --- /dev/null +++ b/app/models/upvs/message_draft.rb @@ -0,0 +1,44 @@ +# == Schema Information +# +# Table name: messages +# +# id :bigint not null, primary key +# collapsed :boolean default(FALSE), not null +# delivered_at :datetime not null +# html_visualization :text +# metadata :json +# outbox :boolean default(FALSE), not null +# read :boolean default(FALSE), not null +# recipient_name :string +# replyable :boolean default(TRUE), not null +# sender_name :string +# title :string +# type :string +# uuid :uuid not null +# created_at :datetime not null +# updated_at :datetime not null +# author_id :bigint +# import_id :bigint +# message_thread_id :bigint not null +# +class Upvs::MessageDraft < MessageDraft + validate :validate_correlation_id + + private + + def validate_uuid + if uuid + errors.add(:metadata, 'Message ID must be in UUID format') unless uuid.match?(Utils::UUID_PATTERN) + else + errors.add(:metadata, "Message ID can't be blank") + end + end + + def validate_correlation_id + if all_metadata&.dig("correlation_id") + errors.add(:metadata, "Correlation ID must be UUID") unless all_metadata.dig("correlation_id").match?(Utils::UUID_PATTERN) + else + errors.add(:metadata, "Correlation ID can't be blank") + end + end +end diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb index bd1dea4b2..9cc1fdb65 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_messages_api_test.rb @@ -351,44 +351,10 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) - assert_equal "Message ID can't be blank, Message ID must be UUID", json_response['message'] + assert_equal "Message ID can't be blank", json_response['message'] end - test 'marks message invalid unless Message ID in valid format' do - message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: '123', - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', - title: 'Všeobecná agenda', - 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json - - assert_response :unprocessable_entity - - json_response = JSON.parse(response.body) - assert_equal "Message ID can't be blank, Message ID must be UUID", json_response['message'] - end - test 'marks message invalid unless Correlation ID present' do message_params = { posp_id: 'App.GeneralAgenda', @@ -419,7 +385,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_response :unprocessable_entity json_response = JSON.parse(response.body) - assert_equal "No correlation ID", json_response['message'] + assert_equal "Correlation ID can't be blank", json_response['message'] end test 'marks message invalid unless Recipient URI present' do From 1e420b34b231ccd7353575d02659e89d77391f60 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 12 Mar 2024 14:27:03 +0100 Subject: [PATCH 09/40] Add transaction --- .../api/upvs/messages_controller.rb | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index f0a2cd072..01bb81cc6 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -5,37 +5,39 @@ class Api::Upvs::MessagesController < ApiController def create render_unprocessable_entity('Invalid Sender Uri') and return unless @box - @message = ::Upvs::MessageDraft.create(message_params) - @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( - box: @box, - merge_uuid: @message.metadata['correlation_id'], - title: @message.title, - delivered_at: @message.delivered_at - ) + ::Upvs::MessageDraft.transaction do + @message = ::Upvs::MessageDraft.create(message_params) + @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( + box: @box, + merge_uuid: @message.metadata['correlation_id'], + title: @message.title, + delivered_at: @message.delivered_at + ) - render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? - @message.save + render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? + @message.save - permitted_params[:objects].each do |object_params| - message_object = @message.objects.create(object_params.except(:content)) + permitted_params[:objects].each do |object_params| + message_object = @message.objects.create(object_params.except(:content)) - MessageObjectDatum.create( - message_object: message_object, - blob: Base64.decode64(object_params[:content]) - ) - end + MessageObjectDatum.create( + message_object: message_object, + blob: Base64.decode64(object_params[:content]) + ) + end - if @message.valid?(:validate_data) - @message.metadata['status'] = 'created' + if @message.valid?(:validate_data) + @message.metadata['status'] = 'created' - head :created - else - @message.metadata['status'] = 'invalid' + head :created + else + @message.metadata['status'] = 'invalid' - render_unprocessable_entity(@message.errors.messages.values.join(', ')) - end + render_unprocessable_entity(@message.errors.messages.values.join(', ')) + end - @message.save + @message.save + end end private From 804482093bf4210790be20228137bc789fb836c6 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Mon, 18 Mar 2024 17:14:52 +0100 Subject: [PATCH 10/40] Do not create draft unless valid --- .../api/upvs/messages_controller.rb | 5 +- test/integration/upvs_messages_api_test.rb | 75 +++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index 01bb81cc6..d51ce0ec1 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -17,7 +17,7 @@ def create render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? @message.save - permitted_params[:objects].each do |object_params| + permitted_params[:objects]&.each do |object_params| message_object = @message.objects.create(object_params.except(:content)) MessageObjectDatum.create( @@ -32,11 +32,10 @@ def create head :created else @message.metadata['status'] = 'invalid' + @message.destroy render_unprocessable_entity(@message.errors.messages.values.join(', ')) end - - @message.save end end diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb index 9cc1fdb65..ae1fc3a49 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_messages_api_test.rb @@ -4,6 +4,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest setup do @key_pair = OpenSSL::PKey::RSA.new File.read 'test/fixtures/tenant_test_cert.pem' @tenant = tenants(:ssd) + @before_request_messages_count = Message.count end test 'can upload valid message' do @@ -35,6 +36,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :created + assert_not_equal Message.count, @before_request_messages_count end test 'marks message invalid unless title present' do @@ -68,6 +70,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "Title can't be blank", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless no box for given sender URI present' do @@ -101,6 +105,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Invalid Sender Uri', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid if given sender URI for box in another tenant' do @@ -134,6 +140,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Invalid Sender Uri', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless recipient in white list' do @@ -168,6 +176,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Recipient does not accept the form type', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless form type in white list' do @@ -249,6 +259,44 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Recipient does not accept the form type', json_response['message'] + + assert_equal Message.count, @before_request_messages_count + end + + test 'marks message invalid unless message type in white list' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'ks_340702', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/87654321', + title: 'Požiadanie o vyhotovenie kópie listiny uloženej v zbierke zákonom ustanovených listín obchodného registra', + 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/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Recipient does not accept the form type', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless form is valid XML' do @@ -283,6 +331,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Form XSD validation failed', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless form valid against XSD' do @@ -318,6 +368,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Form XSD validation failed', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Message ID present' do @@ -353,6 +405,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal "Message ID can't be blank", json_response['message'] + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Correlation ID present' do @@ -386,6 +439,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "Correlation ID can't be blank", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Recipient URI present' do @@ -419,6 +474,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "No recipient URI", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Posp ID present' do @@ -452,6 +509,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "No posp ID", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Posp version present' do @@ -485,6 +544,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "No posp version", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Message Type present' do @@ -518,6 +579,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "No message type", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless Reference ID in valid format' do @@ -553,6 +616,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "Reference ID must be UUID", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless at least one message object present' do @@ -574,6 +639,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Message contains no objects', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless form object present' do @@ -603,6 +670,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Message has to contain exactly one form object', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless exactly one form object present' do @@ -644,6 +713,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Message has to contain exactly one form object', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless object name present' do @@ -684,6 +755,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal "Objects is not valid, Name can't be blank", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end test 'marks message invalid unless object mimetype in white list' do @@ -725,6 +798,8 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest json_response = JSON.parse(response.body) assert_equal 'Objects is not valid, MimeType of Attachment.txt object is disallowed, allowed mimetypes: application/x-eform-xml, application/xml, application/msword, application/pdf, application/vnd.etsi.asic-e+zip, application/vnd.etsi.asic-s+zip, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-xades_zep, application/x-zip-compressed, image/jpg, image/jpeg, image/png, image/tiff', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end end From 1306094545aaaa3f8806e789540d6a562e0304df Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 10:52:59 +0100 Subject: [PATCH 11/40] Add LocaleConcern --- app/components/message_draft_body_component.html.erb | 2 +- app/controllers/api_controller.rb | 9 +-------- app/controllers/application_controller.rb | 2 ++ app/controllers/concerns/locale_concern.rb | 9 +++++++++ 4 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 app/controllers/concerns/locale_concern.rb diff --git a/app/components/message_draft_body_component.html.erb b/app/components/message_draft_body_component.html.erb index d3d3c8dce..82b2b5cc5 100644 --- a/app/components/message_draft_body_component.html.erb +++ b/app/components/message_draft_body_component.html.erb @@ -17,7 +17,7 @@ <% end %>
<% end %> - <% unless @message.not_yet_submitted? %> + <% unless @message.correctly_created? %>
<% if @message.being_submitted? %>

Správa sa odosiela

diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 3f2aba174..c42e689ea 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -1,4 +1,5 @@ class ApiController < ActionController::API + include LocaleConcern before_action :authenticate_user before_action :set_sk_locale around_action :wrap_in_request_logger @@ -93,12 +94,4 @@ def render_service_unavailable_error def render_unprocessable_entity(message) render status: :unprocessable_entity, json: { message: message } end - - def set_en_locale - I18n.locale = :en - end - - def set_sk_locale - I18n.locale = :sk - end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 584c4b576..207fbfdd3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,9 +1,11 @@ class ApplicationController < ActionController::Base include Authentication include Pundit::Authorization + include LocaleConcern after_action :verify_authorized after_action :verify_policy_scoped, only: :index if respond_to?(:index) before_action :set_menu_context + before_action :set_sk_locale def pundit_user Current.user diff --git a/app/controllers/concerns/locale_concern.rb b/app/controllers/concerns/locale_concern.rb new file mode 100644 index 000000000..682005120 --- /dev/null +++ b/app/controllers/concerns/locale_concern.rb @@ -0,0 +1,9 @@ +module LocaleConcern + def set_en_locale + I18n.locale = :en + end + + def set_sk_locale + I18n.locale = :sk + end +end From 5dbb69b841c98b0d2c5e6a72702ebaf28ac36226 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 10:53:09 +0100 Subject: [PATCH 12/40] Update policies --- app/policies/message_draft_policy.rb | 2 +- app/policies/upvs/message_draft_policy.rb | 64 +++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 app/policies/upvs/message_draft_policy.rb diff --git a/app/policies/message_draft_policy.rb b/app/policies/message_draft_policy.rb index 49328c189..0b64a5824 100644 --- a/app/policies/message_draft_policy.rb +++ b/app/policies/message_draft_policy.rb @@ -35,7 +35,7 @@ def create? end def reply? - true + false end def show? diff --git a/app/policies/upvs/message_draft_policy.rb b/app/policies/upvs/message_draft_policy.rb new file mode 100644 index 000000000..566176859 --- /dev/null +++ b/app/policies/upvs/message_draft_policy.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +class ::Upvs::MessageDraftPolicy < ApplicationPolicy + attr_reader :user, :message + + def initialize(user, message) + @user = user + @message = message + end + + class Scope < Scope + def resolve + # TODO: this does not work for imported drafts (no tags present) + scope.where( + MessageThreadsTag + .select(1) + .joins(tag_groups: :group_memberships) + .where("message_threads_tags.message_thread_id = messages.message_thread_id") + .where(group_memberships: { user_id: @user.id }) + .arel.exists + ) + end + end + + def new? + true + end + + def index? + true + end + + def create? + true # TODO: can everyone create new messages? + end + + def reply? + false + end + + def show? + true + end + + def update? + create? + end + + def submit? + create? + end + + def destroy? + create? + end + + def confirm_unlock? + unlock? + end + + def unlock? + create? + end +end From 0d99332d825453ac732b141a415a4fbe7248d772 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 10:53:26 +0100 Subject: [PATCH 13/40] Add tags to MessageObjects imported from API --- app/controllers/api/upvs/messages_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index d51ce0ec1..61b750a90 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -19,6 +19,9 @@ def create permitted_params[:objects]&.each do |object_params| message_object = @message.objects.create(object_params.except(:content)) + tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] + + message_object.tags += tags MessageObjectDatum.create( message_object: message_object, @@ -28,6 +31,7 @@ def create if @message.valid?(:validate_data) @message.metadata['status'] = 'created' + @message.save head :created else From a6106b108edf02a261cd120750d04bf45d9eb940 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 11:33:00 +0100 Subject: [PATCH 14/40] Update Message policies & fixtures --- app/policies/message_draft_policy.rb | 2 +- app/policies/upvs/message_draft_policy.rb | 2 +- test/fixtures/messages.yml | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/policies/message_draft_policy.rb b/app/policies/message_draft_policy.rb index 0b64a5824..49328c189 100644 --- a/app/policies/message_draft_policy.rb +++ b/app/policies/message_draft_policy.rb @@ -35,7 +35,7 @@ def create? end def reply? - false + true end def show? diff --git a/app/policies/upvs/message_draft_policy.rb b/app/policies/upvs/message_draft_policy.rb index 566176859..ce1d240a2 100644 --- a/app/policies/upvs/message_draft_policy.rb +++ b/app/policies/upvs/message_draft_policy.rb @@ -35,7 +35,7 @@ def create? end def reply? - false + true end def show? diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml index 6b09fd958..2c5fce7da 100644 --- a/test/fixtures/messages.yml +++ b/test/fixtures/messages.yml @@ -44,6 +44,7 @@ ssd_main_general_draft_one: html_visualization: Reply to something delivered_at: 2023-05-18 16:18:26 thread: ssd_main_general + replyable: false metadata: status: created author: basic @@ -55,6 +56,7 @@ ssd_main_general_draft_two: html_visualization: MyString delivered_at: 2023-05-18 16:18:26 thread: ssd_main_general + replyable: false metadata: status: created author: basic @@ -66,6 +68,7 @@ ssd_main_delivery_draft: html_visualization: MyString delivered_at: 2023-05-18 16:19:26 thread: ssd_main_delivery + replyable: false metadata: status: created author: basic From 19b2107a93ff13205bb249af84553a994614f8a7 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 12:02:41 +0100 Subject: [PATCH 15/40] Undo change in MessageDraftBodyComponent --- app/components/message_draft_body_component.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/message_draft_body_component.html.erb b/app/components/message_draft_body_component.html.erb index 82b2b5cc5..d3d3c8dce 100644 --- a/app/components/message_draft_body_component.html.erb +++ b/app/components/message_draft_body_component.html.erb @@ -17,7 +17,7 @@ <% end %>
<% end %> - <% unless @message.correctly_created? %> + <% unless @message.not_yet_submitted? %>
<% if @message.being_submitted? %>

Správa sa odosiela

From 2cbef6b022c8eb1d9ff9433f3226249b71d7a902 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 20 Mar 2024 14:21:41 +0100 Subject: [PATCH 16/40] Small update on Message, MessafeDraft --- .../message_draft_body_component.html.erb | 18 ++++++++++++------ app/models/message.rb | 4 +++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/components/message_draft_body_component.html.erb b/app/components/message_draft_body_component.html.erb index d3d3c8dce..90f1e63ae 100644 --- a/app/components/message_draft_body_component.html.erb +++ b/app/components/message_draft_body_component.html.erb @@ -17,14 +17,20 @@ <% end %>
<% end %> - <% unless @message.not_yet_submitted? %> + <% if @message.invalid? || @message.submit_failed? %> +
+ <% if @message.invalid? %> +

Správa nie je validná

+ <% elsif @message.submit_failed? %> +

Správu sa nepodarilo odoslať

+ <% end %> +
+ <% elsif @message.being_submitted? || @message.submitted? %>
- <% if @message.being_submitted? %> -

Správa sa odosiela

- <% elsif @message.submitted? %> + <% if @message.submitted? %>

Správa bola odoslaná

- <% elsif @message.submit_failed? %> -

Správu sa nepodarilo odoslať

+ <% elsif @message.being_submitted? %> +

Správu sa odosiela

<% end %>
<% end %> diff --git a/app/models/message.rb b/app/models/message.rb index a879235ec..c932afc61 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -106,7 +106,9 @@ def visualization document = Nokogiri::XML(form.unsigned_content) do |config| config.noblanks end - document = Nokogiri::XML(document.xpath('*:XMLDataContainer/*:XMLData/*').to_xml) if document.xpath('*:XMLDataContainer/*:XMLData').any? + document = Nokogiri::XML(document.xpath('*:XMLDataContainer/*:XMLData/*').to_xml) do |config| + config.noblanks + end if document.xpath('*:XMLDataContainer/*:XMLData').any? template = Nokogiri::XSLT(upvs_form.xslt_html) template.transform(document) From e0ffdd9af18fd8f468fad6a82281f7432700c063 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Fri, 22 Mar 2024 14:20:37 +0100 Subject: [PATCH 17/40] Enable creating Upvs::MessageDraft with tags --- .../api/upvs/messages_controller.rb | 19 ++++- public/openapi.yaml | 5 ++ test/integration/upvs_messages_api_test.rb | 74 +++++++++++++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/api/upvs/messages_controller.rb index 61b750a90..5291af630 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/api/upvs/messages_controller.rb @@ -19,9 +19,9 @@ def create permitted_params[:objects]&.each do |object_params| message_object = @message.objects.create(object_params.except(:content)) - tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] + object_tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] - message_object.tags += tags + message_object.tags += object_tags MessageObjectDatum.create( message_object: message_object, @@ -29,13 +29,23 @@ def create ) end + permitted_params[:tags]&.each do |tag_name| + tag = @tenant.tags.find_by(name: tag_name) + + unless tag + @message.destroy + render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return + end + + @message.add_cascading_tag(tag) + end + if @message.valid?(:validate_data) @message.metadata['status'] = 'created' @message.save head :created else - @message.metadata['status'] = 'invalid' @message.destroy render_unprocessable_entity(@message.errors.messages.values.join(', ')) @@ -94,7 +104,8 @@ def permitted_params :mimetype, :object_type, :content, - ] + ], + tags: [] ) end diff --git a/public/openapi.yaml b/public/openapi.yaml index 4684e3865..b8b1276c8 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -250,6 +250,11 @@ paths: mimetype: application/vnd.etsi.asic-e+zip form: false content: base64 asice content + tags: + description: Štítky, ktorými majú byť správy označené + type: array + items: + type: string required: - message_id - correlation_id diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb index ae1fc3a49..cae941d2e 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_messages_api_test.rb @@ -7,6 +7,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest @before_request_messages_count = Message.count end + test 'can upload valid message' do message_params = { posp_id: 'App.GeneralAgenda', @@ -39,6 +40,42 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_not_equal Message.count, @before_request_messages_count end + test 'can upload valid message with tags if they exist' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 +') + } + ], + tags: ['Legal', 'Other'] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :created + assert_not_equal Message.count, @before_request_messages_count + + assert Upvs::MessageDraft.last.tags.map(&:name).include?('Legal') + assert Upvs::MessageDraft.last.tags.map(&:name).include?('Other') + end + test 'marks message invalid unless title present' do message_params = { posp_id: 'App.GeneralAgenda', @@ -801,5 +838,42 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end + + test 'marks message invalid unless tags with given names exist' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678', + title: 'Všeobecná agenda', + 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 +') + } + ], + tags: ['Special'] + } + + post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Tag with name Special does not exist', json_response['message'] + + assert_equal Message.count, @before_request_messages_count + end end From a417d2d4b4cda7bce928f27dd461559ddb45db91 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Sun, 24 Mar 2024 17:05:24 +0100 Subject: [PATCH 18/40] Create SubmissionErrorTag --- app/jobs/govbox/submit_message_draft_job.rb | 3 +++ app/models/submission_error_tag.rb | 26 +++++++++++++++++++ app/models/tenant.rb | 1 + ...40322132501_create_submission_error_tag.rb | 10 +++++++ db/schema.rb | 2 +- 5 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 app/models/submission_error_tag.rb create mode 100644 db/migrate/20240322132501_create_submission_error_tag.rb diff --git a/app/jobs/govbox/submit_message_draft_job.rb b/app/jobs/govbox/submit_message_draft_job.rb index 176a8b999..759d2e429 100644 --- a/app/jobs/govbox/submit_message_draft_job.rb +++ b/app/jobs/govbox/submit_message_draft_job.rb @@ -30,6 +30,7 @@ def perform(message_draft, schedule_sync: true, upvs_client: UpvsEnvironment.upv success, response_status, response_body = sktalk_api.receive_and_save_to_outbox(message_draft_data) if success + message_draft.remove_cascading_tag(message_draft.tenant.submission_error_tag) message_draft.submitted! Govbox::SyncBoxJob.set(wait: 3.minutes).perform_later(message_draft.thread.box) if schedule_sync else @@ -57,6 +58,8 @@ def build_objects(message_draft) end def handle_submit_fail(message_draft, response_status, response_message) + message_draft.add_cascading_tag(message_draft.tenant.submission_error_tag) + case response_status when 408, 503 message_draft.metadata["status"] = "temporary_submit_fail" diff --git a/app/models/submission_error_tag.rb b/app/models/submission_error_tag.rb new file mode 100644 index 000000000..801c7fb52 --- /dev/null +++ b/app/models/submission_error_tag.rb @@ -0,0 +1,26 @@ +# == Schema Information +# +# Table name: tags +# +# id :bigint not null, primary key +# color :enum +# external_name :string +# icon :string +# name :string not null +# tag_groups_count :integer default(0), not null +# type :string not null +# visible :boolean default(TRUE), not null +# created_at :datetime not null +# updated_at :datetime not null +# owner_id :bigint +# tenant_id :bigint not null +# +class SubmissionErrorTag < Tag + def destroyable? + false + end + + def gives_access? + false + end +end diff --git a/app/models/tenant.rb b/app/models/tenant.rb index 371a09105..9697d67cd 100644 --- a/app/models/tenant.rb +++ b/app/models/tenant.rb @@ -24,6 +24,7 @@ class Tenant < ApplicationRecord has_one :signed_tag has_one :signed_externally_tag has_one :archived_tag + has_one :submission_error_tag has_many :tags, dependent: :destroy has_many :signature_requested_from_tags has_many :signed_by_tags diff --git a/db/migrate/20240322132501_create_submission_error_tag.rb b/db/migrate/20240322132501_create_submission_error_tag.rb new file mode 100644 index 000000000..165325329 --- /dev/null +++ b/db/migrate/20240322132501_create_submission_error_tag.rb @@ -0,0 +1,10 @@ +class CreateSubmissionErrorTag < ActiveRecord::Migration[7.1] + def up + Tenant.find_each do |tenant| + tenant.tags.find_or_create_by!( + name: 'Chyba odoslania', + type: 'SubmissionErrorTag' + ) + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 4b9fd0024..6541d45ea 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_03_13_111201) do +ActiveRecord::Schema[7.1].define(version: 2024_03_22_132501) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" From 9adae25112d66f3412914bae4076d556569c02de Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Mon, 25 Mar 2024 08:44:32 +0100 Subject: [PATCH 19/40] Small GUI updates --- app/components/message_draft_body_component.html.erb | 2 +- app/components/message_draft_component.html.erb | 12 +++++++----- app/models/message_draft.rb | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/components/message_draft_body_component.html.erb b/app/components/message_draft_body_component.html.erb index 90f1e63ae..b7ac8c8c2 100644 --- a/app/components/message_draft_body_component.html.erb +++ b/app/components/message_draft_body_component.html.erb @@ -30,7 +30,7 @@ <% if @message.submitted? %>

Správa bola odoslaná

<% elsif @message.being_submitted? %> -

Správu sa odosiela

+

Správa sa odosiela

<% end %>
<% end %> diff --git a/app/components/message_draft_component.html.erb b/app/components/message_draft_component.html.erb index 91dd8417a..04a61e24b 100644 --- a/app/components/message_draft_component.html.erb +++ b/app/components/message_draft_component.html.erb @@ -18,11 +18,13 @@
<% end %> -
- <%= button_to message_draft_path(@message), method: :delete, class: "flex justify-strech items-start self-stretch flex-grow-0 flex-shrink-0 gap-2 p-6 rounded-lg border border-gray-300 px-3.5 py-2.5 hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 rounded-lg", data: { turbo_frame: "_top" }, title: "Zahodiť draft" do %> - <%= render Icons::TrashComponent.new(css_classes: "w-5 h-5 text-red-600") %> - <% end %> -
+ <% if @message.not_yet_submitted? %> +
+ <%= button_to message_draft_path(@message), method: :delete, class: "flex justify-strech items-start self-stretch flex-grow-0 flex-shrink-0 gap-2 p-6 rounded-lg border border-gray-300 px-3.5 py-2.5 hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 rounded-lg", data: { turbo_frame: "_top" }, title: "Zahodiť draft" do %> + <%= render Icons::TrashComponent.new(css_classes: "w-5 h-5 text-red-600") %> + <% end %> +
+ <% end %> diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 857aebd05..5751aafc7 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -102,7 +102,7 @@ def invalid? end def not_yet_submitted? - metadata["status"] == "created" || metadata["status"] == "invalid" + %w[created invalid].include?(metadata["status"]) end def being_submitted? @@ -114,7 +114,7 @@ def submitted? end def submit_failed? - metadata["status"] == "submit_fail" + %w[submit_fail temporary_submit_fail].include?(metadata["status"]) end def being_submitted! From 7ed7bfdf0c55214dba2b97f7ca3fee833e173f8f Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Mon, 25 Mar 2024 10:45:24 +0100 Subject: [PATCH 20/40] Update syntax in MessageDraft --- app/models/message_draft.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 5751aafc7..8a85a975e 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -102,7 +102,7 @@ def invalid? end def not_yet_submitted? - %w[created invalid].include?(metadata["status"]) + metadata["status"].in?(%w[created invalid]) end def being_submitted? @@ -114,7 +114,7 @@ def submitted? end def submit_failed? - %w[submit_fail temporary_submit_fail].include?(metadata["status"]) + metadata["status"].in?(%w[submit_fail temporary_submit_fail]) end def being_submitted! From 53a048bbb2a25a8d97a8b02574749222ff8e1af5 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Mon, 25 Mar 2024 10:47:35 +0100 Subject: [PATCH 21/40] Add TODO --- app/jobs/govbox/submit_message_draft_job.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/jobs/govbox/submit_message_draft_job.rb b/app/jobs/govbox/submit_message_draft_job.rb index 759d2e429..f8a0271ca 100644 --- a/app/jobs/govbox/submit_message_draft_job.rb +++ b/app/jobs/govbox/submit_message_draft_job.rb @@ -58,6 +58,7 @@ def build_objects(message_draft) end def handle_submit_fail(message_draft, response_status, response_message) + # TODO notification message_draft.add_cascading_tag(message_draft.tenant.submission_error_tag) case response_status From 68df69178cbc8ecfe3472c0b9eb9314ec7ad0a3c Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Mon, 25 Mar 2024 12:59:52 +0100 Subject: [PATCH 22/40] Update tag name --- db/migrate/20240322132501_create_submission_error_tag.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20240322132501_create_submission_error_tag.rb b/db/migrate/20240322132501_create_submission_error_tag.rb index 165325329..718a88185 100644 --- a/db/migrate/20240322132501_create_submission_error_tag.rb +++ b/db/migrate/20240322132501_create_submission_error_tag.rb @@ -2,7 +2,7 @@ class CreateSubmissionErrorTag < ActiveRecord::Migration[7.1] def up Tenant.find_each do |tenant| tenant.tags.find_or_create_by!( - name: 'Chyba odoslania', + name: 'Problémové', type: 'SubmissionErrorTag' ) end From b2ea5b2e1f892015810cf50900c2b93bc412f74d Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Tue, 26 Mar 2024 16:07:58 +0100 Subject: [PATCH 23/40] Move creating Upvs::MessageDraft creating from controller to concern --- app/controllers/api/messages_controller.rb | 29 ++++ .../upvs/message_draft_concern.rb} | 17 +-- config/routes.rb | 6 +- public/openapi.yaml | 4 +- test/integration/upvs_messages_api_test.rb | 124 +++++++++++------- 5 files changed, 117 insertions(+), 63 deletions(-) rename app/controllers/{api/upvs/messages_controller.rb => concerns/upvs/message_draft_concern.rb} (89%) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 5ec95e842..c21f5f8a1 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -1,5 +1,34 @@ class Api::MessagesController < Api::TenantController + before_action :set_en_locale + + include Upvs::MessageDraftConcern + + ALLOWED_CONTENT_TYPES = ['application/json;type=upvs'] + + before_action :check_content_type, only: :create + + def create + case message_type(raw_content_type) + when 'upvs' + create_upvs_message_draft + end + end + def show @message = @tenant.messages.find(params[:id]) end + + private + + def raw_content_type + request.content_type + end + + def message_type(content_type) + content_type.match(/(application\/json\;type\=)(.*)/)[2] + end + + def check_content_type + render_bad_request(ActionController::BadRequest.new("Disallowed Content-Type: #{raw_content_type}")) unless raw_content_type.in?(ALLOWED_CONTENT_TYPES) + end end diff --git a/app/controllers/api/upvs/messages_controller.rb b/app/controllers/concerns/upvs/message_draft_concern.rb similarity index 89% rename from app/controllers/api/upvs/messages_controller.rb rename to app/controllers/concerns/upvs/message_draft_concern.rb index 5291af630..1f28f663f 100644 --- a/app/controllers/api/upvs/messages_controller.rb +++ b/app/controllers/concerns/upvs/message_draft_concern.rb @@ -1,8 +1,6 @@ -class Api::Upvs::MessagesController < ApiController - before_action :set_box - before_action :set_en_locale - - def create +module Upvs::MessageDraftConcern + def create_upvs_message_draft + set_box render_unprocessable_entity('Invalid Sender Uri') and return unless @box ::Upvs::MessageDraft.transaction do @@ -17,7 +15,7 @@ def create render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? @message.save - permitted_params[:objects]&.each do |object_params| + permitted_params.fetch(:objects, []).each do |object_params| message_object = @message.objects.create(object_params.except(:content)) object_tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] @@ -29,7 +27,7 @@ def create ) end - permitted_params[:tags]&.each do |tag_name| + permitted_params.fetch(:tags, []).each do |tag_name| tag = @tenant.tags.find_by(name: tag_name) unless tag @@ -86,6 +84,7 @@ def message_params def permitted_params params.permit( + :type, :message_id, :correlation_id, :reference_id, @@ -108,8 +107,4 @@ def permitted_params tags: [] ) end - - def authenticate_user - @tenant = ApiEnvironment.tenant_token_authenticator.verify_token(authenticity_token) - end end diff --git a/config/routes.rb b/config/routes.rb index 96ec99971..e19556163 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -201,12 +201,8 @@ end end - namespace :upvs do - resources :messages, only: [:create] - end - resources :message_threads, only: [:show] - resources :messages, only: [:show] + resources :messages, only: [:create, :show] end if UpvsEnvironment.sso_support? diff --git a/public/openapi.yaml b/public/openapi.yaml index b8b1276c8..0b570a437 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -132,7 +132,7 @@ paths: security: - "Tenant_Token": [] - /api/upvs/messages: + /api/messages: post: tags: [ Správy ] summary: Vytvorí novú správu vrátane jej objektov @@ -140,7 +140,7 @@ paths: Vytvorí novú správu vrátane jej objektov. requestBody: content: - application/json: + application/json;type=upvs: schema: type: object properties: diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_messages_api_test.rb index cae941d2e..d3378c2d8 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_messages_api_test.rb @@ -7,7 +7,6 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest @before_request_messages_count = Message.count end - test 'can upload valid message' do message_params = { posp_id: 'App.GeneralAgenda', @@ -34,7 +33,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :created assert_not_equal Message.count, @before_request_messages_count @@ -67,7 +66,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest tags: ['Legal', 'Other'] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :created assert_not_equal Message.count, @before_request_messages_count @@ -76,7 +75,42 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert Upvs::MessageDraft.last.tags.map(&:name).include?('Other') end - test 'marks message invalid unless title present' do + test 'does not create message unless valid ContentType' do + message_params = { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + 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', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=Draft" } + + assert_response :bad_request + + json_response = JSON.parse(response.body) + assert_equal "Disallowed Content-Type: application/json;type=Draft", json_response['message'] + + assert_equal Message.count, @before_request_messages_count + end + + test 'does not create message unless title present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -101,7 +135,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -111,7 +145,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless no box for given sender URI present' do + test 'does not create message unless no box for given sender URI present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -136,7 +170,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -146,7 +180,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid if given sender URI for box in another tenant' do + test 'does not create message if given sender URI for box in another tenant' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -171,7 +205,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -181,7 +215,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless recipient in white list' do + test 'does not create message unless recipient in white list' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -207,7 +241,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -217,7 +251,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless form type in white list' do + test 'does not create message unless form type in white list' do message_params = { posp_id: '00166073.MSSR_ORSR_Poziadanie_o_vyhotovenie_kopie_listiny_ulozenej_v_zbierke_listin.sk', posp_version: '1.53', @@ -290,7 +324,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -300,7 +334,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless message type in white list' do + test 'does not create message unless message type in white list' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -326,7 +360,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -336,7 +370,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless form is valid XML' do + test 'does not create message unless form is valid XML' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -362,7 +396,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }) .to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -372,7 +406,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless form valid against XSD' do + test 'does not create message unless form valid against XSD' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -399,7 +433,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -409,7 +443,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Message ID present' do + test 'does not create message unless Message ID present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -434,7 +468,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -445,7 +479,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Correlation ID present' do + test 'does not create message unless Correlation ID present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -470,7 +504,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -480,7 +514,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Recipient URI present' do + test 'does not create message unless Recipient URI present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -505,7 +539,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -515,7 +549,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Posp ID present' do + test 'does not create message unless Posp ID present' do message_params = { posp_version: '1.9', message_type: 'App.GeneralAgenda', @@ -540,7 +574,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -550,7 +584,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Posp version present' do + test 'does not create message unless Posp version present' do message_params = { posp_id: 'App.GeneralAgenda', message_type: 'App.GeneralAgenda', @@ -575,7 +609,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -585,7 +619,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Message Type present' do + test 'does not create message unless Message Type present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -610,7 +644,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -620,7 +654,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless Reference ID in valid format' do + test 'does not create message unless Reference ID in valid format' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -647,7 +681,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -657,7 +691,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless at least one message object present' do + test 'does not create message unless at least one message object present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -670,7 +704,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest objects: [] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -680,7 +714,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless form object present' do + test 'does not create message unless form object present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -701,7 +735,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -711,7 +745,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless exactly one form object present' do + test 'does not create message unless exactly one form object present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -744,7 +778,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -754,7 +788,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless object name present' do + test 'does not create message unless object name present' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -786,7 +820,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -796,7 +830,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless object mimetype in white list' do + test 'does not create message unless object mimetype in white list' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -829,7 +863,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -839,7 +873,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'marks message invalid unless tags with given names exist' do + test 'does not create message unless tags with given names exist' do message_params = { posp_id: 'App.GeneralAgenda', posp_version: '1.9', @@ -866,7 +900,7 @@ class ThreadsApiTest < ActionDispatch::IntegrationTest tags: ['Special'] } - post '/api/upvs/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity From 227e4ce06b3bb253bc5f7547035169b719f2c926 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 27 Mar 2024 10:03:57 +0100 Subject: [PATCH 24/40] Small syntax fix --- app/controllers/api/messages_controller.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index c21f5f8a1..4408c9801 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -1,12 +1,11 @@ class Api::MessagesController < Api::TenantController before_action :set_en_locale + before_action :check_content_type, only: :create include Upvs::MessageDraftConcern ALLOWED_CONTENT_TYPES = ['application/json;type=upvs'] - before_action :check_content_type, only: :create - def create case message_type(raw_content_type) when 'upvs' From 922047ab7422dc85326e47ee8244d5d171afaabe Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 27 Mar 2024 14:49:48 +0100 Subject: [PATCH 25/40] Add SkTalk Class param to API & fix XSDs seeds --- app/controllers/concerns/upvs/message_draft_concern.rb | 2 ++ db/seeds.rb | 6 +++--- public/openapi.yaml | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/controllers/concerns/upvs/message_draft_concern.rb b/app/controllers/concerns/upvs/message_draft_concern.rb index 1f28f663f..79bd14d00 100644 --- a/app/controllers/concerns/upvs/message_draft_concern.rb +++ b/app/controllers/concerns/upvs/message_draft_concern.rb @@ -77,6 +77,7 @@ def message_params posp_id: permitted_message_params['posp_id'], posp_version: permitted_message_params['posp_version'], message_type: permitted_message_params['message_type'], + sktalk_class: permitted_message_params['sktalk_class'], status: 'being_loaded' } } @@ -95,6 +96,7 @@ def permitted_params :posp_id, :posp_version, :message_type, + :sktalk_class, :title, objects: [ :name, diff --git a/db/seeds.rb b/db/seeds.rb index 5c8c7a14b..4b09ec6fb 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -753,7 +753,7 @@ - + @@ -1931,7 +1931,7 @@ - + @@ -2917,7 +2917,7 @@ - + diff --git a/public/openapi.yaml b/public/openapi.yaml index 0b570a437..275f09620 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -178,6 +178,11 @@ paths: description: Typ správy type: string example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk + sktalk_class: + description: Trieda SkTalk správy + type: string + example: IAM_FORM_ZNEPLATNENIE_TU_REQ_01 + default: EGOV_APPLICATION sender_business_reference: description: Spisová značka odosielateľa elektronickej správy type: string From 41d85d5315e795b2716d0b49f242e34520f5334b Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 09:03:49 +0200 Subject: [PATCH 26/40] Rename test file --- ...pvs_messages_api_test.rb => upvs_message_drafts_api_test.rb} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/integration/{upvs_messages_api_test.rb => upvs_message_drafts_api_test.rb} (99%) diff --git a/test/integration/upvs_messages_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb similarity index 99% rename from test/integration/upvs_messages_api_test.rb rename to test/integration/upvs_message_drafts_api_test.rb index d3378c2d8..26e0a148b 100644 --- a/test/integration/upvs_messages_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -1,6 +1,6 @@ require "test_helper" -class ThreadsApiTest < ActionDispatch::IntegrationTest +class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest setup do @key_pair = OpenSSL::PKey::RSA.new File.read 'test/fixtures/tenant_test_cert.pem' @tenant = tenants(:ssd) From d975c175ab2da3cccf5c2862e738dcfd893fb8d2 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 09:29:45 +0200 Subject: [PATCH 27/40] Update drafts API endpoint --- app/controllers/api/messages_controller.rb | 12 ++--- app/models/message_draft.rb | 2 +- config/routes.rb | 6 ++- .../upvs_message_drafts_api_test.rb | 48 +++++++++---------- 4 files changed, 35 insertions(+), 33 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 4408c9801..0b6937e4d 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -1,22 +1,22 @@ class Api::MessagesController < Api::TenantController before_action :set_en_locale - before_action :check_content_type, only: :create + before_action :check_content_type, only: :message_drafts include Upvs::MessageDraftConcern ALLOWED_CONTENT_TYPES = ['application/json;type=upvs'] - def create + def show + @message = @tenant.messages.find(params[:id]) + end + + def message_drafts case message_type(raw_content_type) when 'upvs' create_upvs_message_draft end end - def show - @message = @tenant.messages.find(params[:id]) - end - private def raw_content_type diff --git a/app/models/message_draft.rb b/app/models/message_draft.rb index 9709f2cae..990201d29 100644 --- a/app/models/message_draft.rb +++ b/app/models/message_draft.rb @@ -161,7 +161,7 @@ def create_form_object def validate_form return if errors[:metadata].any? - unless ::Upvs::ServiceWithFormAllowRule.form_services(all_metadata).where(institution_uri: metadata['recipient_uri']).any? + unless ::Upvs::ServiceWithFormAllowRule.matching_metadata(all_metadata).where(institution_uri: metadata['recipient_uri']).any? errors.add(:base, :disallowed_form_for_recipient) return end diff --git a/config/routes.rb b/config/routes.rb index c76122d44..baade5293 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -201,8 +201,10 @@ end end - resources :message_threads, only: [:show] - resources :messages, only: [:create, :show] + resources :message_threads, only: :show + resources :messages, only: :show do + post :message_drafts, on: :collection + end end if UpvsEnvironment.sso_support? diff --git a/test/integration/upvs_message_drafts_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb index 26e0a148b..7c6d48695 100644 --- a/test/integration/upvs_message_drafts_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -33,7 +33,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :created assert_not_equal Message.count, @before_request_messages_count @@ -66,7 +66,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest tags: ['Legal', 'Other'] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :created assert_not_equal Message.count, @before_request_messages_count @@ -100,7 +100,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=Draft" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=Draft" } assert_response :bad_request @@ -135,7 +135,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -170,7 +170,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -205,7 +205,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -241,7 +241,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -324,7 +324,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -360,7 +360,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -396,7 +396,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }) .to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }) .to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -433,7 +433,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -468,7 +468,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -504,7 +504,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -539,7 +539,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -574,7 +574,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -609,7 +609,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -644,7 +644,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -681,7 +681,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -704,7 +704,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest objects: [] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -735,7 +735,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -778,7 +778,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -820,7 +820,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -863,7 +863,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity @@ -900,7 +900,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest tags: ['Special'] } - post '/api/messages', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } assert_response :unprocessable_entity From 3e79a00ccfac1ec1315263ba89e9f4c4924ecd30 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 11:33:37 +0200 Subject: [PATCH 28/40] Update controller --- app/controllers/api/messages_controller.rb | 100 ++++++++++++++-- .../concerns/upvs/message_draft_concern.rb | 112 ------------------ app/models/message.rb | 2 +- 3 files changed, 88 insertions(+), 126 deletions(-) delete mode 100644 app/controllers/concerns/upvs/message_draft_concern.rb diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 0b6937e4d..01aed4351 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -1,33 +1,107 @@ class Api::MessagesController < Api::TenantController before_action :set_en_locale - before_action :check_content_type, only: :message_drafts + before_action :load_box, only: :message_drafts + before_action :check_message_type, only: :message_drafts - include Upvs::MessageDraftConcern - - ALLOWED_CONTENT_TYPES = ['application/json;type=upvs'] + ALLOWED_MESSAGE_TYPES = ['Upvs::MessageDraft'] def show @message = @tenant.messages.find(params[:id]) end def message_drafts - case message_type(raw_content_type) - when 'upvs' - create_upvs_message_draft + render_unprocessable_entity('Invalid sender') and return unless @box + + ::Message.transaction do + @message = ::Message.create(permitted_params.except(:objects, :tags).merge({ + sender_name: @box.name, + # recipient_name: TODO search name in UPVS dataset, + outbox: true, + replyable: false, + delivered_at: Time.now + })) + @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( + box: @box, + merge_uuid: @message.metadata['correlation_id'], + title: @message.title, + delivered_at: @message.delivered_at + ) + + render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? + @message.save + + permitted_params.fetch(:objects, []).each do |object_params| + message_object = @message.objects.create(object_params.except(:content)) + object_tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] + + message_object.tags += object_tags + + MessageObjectDatum.create( + message_object: message_object, + blob: Base64.decode64(object_params[:content]) + ) + end + + permitted_params.fetch(:tags, []).each do |tag_name| + tag = @tenant.tags.find_by(name: tag_name) + + unless tag + @message.destroy + render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return + end + + @message.add_cascading_tag(tag) + end + + if @message.valid?(:validate_data) + @message.metadata['status'] = 'created' + @message.save + + head :created + else + @message.destroy + + render_unprocessable_entity(@message.errors.messages.values.join(', ')) + end end end private - def raw_content_type - request.content_type + def permitted_params + params.permit( + :type, + :uuid, + :title, + metadata: [ + :correlation_id, + :reference_id, + :sender_uri, + :recipient_uri, + :sender_business_reference, + :recipient_business_reference, + :posp_id, + :posp_version, + :message_type, + :sktalk_class + ], + objects: [ + :name, + :is_signed, + :to_be_signed, + :mimetype, + :object_type, + :content, + ], + tags: [] + ) end - def message_type(content_type) - content_type.match(/(application\/json\;type\=)(.*)/)[2] + def check_message_type + render_bad_request(ActionController::BadRequest.new("Disallowed message type: #{params[:type]}")) unless params[:type].in?(ALLOWED_MESSAGE_TYPES) end - def check_content_type - render_bad_request(ActionController::BadRequest.new("Disallowed Content-Type: #{raw_content_type}")) unless raw_content_type.in?(ALLOWED_CONTENT_TYPES) + def load_box + @box = @tenant.boxes.find_by(uri: permitted_params[:metadata][:sender_uri]) end end diff --git a/app/controllers/concerns/upvs/message_draft_concern.rb b/app/controllers/concerns/upvs/message_draft_concern.rb deleted file mode 100644 index 79bd14d00..000000000 --- a/app/controllers/concerns/upvs/message_draft_concern.rb +++ /dev/null @@ -1,112 +0,0 @@ -module Upvs::MessageDraftConcern - def create_upvs_message_draft - set_box - render_unprocessable_entity('Invalid Sender Uri') and return unless @box - - ::Upvs::MessageDraft.transaction do - @message = ::Upvs::MessageDraft.create(message_params) - @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( - box: @box, - merge_uuid: @message.metadata['correlation_id'], - title: @message.title, - delivered_at: @message.delivered_at - ) - - render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? - @message.save - - permitted_params.fetch(:objects, []).each do |object_params| - message_object = @message.objects.create(object_params.except(:content)) - object_tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] - - message_object.tags += object_tags - - MessageObjectDatum.create( - message_object: message_object, - blob: Base64.decode64(object_params[:content]) - ) - end - - permitted_params.fetch(:tags, []).each do |tag_name| - tag = @tenant.tags.find_by(name: tag_name) - - unless tag - @message.destroy - render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return - end - - @message.add_cascading_tag(tag) - end - - if @message.valid?(:validate_data) - @message.metadata['status'] = 'created' - @message.save - - head :created - else - @message.destroy - - render_unprocessable_entity(@message.errors.messages.values.join(', ')) - end - end - end - - private - - def set_box - @box = @tenant.boxes.find_by(uri: permitted_params[:sender_uri]) - end - - def message_params - permitted_message_params = permitted_params - { - delivered_at: Time.now, - outbox: true, - # recipient_name: TODO search name in UPVS dataset, - replyable: false, - sender_name: @box.name, - title: permitted_message_params['title'], - uuid: permitted_message_params['message_id'], - metadata: { - correlation_id: permitted_message_params['correlation_id'], - reference_id: permitted_message_params['reference_id'], - sender_uri: permitted_message_params['sender_uri'], - recipient_uri: permitted_message_params['recipient_uri'], - sender_business_reference: permitted_message_params['sender_business_reference'], - recipient_business_reference: permitted_message_params['recipient_business_reference'], - posp_id: permitted_message_params['posp_id'], - posp_version: permitted_message_params['posp_version'], - message_type: permitted_message_params['message_type'], - sktalk_class: permitted_message_params['sktalk_class'], - status: 'being_loaded' - } - } - end - - def permitted_params - params.permit( - :type, - :message_id, - :correlation_id, - :reference_id, - :sender_uri, - :recipient_uri, - :sender_business_reference, - :recipient_business_reference, - :posp_id, - :posp_version, - :message_type, - :sktalk_class, - :title, - objects: [ - :name, - :is_signed, - :to_be_signed, - :mimetype, - :object_type, - :content, - ], - tags: [] - ) - end -end diff --git a/app/models/message.rb b/app/models/message.rb index ee8d5736c..cf109d05b 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -115,7 +115,7 @@ def visualization end def all_metadata - metadata.merge(template&.metadata) + metadata.merge(template&.metadata || {}) end def template From cd0b01f157c6b32eb84d6575a4d2468c4ccd0bee Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 11:35:40 +0200 Subject: [PATCH 29/40] Update tests according to changes --- .../upvs_message_drafts_api_test.rb | 455 ++++++++++-------- 1 file changed, 265 insertions(+), 190 deletions(-) diff --git a/test/integration/upvs_message_drafts_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb index 7c6d48695..8f37bcecb 100644 --- a/test/integration/upvs_message_drafts_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -9,14 +9,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'can upload valid message' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -33,7 +36,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + 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_not_equal Message.count, @before_request_messages_count @@ -41,14 +44,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'can upload valid message with tags if they exist' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -66,7 +72,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest tags: ['Legal', 'Other'] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + 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_not_equal Message.count, @before_request_messages_count @@ -77,13 +83,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless valid ContentType' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Vszp::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', @@ -100,25 +110,28 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=Draft" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :bad_request json_response = JSON.parse(response.body) - assert_equal "Disallowed Content-Type: application/json;type=Draft", json_response['message'] + assert_equal "Disallowed message type: Vszp::MessageDraft", json_response['message'] assert_equal Message.count, @before_request_messages_count end test 'does not create message unless title present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', + 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', @@ -135,7 +148,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -147,13 +160,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless no box for given sender URI present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'NonExistentURI', - recipient_uri: 'ico://sk/12345678', + 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: 'NonExistentURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -170,25 +187,29 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity json_response = JSON.parse(response.body) - assert_equal 'Invalid Sender Uri', json_response['message'] + assert_equal 'Invalid sender', json_response['message'] assert_equal Message.count, @before_request_messages_count end test 'does not create message if given sender URI for box in another tenant' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SolverMainURI', - recipient_uri: 'ico://sk/12345678', + 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: 'SolverMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -205,26 +226,29 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity json_response = JSON.parse(response.body) - assert_equal 'Invalid Sender Uri', json_response['message'] + assert_equal 'Invalid sender', json_response['message'] assert_equal Message.count, @before_request_messages_count end test 'does not create message unless recipient in white list' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/87654321', + 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/87654321' + }, objects: [ { name: 'Form.xml', @@ -241,7 +265,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -253,14 +277,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless form type in white list' do message_params = { - posp_id: '00166073.MSSR_ORSR_Poziadanie_o_vyhotovenie_kopie_listiny_ulozenej_v_zbierke_listin.sk', - posp_version: '1.53', - message_type: 'ks_340702', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/87654321', + type: 'Upvs::MessageDraft', title: 'Požiadanie o vyhotovenie kópie listiny uloženej v zbierke zákonom ustanovených listín obchodného registra', + uuid: SecureRandom.uuid, + metadata: { + posp_id: '00166073.MSSR_ORSR_Poziadanie_o_vyhotovenie_kopie_listiny_ulozenej_v_zbierke_listin.sk', + posp_version: '1.53', + message_type: 'ks_340702', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/87654321' + }, objects: [ { name: 'Form.xml', @@ -324,7 +351,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -336,14 +363,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless message type in white list' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'ks_340702', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/87654321', + type: 'Upvs::MessageDraft', title: 'Požiadanie o vyhotovenie kópie listiny uloženej v zbierke zákonom ustanovených listín obchodného registra', + uuid: SecureRandom.uuid, metadata: { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'ks_340702', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/87654321' + }, objects: [ { name: 'Form.xml', @@ -360,7 +389,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -372,14 +401,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless form is valid XML' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -396,7 +428,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }) .to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }) , as: :json assert_response :unprocessable_entity @@ -408,14 +440,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless form valid against XSD' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -433,7 +468,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -445,13 +480,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Message ID present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + 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', @@ -468,7 +506,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -481,13 +519,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Correlation ID present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -504,7 +545,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -516,13 +557,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Recipient URI present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', + 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' + }, objects: [ { name: 'Form.xml', @@ -539,7 +583,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -551,13 +595,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Posp ID present' do message_params = { - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -574,7 +621,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -586,13 +633,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Posp version present' do message_params = { - posp_id: 'App.GeneralAgenda', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_id: 'App.GeneralAgenda', + message_type: 'App.GeneralAgenda', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -609,7 +659,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -621,13 +671,16 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Message Type present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -644,7 +697,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -656,15 +709,18 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless Reference ID in valid format' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - reference_id: '12345', - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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, + reference_id: '12345', + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [ { name: 'Form.xml', @@ -681,7 +737,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -693,18 +749,22 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless at least one message object present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', + uuid: SecureRandom.uuid, + metadata: { + posp_id: 'App.GeneralAgenda', + posp_version: '1.9', + message_type: 'App.GeneralAgenda', + message_id: SecureRandom.uuid, + correlation_id: SecureRandom.uuid, + sender_uri: 'SSDMainURI', + recipient_uri: 'ico://sk/12345678' + }, objects: [] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -716,14 +776,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless form object present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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: 'Attachment.xml', @@ -735,7 +798,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -747,14 +810,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless exactly one form object present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -778,7 +844,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -790,14 +856,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless object name present' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -820,7 +889,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -832,14 +901,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless object mimetype in white list' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -863,7 +935,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity @@ -875,14 +947,17 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest test 'does not create message unless tags with given names exist' do message_params = { - posp_id: 'App.GeneralAgenda', - posp_version: '1.9', - message_type: 'App.GeneralAgenda', - message_id: SecureRandom.uuid, - correlation_id: SecureRandom.uuid, - sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + 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', @@ -900,7 +975,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest tags: ['Special'] } - post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }).to_json, headers: { "Content-Type": "application/json;type=upvs" } + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json assert_response :unprocessable_entity From 2a68475231ec6c5e23a67691178df6e4e52f31eb Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 13:04:16 +0200 Subject: [PATCH 30/40] Move creating Message of special type to its class --- app/controllers/api/messages_controller.rb | 16 +------- app/models/upvs/message_draft.rb | 43 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 01aed4351..8f58117c0 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -13,22 +13,8 @@ def message_drafts render_unprocessable_entity('Invalid sender') and return unless @box ::Message.transaction do - @message = ::Message.create(permitted_params.except(:objects, :tags).merge({ - sender_name: @box.name, - # recipient_name: TODO search name in UPVS dataset, - outbox: true, - replyable: false, - delivered_at: Time.now - })) - @message.thread = @box&.message_threads&.find_or_build_by_merge_uuid( - box: @box, - merge_uuid: @message.metadata['correlation_id'], - title: @message.title, - delivered_at: @message.delivered_at - ) - + @message = permitted_params[:type].classify.safe_constantize.load_and_validate(permitted_params, box: @box) render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? - @message.save permitted_params.fetch(:objects, []).each do |object_params| message_object = @message.objects.create(object_params.except(:content)) diff --git a/app/models/upvs/message_draft.rb b/app/models/upvs/message_draft.rb index 53f7f4c09..5e143d4ca 100644 --- a/app/models/upvs/message_draft.rb +++ b/app/models/upvs/message_draft.rb @@ -24,6 +24,49 @@ class Upvs::MessageDraft < MessageDraft validate :validate_correlation_id + def self.load_and_validate(message_params, box:) + message_params = message_params.permit( + :type, + :uuid, + :title, + metadata: [ + :correlation_id, + :reference_id, + :sender_uri, + :recipient_uri, + :sender_business_reference, + :recipient_business_reference, + :posp_id, + :posp_version, + :message_type, + :sktalk_class + ] + ) + + message = ::Message.create(message_params.except(:objects, :tags).merge( + { + sender_name: box.name, + # recipient_name: TODO search name in UPVS dataset, + outbox: true, + replyable: false, + delivered_at: Time.now + } + ) + ) + + message.thread = box.message_threads&.find_or_build_by_merge_uuid( + box: box, + merge_uuid: message.metadata['correlation_id'], + title: message.title, + delivered_at: message.delivered_at + ) + + return message unless message.valid? + + message.save + message + end + private def validate_uuid From 5b0d49960fc39d89d15940af35f0d946eda27bc5 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 13:16:07 +0200 Subject: [PATCH 31/40] Update API specification --- public/openapi.yaml | 109 ++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/public/openapi.yaml b/public/openapi.yaml index 275f09620..5b35805ba 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -132,69 +132,78 @@ paths: security: - "Tenant_Token": [] - /api/messages: + /api/messages/message_drafts: post: tags: [ Správy ] - summary: Vytvorí novú správu vrátane jej objektov + summary: Vytvorí novú rozpracovanú správu vrátane jej objektov description: | - Vytvorí novú správu vrátane jej objektov. + Vytvorí novú rozpracovanú správu vrátane jej objektov. requestBody: content: - application/json;type=upvs: + application/json: schema: type: object properties: - message_id: - description: Identifikátor správy - type: string - format: uuid - correlation_id: - description: Identifikátor vlákna správ + title: + description: Predmet správy type: string - format: uuid - reference_id: - description: Identifikátor správy, na ktorú sa správa (odpoveď) viaže + example: Žaloba + uuid: + description: Identifikátor správy type: string format: uuid - recipient_uri: - description: Identifikátor prijímateľa správy - type: string - format: uri - example: ico://sk/83369510 - sender_uri: - description: Identifikátor odosielateľa správy - type: string - format: uri - example: ico://sk/83369526 - posp_id: - description: Identifikátor formulára - type: string - example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk - posp_version: - description: Verzia formulára - type: string - example: "1.11" - message_type: + type: description: Typ správy type: string - example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk - sktalk_class: - description: Trieda SkTalk správy - type: string - example: IAM_FORM_ZNEPLATNENIE_TU_REQ_01 - default: EGOV_APPLICATION - sender_business_reference: - description: Spisová značka odosielateľa elektronickej správy - type: string - example: "1234567" - recipient_business_reference: - description: Spisová značka prijímateľa elektronickej správy - type: string - example: EX1234/2000 - title: - description: Predmet správy - type: string - example: Žaloba + enum: + - Upvs::MessageDraft + metadata: + description: Metaúdaje správy + type: object + properties: + correlation_id: + description: Identifikátor vlákna správ + type: string + format: uuid + reference_id: + description: Identifikátor správy, na ktorú sa správa (odpoveď) viaže + type: string + format: uuid + recipient_uri: + description: Identifikátor prijímateľa správy + type: string + format: uri + example: ico://sk/83369510 + sender_uri: + description: Identifikátor odosielateľa správy + type: string + format: uri + example: ico://sk/83369526 + posp_id: + description: Identifikátor formulára + type: string + example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk + posp_version: + description: Verzia formulára + type: string + example: "1.11" + message_type: + description: Typ správy + type: string + example: 00166073.RESS_EZA_Zaloba_doplnenie_ine.sk + sktalk_class: + description: Trieda SkTalk správy + type: string + example: IAM_FORM_ZNEPLATNENIE_TU_REQ_01 + default: EGOV_APPLICATION + sender_business_reference: + description: Spisová značka odosielateľa elektronickej správy + type: string + example: "1234567" + recipient_business_reference: + description: Spisová značka prijímateľa elektronickej správy + type: string + example: EX1234/2000 objects: description: Objekty správy type: array From fe5fc6fde5deaedf0eabdb9af4ab9d1351d627fb Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 13:22:16 +0200 Subject: [PATCH 32/40] Make updates after setting default value for metadata: {} --- app/models/upvs/message_template.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/upvs/message_template.rb b/app/models/upvs/message_template.rb index d4abd4e69..6f25d5425 100644 --- a/app/models/upvs/message_template.rb +++ b/app/models/upvs/message_template.rb @@ -82,8 +82,8 @@ def create_message_reply(message, original_message:, author:) data: { Predmet: message_title }, - recipient_uri: original_message.metadata&.dig("sender_uri"), - correlation_id: original_message.metadata&.dig("correlation_id"), + recipient_uri: original_message.metadata.dig("sender_uri"), + correlation_id: original_message.metadata.dig("correlation_id"), reference_id: original_message.uuid, original_message_id: original_message.id, status: 'created' From 33373a3d8fc6dd265067012d77e1617ad683d20c Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Wed, 10 Apr 2024 13:46:40 +0200 Subject: [PATCH 33/40] Update Localization --- app/controllers/api_controller.rb | 3 +-- app/controllers/application_controller.rb | 2 +- app/controllers/concerns/locale_concern.rb | 9 --------- app/controllers/concerns/localization.rb | 15 +++++++++++++++ 4 files changed, 17 insertions(+), 12 deletions(-) delete mode 100644 app/controllers/concerns/locale_concern.rb create mode 100644 app/controllers/concerns/localization.rb diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb index 24f6a7be2..afe2f23a1 100644 --- a/app/controllers/api_controller.rb +++ b/app/controllers/api_controller.rb @@ -1,7 +1,6 @@ class ApiController < ActionController::API - include LocaleConcern + include Localization before_action :authenticate_user - before_action :set_sk_locale around_action :wrap_in_request_logger rescue_from JWT::DecodeError do |error| diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 207fbfdd3..39678ddf4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,7 @@ class ApplicationController < ActionController::Base include Authentication include Pundit::Authorization - include LocaleConcern + include Localization after_action :verify_authorized after_action :verify_policy_scoped, only: :index if respond_to?(:index) before_action :set_menu_context diff --git a/app/controllers/concerns/locale_concern.rb b/app/controllers/concerns/locale_concern.rb deleted file mode 100644 index 682005120..000000000 --- a/app/controllers/concerns/locale_concern.rb +++ /dev/null @@ -1,9 +0,0 @@ -module LocaleConcern - def set_en_locale - I18n.locale = :en - end - - def set_sk_locale - I18n.locale = :sk - end -end diff --git a/app/controllers/concerns/localization.rb b/app/controllers/concerns/localization.rb new file mode 100644 index 000000000..1fe4936a4 --- /dev/null +++ b/app/controllers/concerns/localization.rb @@ -0,0 +1,15 @@ +module Localization + extend ActiveSupport::Concern + + included do + before_action :set_sk_locale + end + + def set_en_locale + I18n.locale = :en + end + + def set_sk_locale + I18n.locale = :sk + end +end From 626ccb5ff83048a48fa066bffa4da0f50279f88f Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 09:34:27 +0200 Subject: [PATCH 34/40] Enable to add tags for MessageObjects --- app/controllers/api/messages_controller.rb | 27 ++++++++++++++-------- app/models/message_object.rb | 13 +++++++++++ app/models/message_thread.rb | 8 +++---- public/openapi.yaml | 5 ++++ 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 8f58117c0..2b776a962 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -17,10 +17,15 @@ def message_drafts render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? permitted_params.fetch(:objects, []).each do |object_params| - message_object = @message.objects.create(object_params.except(:content)) - object_tags = message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] + message_object = @message.objects.create(object_params.except(:content, :tags)) + message_object.tags += message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] - message_object.tags += object_tags + object_params.fetch(:tags, []).each do |tag_name| + tag = find_tenant_tag_by_name(tag_name) + render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return unless tag + + message_object.add_tag(tag) + end MessageObjectDatum.create( message_object: message_object, @@ -29,12 +34,8 @@ def message_drafts end permitted_params.fetch(:tags, []).each do |tag_name| - tag = @tenant.tags.find_by(name: tag_name) - - unless tag - @message.destroy - render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return - end + tag = find_tenant_tag_by_name(tag_name) + render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return unless tag @message.add_cascading_tag(tag) end @@ -54,6 +55,13 @@ def message_drafts private + def find_tenant_tag_by_name(tag_name) + tag = @tenant.tags.find_by(name: tag_name) + @message.destroy unless tag + + tag + end + def permitted_params params.permit( :type, @@ -78,6 +86,7 @@ def permitted_params :mimetype, :object_type, :content, + tags: [] ], tags: [] ) diff --git a/app/models/message_object.rb b/app/models/message_object.rb index 72ae16fe0..39e2f8fc0 100644 --- a/app/models/message_object.rb +++ b/app/models/message_object.rb @@ -53,6 +53,19 @@ def self.create_message_objects(message, objects) end end + def add_tag(tag) + assign_tag(tag) + thread.assign_tag(tag) + + if tag.is_a?(SignatureRequestedFromTag) + assign_tag(tag.tenant.signature_requested_tag) + thread.assign_tag(tag.tenant.signature_requested_tag) + elsif tag.is_a?(SignedByTag) + assign_tag(tag.tenant.signed_tag) + thread.assign_tag(tag.tenant.signed_tag) + end + end + def mark_signed_by_user(user) assign_tag(user.signed_by_tag) unassign_tag(user.signature_requested_from_tag) diff --git a/app/models/message_thread.rb b/app/models/message_thread.rb index cdd9b80c1..943dff2db 100644 --- a/app/models/message_thread.rb +++ b/app/models/message_thread.rb @@ -158,6 +158,10 @@ def remove_signature_requested_from_user(user) end end + def assign_tag(tag) + message_threads_tags.find_or_create_by!(tag: tag) + end + private def has_tag?(tag) @@ -168,10 +172,6 @@ def has_tag_in_message_objects?(tag) objects.joins(:tags).where(tags: tag).exists? end - def assign_tag(tag) - message_threads_tags.find_or_create_by!(tag: tag) - end - def unassign_tag(tag) message_threads_tags.find_by(tag: tag)&.destroy end diff --git a/public/openapi.yaml b/public/openapi.yaml index 5b35805ba..74f57fee1 100644 --- a/public/openapi.yaml +++ b/public/openapi.yaml @@ -245,6 +245,11 @@ paths: content: description: Obsah objektu zakódovaný podľa Base64 type: string + tags: + description: Štítky, ktorými má byť objekt označený + type: array + items: + type: string required: - name - mimetype From 53f44f5a0106490cd83938426abe64c4cc09bc46 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 10:10:37 +0200 Subject: [PATCH 35/40] Add tests --- test/fixtures/tags.yml | 16 +++ .../upvs_message_drafts_api_test.rb | 120 +++++++++++++++++- 2 files changed, 135 insertions(+), 1 deletion(-) diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml index 864f35067..099731f4d 100644 --- a/test/fixtures/tags.yml +++ b/test/fixtures/tags.yml @@ -82,6 +82,14 @@ ssd_signature_requested: icon: pencil color: yellow +ssd_basic_user_signature_requested: + name: 'Na podpis: Another user' + type: SignatureRequestedFromTag + visible: true + tenant: ssd + icon: pencil + color: yellow + ssd_signed: name: Podpisane type: SignedTag @@ -90,6 +98,14 @@ ssd_signed: icon: fingerprint color: green +ssd_basic_user_signed: + name: 'Podpisane: Another user' + type: SignedByTag + visible: true + tenant: ssd + icon: fingerprint + color: green + ssd_archived: name: Archivovane type: ArchivedTag diff --git a/test/integration/upvs_message_drafts_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb index 8f37bcecb..a905c5b89 100644 --- a/test/integration/upvs_message_drafts_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -984,5 +984,123 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end -end + test 'can upload valid message with object tags if they exist' 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 +'), + tags: ['Na podpis'] + } + ], + tags: ['Legal', 'Other'] + } + + 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_not_equal Message.count, @before_request_messages_count + + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name) == ['Na podpis'] + end + + test 'can upload valid message with object SignatureRequestedFromTags if they exist' 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 +'), + tags: ['Na podpis: Another user'] + } + ], + tags: ['Legal', 'Other'] + } + + 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_not_equal Message.count, @before_request_messages_count + + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis: Another user') + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis') + end + + test 'can upload valid message with object SignedByTags if they exist' 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 +'), + tags: ['Podpisane: Another user'] + } + ], + tags: ['Legal', 'Other'] + } + + 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_not_equal Message.count, @before_request_messages_count + + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane: Another user') + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane') + end +end From 73b5b3ce22ec98818d2940b8eeb9570e94eba4e8 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 11:29:20 +0200 Subject: [PATCH 36/40] Do tags validation before creating Message --- app/controllers/api/messages_controller.rb | 29 +++++++++++----------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 2b776a962..d0f1460f8 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -2,6 +2,7 @@ class Api::MessagesController < Api::TenantController before_action :set_en_locale before_action :load_box, only: :message_drafts before_action :check_message_type, only: :message_drafts + before_action :check_tags, only: :message_drafts ALLOWED_MESSAGE_TYPES = ['Upvs::MessageDraft'] @@ -10,8 +11,6 @@ def show end def message_drafts - render_unprocessable_entity('Invalid sender') and return unless @box - ::Message.transaction do @message = permitted_params[:type].classify.safe_constantize.load_and_validate(permitted_params, box: @box) render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? @@ -21,9 +20,7 @@ def message_drafts message_object.tags += message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] object_params.fetch(:tags, []).each do |tag_name| - tag = find_tenant_tag_by_name(tag_name) - render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return unless tag - + tag = @tenant.tags.find_by(name: tag_name) message_object.add_tag(tag) end @@ -34,9 +31,7 @@ def message_drafts end permitted_params.fetch(:tags, []).each do |tag_name| - tag = find_tenant_tag_by_name(tag_name) - render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return unless tag - + tag = @tenant.tags.find_by(name: tag_name) @message.add_cascading_tag(tag) end @@ -55,13 +50,6 @@ def message_drafts private - def find_tenant_tag_by_name(tag_name) - tag = @tenant.tags.find_by(name: tag_name) - @message.destroy unless tag - - tag - end - def permitted_params params.permit( :type, @@ -96,7 +84,18 @@ def check_message_type render_bad_request(ActionController::BadRequest.new("Disallowed message type: #{params[:type]}")) unless params[:type].in?(ALLOWED_MESSAGE_TYPES) end + def check_tags + tag_names = permitted_params.fetch(:tags, []) + permitted_params.fetch(:objects, []).map {|o| o['tags'] }.compact + + tag_names.each do |tag_name| + @tenant.tags.find_by!(name: tag_name) + rescue ActiveRecord::RecordNotFound + render_unprocessable_entity("Tag with name #{tag_name} does not exist") and return + end + end + def load_box @box = @tenant.boxes.find_by(uri: permitted_params[:metadata][:sender_uri]) + render_unprocessable_entity('Invalid sender') and return unless @box end end From 7efebf151477647a64097ec2916228861172a9b1 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 12:45:21 +0200 Subject: [PATCH 37/40] Update assigning tags --- app/controllers/api/messages_controller.rb | 3 ++- app/models/message_object.rb | 21 ++++----------------- app/models/signature_requested_from_tag.rb | 10 ++++++++++ app/models/signed_by_tag.rb | 10 ++++++++++ app/models/tag.rb | 8 ++++++++ 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index d0f1460f8..7d97fd1db 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -21,7 +21,8 @@ def message_drafts object_params.fetch(:tags, []).each do |tag_name| tag = @tenant.tags.find_by(name: tag_name) - message_object.add_tag(tag) + tag.assign_to_message_object(message_object) + tag.assign_to_thread(@message.thread) end MessageObjectDatum.create( diff --git a/app/models/message_object.rb b/app/models/message_object.rb index 39e2f8fc0..a02f09669 100644 --- a/app/models/message_object.rb +++ b/app/models/message_object.rb @@ -53,19 +53,6 @@ def self.create_message_objects(message, objects) end end - def add_tag(tag) - assign_tag(tag) - thread.assign_tag(tag) - - if tag.is_a?(SignatureRequestedFromTag) - assign_tag(tag.tenant.signature_requested_tag) - thread.assign_tag(tag.tenant.signature_requested_tag) - elsif tag.is_a?(SignedByTag) - assign_tag(tag.tenant.signed_tag) - thread.assign_tag(tag.tenant.signed_tag) - end - end - def mark_signed_by_user(user) assign_tag(user.signed_by_tag) unassign_tag(user.signature_requested_from_tag) @@ -120,6 +107,10 @@ def downloadable_archived_object? archived_object&.archived? end + def assign_tag(tag) + message_objects_tags.find_or_create_by!(tag: tag) + end + private def allowed_mime_type? @@ -134,10 +125,6 @@ def has_tag?(tag) message_objects_tags.joins(:tag).where(tag: tag).exists? end - def assign_tag(tag) - message_objects_tags.find_or_create_by!(tag: tag) - end - def unassign_tag(tag) message_objects_tags.find_by(tag: tag)&.destroy end diff --git a/app/models/signature_requested_from_tag.rb b/app/models/signature_requested_from_tag.rb index c9e44b302..bf8b81b97 100644 --- a/app/models/signature_requested_from_tag.rb +++ b/app/models/signature_requested_from_tag.rb @@ -16,6 +16,16 @@ # tenant_id :bigint not null # class SignatureRequestedFromTag < Tag + def assign_to_message_object(message_object) + super + tenant.signature_requested_tag.assign_to_message_object(message_object) + end + + def assign_to_thread(thread) + super + tenant.signature_requested_tag.assign_to_thread(thread) + end + def destroyable? false end diff --git a/app/models/signed_by_tag.rb b/app/models/signed_by_tag.rb index 5811aad51..21ed714b8 100644 --- a/app/models/signed_by_tag.rb +++ b/app/models/signed_by_tag.rb @@ -16,6 +16,16 @@ # tenant_id :bigint not null # class SignedByTag < Tag + def assign_to_message_object(message_object) + super + tenant.signed_tag.assign_to_message_object(message_object) + end + + def assign_to_thread(thread) + super + tenant.signed_tag.assign_to_thread(thread) + end + def destroyable? false end diff --git a/app/models/tag.rb b/app/models/tag.rb index 9d62885f3..3f28c1fc1 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -41,6 +41,14 @@ class Tag < ApplicationRecord after_update_commit ->(tag) { EventBus.publish(:tag_renamed, tag) if previous_changes.key?("name") } + def assign_to_message_object(message_object) + message_object.assign_tag(self) + end + + def assign_to_thread(thread) + thread.assign_tag(self) + end + def mark_readable_by_groups(groups) self.groups += groups end From e182d66955083d8cad1e977d1b9a752533f3e128 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 13:31:31 +0200 Subject: [PATCH 38/40] Change Upvs::MessageDraft.load_and_validate method to Upvs::MessageDraft.load_from_params --- app/controllers/api/messages_controller.rb | 3 ++- app/models/upvs/message_draft.rb | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 8f58117c0..b114670b8 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -13,8 +13,9 @@ def message_drafts render_unprocessable_entity('Invalid sender') and return unless @box ::Message.transaction do - @message = permitted_params[:type].classify.safe_constantize.load_and_validate(permitted_params, box: @box) + @message = permitted_params[:type].classify.safe_constantize.load_from_params(permitted_params, box: @box) render_unprocessable_entity(@message.errors.messages.values.join(', ')) and return unless @message.valid? + @message.save permitted_params.fetch(:objects, []).each do |object_params| message_object = @message.objects.create(object_params.except(:content)) diff --git a/app/models/upvs/message_draft.rb b/app/models/upvs/message_draft.rb index 5e143d4ca..dfd36f131 100644 --- a/app/models/upvs/message_draft.rb +++ b/app/models/upvs/message_draft.rb @@ -24,7 +24,7 @@ class Upvs::MessageDraft < MessageDraft validate :validate_correlation_id - def self.load_and_validate(message_params, box:) + def self.load_from_params(message_params, box:) message_params = message_params.permit( :type, :uuid, @@ -61,9 +61,6 @@ def self.load_and_validate(message_params, box:) delivered_at: message.delivered_at ) - return message unless message.valid? - - message.save message end From 304126bbec47faa84772d3f67d00b46cc800b662 Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 14:38:56 +0200 Subject: [PATCH 39/40] Update assigning SignedExternallyTag --- app/controllers/api/messages_controller.rb | 2 +- .../upvs_message_drafts_api_test.rb | 159 ++++++++++++------ 2 files changed, 106 insertions(+), 55 deletions(-) diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index 7d97fd1db..a24fcf613 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -17,13 +17,13 @@ def message_drafts permitted_params.fetch(:objects, []).each do |object_params| message_object = @message.objects.create(object_params.except(:content, :tags)) - message_object.tags += message_object.is_signed ? [@message.thread.box.tenant.signed_externally_tag!] : [] object_params.fetch(:tags, []).each do |tag_name| tag = @tenant.tags.find_by(name: tag_name) tag.assign_to_message_object(message_object) tag.assign_to_thread(@message.thread) end + @message.thread.box.tenant.signed_externally_tag!.assign_to_message_object(message_object) if message_object.is_signed MessageObjectDatum.create( message_object: message_object, diff --git a/test/integration/upvs_message_drafts_api_test.rb b/test/integration/upvs_message_drafts_api_test.rb index a905c5b89..483df0422 100644 --- a/test/integration/upvs_message_drafts_api_test.rb +++ b/test/integration/upvs_message_drafts_api_test.rb @@ -854,7 +854,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest assert_equal Message.count, @before_request_messages_count end - test 'does not create message unless object name present' do + test 'can upload valid message with multiples objects' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -881,25 +881,31 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest ') }, { + name: 'Attachment.xml', is_signed: false, mimetype: 'application/xml', object_type: 'ATTACHMENT', content: Base64.encode64('Hello!') + }, + { + name: 'SignedAttachment.xml', + is_signed: true, + mimetype: 'application/xml', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') } ] } post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json - assert_response :unprocessable_entity - - json_response = JSON.parse(response.body) - assert_equal "Objects is not valid, Name can't be blank", json_response['message'] + assert_response :created + assert_not_equal Message.count, @before_request_messages_count - assert_equal Message.count, @before_request_messages_count + assert Message.last.objects.last.tags.include?(tags(:ssd_signed_externally)) end - - test 'does not create message unless object mimetype in white list' do + + test 'can upload valid message with object tags if they exist' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -910,7 +916,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest message_type: 'App.GeneralAgenda', correlation_id: SecureRandom.uuid, sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678' + recipient_uri: 'ico://sk/12345678', }, objects: [ { @@ -923,29 +929,22 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest Všeobecný predmet Všeobecný text -') - }, - { - name: 'Attachment.txt', - is_signed: false, - mimetype: 'text/plain', - object_type: 'ATTACHMENT', - content: Base64.encode64('Hello!') +'), + tags: ['Na podpis'] } - ] + ], + tags: ['Legal', 'Other'] } post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json - assert_response :unprocessable_entity - - json_response = JSON.parse(response.body) - assert_equal 'Objects is not valid, MimeType of Attachment.txt object is disallowed, allowed mimetypes: application/x-eform-xml, application/xml, application/msword, application/pdf, application/vnd.etsi.asic-e+zip, application/vnd.etsi.asic-s+zip, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-xades_zep, application/x-zip-compressed, image/jpg, image/jpeg, image/png, image/tiff', json_response['message'] + assert_response :created + assert_not_equal Message.count, @before_request_messages_count - assert_equal Message.count, @before_request_messages_count + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name) == ['Na podpis'] end - test 'does not create message unless tags with given names exist' do + test 'can upload valid message with object SignatureRequestedFromTags if they exist' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -956,7 +955,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest message_type: 'App.GeneralAgenda', correlation_id: SecureRandom.uuid, sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678' + recipient_uri: 'ico://sk/12345678', }, objects: [ { @@ -969,23 +968,23 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest Všeobecný predmet Všeobecný text -') +'), + tags: ['Na podpis: Another user'] } ], - tags: ['Special'] + tags: ['Legal', 'Other'] } post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json - assert_response :unprocessable_entity - - json_response = JSON.parse(response.body) - assert_equal 'Tag with name Special does not exist', json_response['message'] + assert_response :created + assert_not_equal Message.count, @before_request_messages_count - assert_equal Message.count, @before_request_messages_count + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis: Another user') + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis') end - test 'can upload valid message with object tags if they exist' do + test 'can upload valid message with object SignedByTags if they exist' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -1010,7 +1009,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest Všeobecný predmet Všeobecný text '), - tags: ['Na podpis'] + tags: ['Podpisane: Another user'] } ], tags: ['Legal', 'Other'] @@ -1021,10 +1020,11 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest assert_response :created assert_not_equal Message.count, @before_request_messages_count - assert Upvs::MessageDraft.last.objects.last.tags.map(&:name) == ['Na podpis'] + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane: Another user') + assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane') end - test 'can upload valid message with object SignatureRequestedFromTags if they exist' do + test 'does not create message unless object name present' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -1035,7 +1035,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest message_type: 'App.GeneralAgenda', correlation_id: SecureRandom.uuid, sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + recipient_uri: 'ico://sk/12345678' }, objects: [ { @@ -1048,23 +1048,74 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest Všeobecný predmet Všeobecný text -'), - tags: ['Na podpis: Another user'] +') + }, + { + is_signed: false, + mimetype: 'application/xml', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') } - ], - tags: ['Legal', 'Other'] + ] } 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_not_equal Message.count, @before_request_messages_count + assert_response :unprocessable_entity - assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis: Another user') - assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Na podpis') + json_response = JSON.parse(response.body) + assert_equal "Objects is not valid, Name can't be blank", json_response['message'] + + assert_equal Message.count, @before_request_messages_count end + + test 'does not create message unless object mimetype in white list' 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 +') + }, + { + name: 'Attachment.txt', + is_signed: false, + mimetype: 'text/plain', + object_type: 'ATTACHMENT', + content: Base64.encode64('Hello!') + } + ] + } - test 'can upload valid message with object SignedByTags if they exist' do + post '/api/messages/message_drafts', params: message_params.merge({ token: generate_api_token(sub: @tenant.id, key_pair: @key_pair) }), as: :json + + assert_response :unprocessable_entity + + json_response = JSON.parse(response.body) + assert_equal 'Objects is not valid, MimeType of Attachment.txt object is disallowed, allowed mimetypes: application/x-eform-xml, application/xml, application/msword, application/pdf, application/vnd.etsi.asic-e+zip, application/vnd.etsi.asic-s+zip, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/x-xades_zep, application/x-zip-compressed, image/jpg, image/jpeg, image/png, image/tiff', json_response['message'] + + assert_equal Message.count, @before_request_messages_count + end + + test 'does not create message unless tags with given names exist' do message_params = { type: 'Upvs::MessageDraft', title: 'Všeobecná agenda', @@ -1075,7 +1126,7 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest message_type: 'App.GeneralAgenda', correlation_id: SecureRandom.uuid, sender_uri: 'SSDMainURI', - recipient_uri: 'ico://sk/12345678', + recipient_uri: 'ico://sk/12345678' }, objects: [ { @@ -1088,19 +1139,19 @@ class UpvsMessageDraftsApiTest < ActionDispatch::IntegrationTest Všeobecný predmet Všeobecný text -'), - tags: ['Podpisane: Another user'] +') } ], - tags: ['Legal', 'Other'] + tags: ['Special'] } 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_not_equal Message.count, @before_request_messages_count + assert_response :unprocessable_entity - assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane: Another user') - assert Upvs::MessageDraft.last.objects.last.tags.map(&:name).include?('Podpisane') + json_response = JSON.parse(response.body) + assert_equal 'Tag with name Special does not exist', json_response['message'] + + assert_equal Message.count, @before_request_messages_count end end From 61a94335d52dcaf240f751edcae5e79e8eb975bf Mon Sep 17 00:00:00 2001 From: luciajanikova <19lucia99@gmail.com> Date: Thu, 11 Apr 2024 14:40:36 +0200 Subject: [PATCH 40/40] Remove extra before_action from ApplicationController --- app/controllers/application_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 39678ddf4..24bdd32ee 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,7 +5,6 @@ class ApplicationController < ActionController::Base after_action :verify_authorized after_action :verify_policy_scoped, only: :index if respond_to?(:index) before_action :set_menu_context - before_action :set_sk_locale def pundit_user Current.user