diff --git a/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj b/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj index 09fde8e83..f922e7fef 100644 --- a/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj +++ b/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj @@ -1,10 +1,19 @@ (ns solita.etp.api.palveluvayla - (:require [schema.core :as s] + (:require [ring.util.response :as response] + [schema.core :as s] + [solita.etp.api.response :as api-response] [solita.etp.schema.common :as schema.common] - [solita.etp.schema.energiatodistus :as schema.energiatodistus])) + [solita.etp.schema.energiatodistus :as schema.energiatodistus] + [solita.etp.service.energiatodistus :as service.energiatodistus] + [solita.etp.service.energiatodistus-pdf :as service.energiatodistus-pdf] + [solita.etp.service.energiatodistus-search :as service.energiatodistus-search])) (def accept-language-header {(s/optional-key :accept-language) schema.common/AcceptLanguage}) +(def i-am-paakayttaja {:rooli 2}) +(def versio-2013 ["=" "energiatodistus.versio" 2013]) +(def versio-2018 ["=" "energiatodistus.versio" 2018]) + (def routes ["/energiatodistukset" ["/pdf/:id" ["" {:get {:summary "Hae PDF-muotoinen energiatodistus tunnuksen id:llä" @@ -12,7 +21,24 @@ :header accept-language-header} :responses {200 {:body nil} 404 {:body s/Str}} - :handler (constantly {:status 200}) + :handler (fn [{:keys [db aws-s3-client], + {{:keys [accept-language]} :header} :parameters + {{:keys [id]} :path} :parameters}] + (let [language-preference-order (if accept-language + (->> accept-language + (sort-by second) + (reverse) + (map first)) + ["fi" "sv"])] + (api-response/pdf-response ; Return the first language version that exists if any + (some identity (->> language-preference-order + (map #(service.energiatodistus-pdf/find-energiatodistus-pdf db + aws-s3-client + i-am-paakayttaja + id + %)))) + "energiatodistus.pdf" + (str "Energiatodistus " id " does not exists.")))) :openapi {:responses {200 {:description "PDF-muotoinen energiatodistus" :content {:application/pdf {:schema {:type "string" :format "binary"}}}}}}}}]] @@ -21,27 +47,63 @@ ["" {:get {:summary "Hae energiatodistuksia json-muodossa. Palauttaa jaetut kentät sekä 2013, että 2018 lain mukaisista energiatodistuksista" :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} :responses {200 {:body [schema.energiatodistus/EnergiatodistusForAnyLaatija]}} - :handler (constantly {:status 200})}}] + :handler (fn [{{:keys [query]} :parameters :keys [db]}] + (api-response/get-response + (service.energiatodistus-search/search + db + i-am-paakayttaja + {:where [[["=" "energiatodistus.perustiedot.rakennustunnus" (:rakennustunnus query)]]]} + schema.energiatodistus/EnergiatodistusForAnyLaatija) + (str "Virhe haussa")))}}] ["/:id" {:get {:summary "Hae yksittäinen energiatodistus todistuksen tunnuksen perusteella. Vastaus sisältää vain kentät jotka ovat yhteisiä 2013 ja 2018 versioille." :parameters {:path {:id schema.common/Key}} - :responses {200 {:body [schema.energiatodistus/EnergiatodistusForAnyLaatija]} + :responses {200 {:body schema.energiatodistus/EnergiatodistusForAnyLaatija} 404 {:body s/Str}} - :handler (constantly {:status 200})}}]] + :handler (fn [{{{:keys [id]} :path} :parameters :keys [db]}] + (api-response/get-response + (service.energiatodistus/find-energiatodistus-any-laatija db id) + (str "Energiatodistus " id " does not exists.")))}}]] ["/2013" - ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2013 säännösten mukaan" - :responses {200 {:body [schema.energiatodistus/Energiatodistus2013]}} - :handler (constantly {:status 200})}}] + ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2013 säännösten mukaan" + :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} + :responses {200 {:body [schema.energiatodistus/Energiatodistus2013]}} + :handler (fn [{{:keys [query]} :parameters :keys [db]}] + (api-response/get-response + (service.energiatodistus-search/search + db + i-am-paakayttaja + {:where [[["=" "energiatodistus.perustiedot.rakennustunnus" (:rakennustunnus query)] + versio-2013]]} + schema.energiatodistus/Energiatodistus2013) + (str "Virhe haussa")))}}] ["/:id" {:get {:summary "Hae yksittäinen vuoden 2013 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella" :parameters {:path {:id schema.common/Key}} :responses {200 {:body schema.energiatodistus/Energiatodistus2013} 404 {:body s/Str}} - :handler (constantly {:status 200})}}]] + :handler (fn [{{{:keys [id]} :path} :parameters :keys [db]}] + (api-response/get-response + (-> (service.energiatodistus/find-energiatodistus db id) + (#(if (= (:versio %) 2013) % nil))) + (str "Energiatodistus " id " does not exists.")))}}]] ["/2018" - ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2018 säännösten mukaan" - :responses {200 {:body [schema.energiatodistus/Energiatodistus2018]}} - :handler (constantly {:status 200})}}] + ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2018 säännösten mukaan" + :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} + :responses {200 {:body [schema.energiatodistus/Energiatodistus2018]}} + :handler (fn [{{:keys [query]} :parameters :keys [db]}] + (api-response/get-response + (service.energiatodistus-search/search + db + i-am-paakayttaja + {:where [[["=" "energiatodistus.perustiedot.rakennustunnus" (:rakennustunnus query)] + versio-2018]]} + schema.energiatodistus/Energiatodistus2018) + (str "Virhe haussa")))}}] ["/:id" {:get {:summary "Hae yksittäinen vuoden 2018 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella" :parameters {:path {:id schema.common/Key}} :responses {200 {:body schema.energiatodistus/Energiatodistus2018} 404 {:body s/Str}} - :handler (constantly {:status 200})}}]]]]) + :handler (fn [{{{:keys [id]} :path} :parameters :keys [db]}] + (api-response/get-response + (-> (service.energiatodistus/find-energiatodistus db id) + (#(if (= (:versio %) 2018) % nil))) + (str "Energiatodistus " id " does not exists.")))}}]]]]) diff --git a/etp-backend/src/main/clj/solita/etp/schema/common.clj b/etp-backend/src/main/clj/solita/etp/schema/common.clj index 5ff224163..501060932 100644 --- a/etp-backend/src/main/clj/solita/etp/schema/common.clj +++ b/etp-backend/src/main/clj/solita/etp/schema/common.clj @@ -201,6 +201,7 @@ (schema/defschema WeightedLocale "A single locale with weight for Accept-Language header" [(schema/one (schema/constrained schema/Str #(re-matches #"(?i)([*]|[a-z]{2,3})" %)) "lang") (schema/one (schema/constrained schema/Num #(and (>= % 0) (<= % 1))) "weight")]) + (schema/defschema AcceptLanguage "Define a schema for Accept-Language header. The header can contain multiple locales with preferred weights, for example Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5" [WeightedLocale]) @@ -217,4 +218,4 @@ 2 [(-> parts first parse-lang) (Double/parseDouble (second parts))]))) (defn parse-accept-language [s] - (map parse-locale (str/split s #","))) + (map parse-locale (map str/trim (str/split s #",")))) diff --git a/etp-backend/src/main/clj/solita/etp/security.clj b/etp-backend/src/main/clj/solita/etp/security.clj index c0a569a21..b1d97453a 100644 --- a/etp-backend/src/main/clj/solita/etp/security.clj +++ b/etp-backend/src/main/clj/solita/etp/security.clj @@ -11,6 +11,8 @@ [solita.etp.exception :as exception])) (defn- req->jwt [request] + ;(println (:headers request)) + (println request) (try (jwt/req->verified-jwt-payloads request) (catch Throwable t diff --git a/etp-backend/src/main/clj/solita/etp/service/energiatodistus_pdf.clj b/etp-backend/src/main/clj/solita/etp/service/energiatodistus_pdf.clj index 8430e36f2..5ebde78be 100644 --- a/etp-backend/src/main/clj/solita/etp/service/energiatodistus_pdf.clj +++ b/etp-backend/src/main/clj/solita/etp/service/energiatodistus_pdf.clj @@ -96,8 +96,8 @@ "☒ för en befintlig byggnad, datum för iakttagelser på plats" "☐ för en befintlig byggnad, datum för iakttagelser på plats")} {:f #(some->> % :perustiedot :havainnointikaynti (.format date-formatter))} - {:path [:tulokset :e-luku]} - {:path [:tulokset :e-luokka-rajat :raja-uusi-2018]} + {:path [:tulokset :e-luku]} + {:path [:tulokset :e-luokka-rajat :raja-uusi-2018]} {:path [:laatija-fullname]} {:path [:perustiedot :yritys :nimi]} {:f (fn [_] (.format date-formatter (LocalDate/now)))} @@ -533,41 +533,41 @@ {:path [:huomiot :suositukset-sv]} {:path [:huomiot :lisatietoja-fi]} {:path [:huomiot :lisatietoja-sv]}] - 7 (concat [{:path [:id]} - {:path [:lisamerkintoja-fi]} - {:path [:lisamerkintoja-sv]} - {:path [:lahtotiedot :rakennusvaippa :lampokapasiteetti] :dp 1} - {:path [:lahtotiedot :rakennusvaippa :ilmatilavuus] :dp 1} - {:path [:lahtotiedot :ilmanvaihto :tuloilma-lampotila] :dp 1} - {:path [:lahtotiedot :lammitys :tilat-ja-iv :lampopumppu-tuotto-osuus] :dp 0 :percent? true} - {:path [:lahtotiedot :lammitys :lammin-kayttovesi :lampopumppu-tuotto-osuus] :dp 0 :percent? true} - {:path [:lahtotiedot :lammitys :lampohavio-lammittamaton-tila] :dp 1} - ;; The repeating item below is just to fill in some - ;; value, to keep the next items starting at cell - ;; A11. A10 was expected to be required, but the value - ;; inserted there turned out to be unnecessary. - {:path [:lahtotiedot :lammitys :lampohavio-lammittamaton-tila] :dp 1}] - (flatten (for [i (range 12)] - [{:path [:tulokset :kuukausierittely i :tuotto :aurinkosahko] :dp 0} - {:path [:tulokset :kuukausierittely i :tuotto :tuulisahko] :dp 0} - {:path [:tulokset :kuukausierittely i :tuotto :muusahko] :dp 0} - {:path [:tulokset :kuukausierittely i :tuotto :aurinkolampo] :dp 0} - {:path [:tulokset :kuukausierittely i :tuotto :lampopumppu] :dp 0} - {:path [:tulokset :kuukausierittely i :tuotto :muulampo] :dp 0} - {:path [:tulokset :kuukausierittely i :kulutus :sahko] :dp 0} - {:path [:tulokset :kuukausierittely i :kulutus :lampo] :dp 0} - {:path [:tulokset :kuukausierittely i :hyoty :sahko] :dp 0} - {:path [:tulokset :kuukausierittely i :hyoty :lampo] :dp 0}])) - [{:path [:tulokset :kuukausierittely-summat :tuotto :aurinkosahko] :dp 0} - {:path [:tulokset :kuukausierittely-summat :tuotto :tuulisahko] :dp 0} - {:path [:tulokset :kuukausierittely-summat :tuotto :muusahko] :dp 0} - {:path [:tulokset :kuukausierittely-summat :tuotto :aurinkolampo] :dp 0} - {:path [:tulokset :kuukausierittely-summat :tuotto :lampopumppu] :dp 0} - {:path [:tulokset :kuukausierittely-summat :tuotto :muulampo] :dp 0} - {:path [:tulokset :kuukausierittely-summat :kulutus :sahko] :dp 0} - {:path [:tulokset :kuukausierittely-summat :kulutus :lampo] :dp 0} - {:path [:tulokset :kuukausierittely-summat :hyoty :sahko] :dp 0} - {:path [:tulokset :kuukausierittely-summat :hyoty :lampo] :dp 0}])}) + 7 (concat [{:path [:id]} + {:path [:lisamerkintoja-fi]} + {:path [:lisamerkintoja-sv]} + {:path [:lahtotiedot :rakennusvaippa :lampokapasiteetti] :dp 1} + {:path [:lahtotiedot :rakennusvaippa :ilmatilavuus] :dp 1} + {:path [:lahtotiedot :ilmanvaihto :tuloilma-lampotila] :dp 1} + {:path [:lahtotiedot :lammitys :tilat-ja-iv :lampopumppu-tuotto-osuus] :dp 0 :percent? true} + {:path [:lahtotiedot :lammitys :lammin-kayttovesi :lampopumppu-tuotto-osuus] :dp 0 :percent? true} + {:path [:lahtotiedot :lammitys :lampohavio-lammittamaton-tila] :dp 1} + ;; The repeating item below is just to fill in some + ;; value, to keep the next items starting at cell + ;; A11. A10 was expected to be required, but the value + ;; inserted there turned out to be unnecessary. + {:path [:lahtotiedot :lammitys :lampohavio-lammittamaton-tila] :dp 1}] + (flatten (for [i (range 12)] + [{:path [:tulokset :kuukausierittely i :tuotto :aurinkosahko] :dp 0} + {:path [:tulokset :kuukausierittely i :tuotto :tuulisahko] :dp 0} + {:path [:tulokset :kuukausierittely i :tuotto :muusahko] :dp 0} + {:path [:tulokset :kuukausierittely i :tuotto :aurinkolampo] :dp 0} + {:path [:tulokset :kuukausierittely i :tuotto :lampopumppu] :dp 0} + {:path [:tulokset :kuukausierittely i :tuotto :muulampo] :dp 0} + {:path [:tulokset :kuukausierittely i :kulutus :sahko] :dp 0} + {:path [:tulokset :kuukausierittely i :kulutus :lampo] :dp 0} + {:path [:tulokset :kuukausierittely i :hyoty :sahko] :dp 0} + {:path [:tulokset :kuukausierittely i :hyoty :lampo] :dp 0}])) + [{:path [:tulokset :kuukausierittely-summat :tuotto :aurinkosahko] :dp 0} + {:path [:tulokset :kuukausierittely-summat :tuotto :tuulisahko] :dp 0} + {:path [:tulokset :kuukausierittely-summat :tuotto :muusahko] :dp 0} + {:path [:tulokset :kuukausierittely-summat :tuotto :aurinkolampo] :dp 0} + {:path [:tulokset :kuukausierittely-summat :tuotto :lampopumppu] :dp 0} + {:path [:tulokset :kuukausierittely-summat :tuotto :muulampo] :dp 0} + {:path [:tulokset :kuukausierittely-summat :kulutus :sahko] :dp 0} + {:path [:tulokset :kuukausierittely-summat :kulutus :lampo] :dp 0} + {:path [:tulokset :kuukausierittely-summat :hyoty :sahko] :dp 0} + {:path [:tulokset :kuukausierittely-summat :hyoty :lampo] :dp 0}])}) (defn fill-xlsx-template [{:keys [versio] :as complete-energiatodistus} kieli draft?] (with-open [is (-> xlsx-template-paths @@ -614,18 +614,18 @@ dir (.getParent file) result-pdf (str/replace path #".xlsx$" ".pdf") {:keys [exit err] :as sh-result} (libreoffice/run-with-args - "--convert-to" - "pdf" - filename - :dir - dir)] - (if (and (zero? exit) (str/blank? err) (.exists (io/as-file result-pdf))) + "--convert-to" + "pdf" + filename + :dir + dir)] + (if (and (zero? exit) (.exists (io/as-file result-pdf))) result-pdf (throw (ex-info "XLSX to PDF conversion failed" - (assoc sh-result - :type :xlsx-pdf-conversion-failure - :xlsx filename - :pdf-result? (.exists (io/as-file result-pdf)))))))) + (assoc sh-result + :type :xlsx-pdf-conversion-failure + :xlsx filename + :pdf-result? (.exists (io/as-file result-pdf)))))))) (defn input-stream->bytes [is] (with-open [is is @@ -668,11 +668,11 @@ (get kieli) io/resource io/input-stream)) - overlay (doto (Overlay.) - (.setInputFile pdf-path) - (.setDefaultOverlayPDF watermark) - (.setOverlayPosition Overlay$Position/FOREGROUND)) - result (.overlay overlay (HashMap.))] + overlay (doto (Overlay.) + (.setInputFile pdf-path) + (.setDefaultOverlayPDF watermark) + (.setOverlayPosition Overlay$Position/FOREGROUND)) + result (.overlay overlay (HashMap.))] (.save result pdf-path) pdf-path)) @@ -682,8 +682,8 @@ (io/delete-file xlsx-path) (add-e-luokka-image pdf-path (-> complete-energiatodistus - :tulokset - :e-luokka) + :tulokset + :e-luokka) (:versio complete-energiatodistus)) (if draft? @@ -697,14 +697,16 @@ is)) (defn find-existing-pdf [aws-s3-client id kieli] - (file-service/file-exists? aws-s3-client (energiatodistus-service/file-key id kieli)) + (file-service/file-exists? aws-s3-client (energiatodistus-service/file-key id kieli)) (->> (energiatodistus-service/file-key id kieli) (file-service/find-file aws-s3-client) io/input-stream)) (defn find-energiatodistus-pdf [db aws-s3-client whoami id kieli] (when-let [{:keys [allekirjoitusaika] :as complete-energiatodistus} - (complete-energiatodistus-service/find-complete-energiatodistus db whoami id)] + (-> (complete-energiatodistus-service/find-complete-energiatodistus db whoami id) + (#(when (or (= (-> % :perustiedot :kieli) 2) + (contains? (-> % :perustiedot :kieli energiatodistus-service/language-id->codes set) kieli)) %)))] (if allekirjoitusaika (find-existing-pdf aws-s3-client id kieli) (generate-pdf-as-input-stream complete-energiatodistus kieli true)))) @@ -733,28 +735,28 @@ (when-let [{:keys [laatija-fullname versio] :as complete-energiatodistus} (complete-energiatodistus-service/find-complete-energiatodistus db id)] (do-when-signing - complete-energiatodistus - #(let [pdf-path (generate-pdf-as-file complete-energiatodistus language false) - signable-pdf-path (str/replace pdf-path #".pdf" "-signable.pdf") - signature-png-path (str/replace pdf-path #".pdf" "-signature.png") - _ (signature-as-png signature-png-path laatija-fullname) - signable-pdf-path (puumerkki/add-watermarked-signature-space - pdf-path - signable-pdf-path - laatija-fullname - signature-png-path - 75 - (case versio 2013 648 2018 666)) - signable-pdf-data (puumerkki/read-file signable-pdf-path) - digest (puumerkki/compute-base64-pkcs signable-pdf-data) - key (energiatodistus-service/file-key id language)] - (file-service/upsert-file-from-bytes aws-s3-client - key - signable-pdf-data) - (io/delete-file pdf-path) - (io/delete-file signable-pdf-path) - (io/delete-file signature-png-path) - {:digest digest})))) + complete-energiatodistus + #(let [pdf-path (generate-pdf-as-file complete-energiatodistus language false) + signable-pdf-path (str/replace pdf-path #".pdf" "-signable.pdf") + signature-png-path (str/replace pdf-path #".pdf" "-signature.png") + _ (signature-as-png signature-png-path laatija-fullname) + signable-pdf-path (puumerkki/add-watermarked-signature-space + pdf-path + signable-pdf-path + laatija-fullname + signature-png-path + 75 + (case versio 2013 648 2018 666)) + signable-pdf-data (puumerkki/read-file signable-pdf-path) + digest (puumerkki/compute-base64-pkcs signable-pdf-data) + key (energiatodistus-service/file-key id language)] + (file-service/upsert-file-from-bytes aws-s3-client + key + signable-pdf-data) + (io/delete-file pdf-path) + (io/delete-file signable-pdf-path) + (io/delete-file signature-png-path) + {:digest digest})))) (defn comparable-name [s] (-> s @@ -769,20 +771,20 @@ (when-not (= (comparable-name last-name) (comparable-name surname)) (log/warn "Last name from certificate did not match with whoami info when signing energiatodistus PDF.") (exception/throw-ex-info! - {:type :name-does-not-match - :message (format "Last names did not match. Whoami has '%s' and certificate has '%s'" - last-name - surname)})))) + {:type :name-does-not-match + :message (format "Last names did not match. Whoami has '%s' and certificate has '%s'" + last-name + surname)})))) (defn validate-not-after! [^Date now certificate] (let [not-after (-> certificate certificates/not-after)] (when (.after now not-after) (log/warn "Signing certificate validity ended at" not-after) (exception/throw-ex-info! - {:type :expired-signing-certificate - :message (format "ET Signing certificate expired at %s, would have needed to be valid at least until %s" - not-after - now)})))) + {:type :expired-signing-certificate + :message (format "ET Signing certificate expired at %s, would have needed to be valid at least until %s" + not-after + now)})))) (defn validate-certificate! [last-name now certificate-str] (let [certificate (certificates/pem-str->certificate certificate-str)] diff --git a/etp-backend/src/test/clj/solita/etp/api/palveluvayla_test.clj b/etp-backend/src/test/clj/solita/etp/api/palveluvayla_test.clj new file mode 100644 index 000000000..23b33882d --- /dev/null +++ b/etp-backend/src/test/clj/solita/etp/api/palveluvayla_test.clj @@ -0,0 +1,132 @@ +(ns solita.etp.api.palveluvayla-test + (:require [clojure.java.io :as io] + [clojure.test :as t] + [jsonista.core :as j] + [solita.etp.schema.energiatodistus :as schema.energiatodistus] + [solita.etp.test-data.generators :as generators] + [solita.etp.test-data.energiatodistus :as test-data.energiatodistus] + [solita.etp.test-data.laatija :as test-data.laatija] + [solita.etp.test-system :as ts] + [ring.mock.request :as mock] + [solita.etp.service.file :as file]) + (:import (org.apache.commons.io IOUtils))) + +(t/use-fixtures :each ts/fixture) + +(def palveluvayla-basepath "/api/palveluvayla/energiatodistukset") + +(t/deftest test-palveluvayla-api + (let [laatija-id (first (keys (test-data.laatija/generate-and-insert! 1))) + rakennustunnus-1 (generators/generate-rakennustunnus) + rakennustunnus-2 (generators/generate-rakennustunnus) + todistus-2013-fi (-> (test-data.energiatodistus/generate-add 2013 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 0)) + todistus-2018-fi (-> (test-data.energiatodistus/generate-add 2018 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 0)) + todistus-2013-sv (-> (test-data.energiatodistus/generate-add 2013 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 1)) + todistus-2018-sv (-> (test-data.energiatodistus/generate-add 2018 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 1)) + todistus-2013-multilingual (-> (test-data.energiatodistus/generate-add 2013 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 2)) + todistus-2018-multilingual (-> (test-data.energiatodistus/generate-add 2018 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-1) (assoc-in [:perustiedot :kieli] 2)) + todistus-2013-rakennustunnus-2 (-> (test-data.energiatodistus/generate-add 2013 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-2)) + todistus-2018-rakennustunnus-2 (-> (test-data.energiatodistus/generate-add 2018 true) (assoc-in [:perustiedot :rakennustunnus] rakennustunnus-2)) + [todistus-2013-fi-id todistus-2018-fi-id todistus-2013-sv-id todistus-2018-sv-id todistus-2013-multilingual-id todistus-2018-multilingual-id todistus-2013-rakennustunnus-2-id todistus-2018-rakennustunnus-2-id] (test-data.energiatodistus/insert! [todistus-2013-fi todistus-2018-fi todistus-2013-sv todistus-2018-sv todistus-2013-multilingual todistus-2018-multilingual todistus-2013-rakennustunnus-2 todistus-2018-rakennustunnus-2] laatija-id)] + ; LibreOffice is quite slow so do signing in parallel + (doall (pmap #(test-data.energiatodistus/sign! % laatija-id false) [todistus-2013-fi-id todistus-2018-fi-id todistus-2013-sv-id todistus-2018-sv-id todistus-2013-multilingual-id todistus-2018-multilingual-id todistus-2013-rakennustunnus-2-id todistus-2018-rakennustunnus-2-id])) + (t/testing "Fetching energiatodistus basic information by id returns it" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/any/%s" todistus-2013-fi-id))))) + response-body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= todistus-2013-fi-id (:id response-body))) + (schema-tools.coerce/coerce response-body schema.energiatodistus/EnergiatodistusForAnyLaatija schema-tools.coerce/json-coercion-matcher))) + (t/testing "Fetching energiatodistus by id returns it when fetching correct version" + (t/testing "when fetching 2013" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2013/%s" todistus-2013-fi-id))))) + response-body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= todistus-2013-fi-id (:id response-body))) + (schema-tools.coerce/coerce response-body schema.energiatodistus/Energiatodistus2013 schema-tools.coerce/json-coercion-matcher)))) + (t/testing "when fetching 2018" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2018/%s" todistus-2018-fi-id))))) + response-body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= todistus-2018-fi-id (:id response-body))) + (schema-tools.coerce/coerce response-body schema.energiatodistus/Energiatodistus2018 schema-tools.coerce/json-coercion-matcher))) + (t/testing "Fetching wrong version by id returns 404" + (t/testing "for 2013" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2013/%s" todistus-2018-fi-id)))))] + (t/is (= 404 (:status response))))) + (t/testing "for 2018" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2018/%s" todistus-2013-fi-id)))))] + (t/is (= 404 (:status response)))))) + (t/testing "Fetching pdf" + (t/testing "for version 2013" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2013-fi-id))))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2013-fi-id "fi"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "for version 2018" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-fi-id))))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-fi-id "fi"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "Accept-language is honored" + (t/testing "when asking for existing Finnish pdf" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-multilingual-id))) + (mock/header "Accept-Language" "fi"))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-multilingual-id "fi"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "when asking for existing Swedish pdf" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-multilingual-id))) + (mock/header "Accept-Language" "sv"))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-multilingual-id "sv"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "when prioritising Swedish pdf" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-multilingual-id))) + (mock/header "Accept-Language" "fi;q=0.5, sv"))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-multilingual-id "sv"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "when prioritising Finnish pdf" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-multilingual-id))) + (mock/header "Accept-Language" "fi, sv;q=0.5"))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-multilingual-id "fi"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf))))) + (t/testing "Asking for a multilingual pdf without Accept-Language returns Finnish pdf" + (let [response (ts/handler (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-multilingual-id)))) + body (-> response :body io/input-stream) + correct-pdf (file/find-file ts/*aws-s3-client* (format "energiatodistukset/energiatodistus-%s-%s" todistus-2018-multilingual-id "fi"))] + (t/is (= 200 (:status response))) + (t/is (IOUtils/contentEquals body correct-pdf)))) + (t/testing "Asking for pdf in non-existing language returns 404" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/pdf/%s" todistus-2018-fi-id))) + (mock/header "Accept-Language" "sv")))] + (t/is (= 404 (:status response)))))) + (t/testing "Searching for basic information by rakennustunnus returns all versions" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/any?rakennustunnus=%s" rakennustunnus-1))))) + body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= 6 (count body))) + (t/is (= #{todistus-2013-fi-id todistus-2018-fi-id todistus-2013-sv-id todistus-2018-sv-id todistus-2013-multilingual-id todistus-2018-multilingual-id} (set (map :id body)))) + (schema-tools.coerce/coerce body [schema.energiatodistus/EnergiatodistusForAnyLaatija] schema-tools.coerce/json-coercion-matcher))) + (t/testing "Searching for specific version by rakennustunnus returns only that version" + (t/testing "when searching for 2013" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2013?rakennustunnus=%s" rakennustunnus-1))))) + body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= 3 (count body))) + (t/is (= #{todistus-2013-fi-id todistus-2013-sv-id todistus-2013-multilingual-id} (set (map :id body)))) + (schema-tools.coerce/coerce body [schema.energiatodistus/Energiatodistus2013] schema-tools.coerce/json-coercion-matcher))) + (t/testing "when searching for 2018" + (let [response (ts/handler (-> (mock/request :get (str palveluvayla-basepath (format "/json/2018?rakennustunnus=%s" rakennustunnus-1))))) + body (j/read-value (:body response) j/keyword-keys-object-mapper)] + (t/is (= 200 (:status response))) + (t/is (= 3 (count body))) + (t/is (= #{todistus-2018-fi-id todistus-2018-sv-id todistus-2018-multilingual-id} (set (map :id body)))) + (schema-tools.coerce/coerce body [schema.energiatodistus/Energiatodistus2018] schema-tools.coerce/json-coercion-matcher)))))) \ No newline at end of file diff --git a/etp-backend/src/test/clj/solita/etp/test_data/generators.clj b/etp-backend/src/test/clj/solita/etp/test_data/generators.clj index e00241be4..08d6c735e 100644 --- a/etp-backend/src/test/clj/solita/etp/test_data/generators.clj +++ b/etp-backend/src/test/clj/solita/etp/test_data/generators.clj @@ -34,41 +34,49 @@ (defn generate-password [_] (apply str (take (+ 8 (rand-int 192)) (repeatedly random-printable-ascii-char)))) -(def kuukausierittely {:tuotto {:aurinkosahko 1M - :tuulisahko 2M - :aurinkolampo nil - :muulampo 3.5M - :muusahko 4M - :lampopumppu 5.6789M} - :kulutus {:sahko nil - :lampo 6.789M}}) +(def kuukausierittely {:tuotto {:aurinkosahko 1M + :tuulisahko 2M + :aurinkolampo nil + :muulampo 3.5M + :muusahko 4M + :lampopumppu 5.6789M} + :kulutus {:sahko nil + :lampo 6.789M}}) + +(defn- rakennustunnus-generator [_] + (let [number-part (apply str (repeatedly 9 #(rand-nth "0123456789"))) + checksum (common/henkilotunnus-checksum number-part)] + (str number-part checksum))) + +(defn generate-rakennustunnus [] + (rakennustunnus-generator nil)) (def generators - {common/Num1 (test-generators/choose 0 1) - common/NonNegative test-generators/nat - common/IntNonNegative test-generators/nat - common/Year (test-generators/choose 2018 2025) - common/Henkilotunnus (g/always "130200A892S") - common/Ytunnus (g/always "0000000-0") - common/Verkkolaskuosoite (g/always "003712345671") - common/Date (g/always (java.time.LocalDate/now)) - common/Instant (g/always (java.time.Instant/now)) - common/Url (g/always "https://example.com") + {common/Num1 (test-generators/choose 0 1) + common/NonNegative test-generators/nat + common/IntNonNegative test-generators/nat + common/Year (test-generators/choose 2018 2025) + common/Henkilotunnus (g/always "130200A892S") + common/Ytunnus (g/always "0000000-0") + common/Verkkolaskuosoite (g/always "003712345671") + common/Date (g/always (java.time.LocalDate/now)) + common/Instant (g/always (java.time.Instant/now)) + common/Url (g/always "https://example.com") - geo/Maa (test-generators/elements ["FI" "SV"]) - geo/PostinumeroFI (test-generators/elements ["00100" "33100"]) + geo/Maa (test-generators/elements ["FI" "SV"]) + geo/PostinumeroFI (test-generators/elements ["00100" "33100"]) - laatija/MuutToimintaalueet (test-generators/list-distinct - (test-generators/elements (range 18)) - {:min-elements 0 - :max-elements 5}) + laatija/MuutToimintaalueet (test-generators/list-distinct + (test-generators/elements (range 18)) + {:min-elements 0 + :max-elements 5}) - common/Rakennustunnus (g/always "1035150826") + common/Rakennustunnus (test-generators/fmap rakennustunnus-generator test-generators/boolean) energiatodistus/YritysPostinumero (g/always "33100") energiatodistus/OptionalKuukausierittely (test-generators/one-of - [(g/always (vec (repeat 12 kuukausierittely))) - (g/always [])]) - solita.etp.schema.kayttaja/Password (test-generators/fmap generate-password test-generators/boolean)}) + [(g/always (vec (repeat 12 kuukausierittely))) + (g/always [])]) + solita.etp.schema.kayttaja/Password (test-generators/fmap generate-password test-generators/boolean)}) (defn complete ([x schema]