From 1d99e3f5f060621de8964e78747d84305a95cea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Fri, 8 Nov 2024 14:27:56 +0000 Subject: [PATCH 1/5] chore(j-s): Fix DatePicker rendering issue (#16755) * Update react-select and framer-motion * Remove unused dependencies * Add apollo gateway * Add mobx --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/auth-admin-web/specs/index.spec.tsx | 1 - package.json | 7 +- yarn.lock | 567 +++++++---------------- 3 files changed, 165 insertions(+), 410 deletions(-) diff --git a/apps/auth-admin-web/specs/index.spec.tsx b/apps/auth-admin-web/specs/index.spec.tsx index cf2083f1257f..360d006c5bd6 100644 --- a/apps/auth-admin-web/specs/index.spec.tsx +++ b/apps/auth-admin-web/specs/index.spec.tsx @@ -1,6 +1,5 @@ import React from 'react' import { render } from '@testing-library/react' -import 'whatwg-fetch' import Index from '../pages/index' jest.mock('next/router', () => ({ useRouter: () => ({ push: () => jest.fn() }), diff --git a/package.json b/package.json index dd6865be632e..655d9542310a 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "@contentful/field-editor-reference": "5.20.0", "@contentful/field-editor-single-line": "1.1.8", "@contentful/forma-36-react-components": "3.78.4", - "@contentful/forma-36-tokens": "0.10.1", "@contentful/node-apps-toolkit": "2.0.2", "@contentful/react-apps-toolkit": "1.2.15", "@contentful/rich-text-from-markdown": "15.16.6", @@ -93,7 +92,6 @@ "@dnd-kit/core": "6.1.0", "@dnd-kit/sortable": "8.0.0", "@elastic/elasticsearch": "7.7.1", - "@formatjs/cli": "4.2.27", "@formatjs/intl-datetimeformat": "4.1.6", "@formatjs/intl-locale": "2.4.33", "@formatjs/intl-numberformat": "7.1.5", @@ -185,7 +183,7 @@ "font-awesome": "4.7.0", "form-data": "3.0.0", "formik": "2.2.9", - "framer-motion": "11.11.9", + "framer-motion": "11.11.11", "fridagar": "^3.2.0", "fuse.js": "7.0.0", "glob": "10.3.3", @@ -266,7 +264,7 @@ "react-popper": "2.3.0", "react-remove-scroll": "2.5.6", "react-router-dom": "6.11.2", - "react-select": "5.7.3", + "react-select": "5.8.2", "react-table": "7.7.0", "react-toastify": "6.0.8", "react-top-loading-bar": "2.3.1", @@ -305,7 +303,6 @@ "unified": "9.2.0", "uuidv4": "6.0.8", "vm-browserify": "1.1.2", - "whatwg-fetch": "3.6.2", "winston": "3.7.2", "winston-cloudwatch": "3.1.1", "winston-transport": "4.6.0", diff --git a/yarn.lock b/yarn.lock index a6fc3abd28bd..3c8a12cb1d90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -324,18 +324,32 @@ __metadata: linkType: hard "@apollo/composition@npm:^2.1.1": - version: 2.1.3 - resolution: "@apollo/composition@npm:2.1.3" + version: 2.9.3 + resolution: "@apollo/composition@npm:2.9.3" dependencies: - "@apollo/federation-internals": ^2.1.3 - "@apollo/query-graphs": ^2.1.3 + "@apollo/federation-internals": 2.9.3 + "@apollo/query-graphs": 2.9.3 peerDependencies: graphql: ^16.5.0 - checksum: c63f443540a8af2cf9f11468a447334de94dacfac2571d7cf5c903f69887b9850ebe25ccc0a19353ce1ce5de8f4cad7f4b26e63f4c454e254f0e1f2f6cdd7fb9 + checksum: 58b00da585d378eb42bf9e1e4cf355d2cb5c096848fce76cc473c459debe846ca44f69d921b3ea51eca21af438ce9e5f22f27e69d97dfb3767e3d3e479229c09 languageName: node linkType: hard -"@apollo/federation-internals@npm:^2.1.1, @apollo/federation-internals@npm:^2.1.3": +"@apollo/federation-internals@npm:2.9.3": + version: 2.9.3 + resolution: "@apollo/federation-internals@npm:2.9.3" + dependencies: + "@types/uuid": ^9.0.0 + chalk: ^4.1.0 + js-levenshtein: ^1.1.6 + uuid: ^9.0.0 + peerDependencies: + graphql: ^16.5.0 + checksum: 1227e9c63d7e5dc8aa935a248959103675fe163423ec05d09fbbe8fa9434c040d0280248091978708ca97b0766178ac2e5f88892a20dcecf7600065924bae59c + languageName: node + linkType: hard + +"@apollo/federation-internals@npm:^2.1.1": version: 2.1.3 resolution: "@apollo/federation-internals@npm:2.1.3" dependencies: @@ -399,45 +413,70 @@ __metadata: languageName: node linkType: hard -"@apollo/query-graphs@npm:^2.1.3": - version: 2.1.3 - resolution: "@apollo/query-graphs@npm:2.1.3" +"@apollo/protobufjs@npm:1.2.7": + version: 1.2.7 + resolution: "@apollo/protobufjs@npm:1.2.7" dependencies: - "@apollo/federation-internals": ^2.1.3 + "@protobufjs/aspromise": ^1.1.2 + "@protobufjs/base64": ^1.1.2 + "@protobufjs/codegen": ^2.0.4 + "@protobufjs/eventemitter": ^1.1.0 + "@protobufjs/fetch": ^1.1.0 + "@protobufjs/float": ^1.0.2 + "@protobufjs/inquire": ^1.1.0 + "@protobufjs/path": ^1.1.2 + "@protobufjs/pool": ^1.1.0 + "@protobufjs/utf8": ^1.1.0 + "@types/long": ^4.0.0 + long: ^4.0.0 + bin: + apollo-pbjs: bin/pbjs + apollo-pbts: bin/pbts + checksum: e01a33984ae06d6679f6796bb44e55260112ddd090ebc9f87d3f952c45153dd5df5c91ac4bf91ba60fb72ff8c1218059ce4bf8bb2eb08c5049c783de0098eec0 + languageName: node + linkType: hard + +"@apollo/query-graphs@npm:2.9.3": + version: 2.9.3 + resolution: "@apollo/query-graphs@npm:2.9.3" + dependencies: + "@apollo/federation-internals": 2.9.3 deep-equal: ^2.0.5 - ts-graphviz: ^0.16.0 + ts-graphviz: ^1.5.4 + uuid: ^9.0.0 peerDependencies: graphql: ^16.5.0 - checksum: 919029ce34510d1d8a747d803b8cde603ddd56f947c5bc2676eba7fd3a2f427112bffcdf19f79f71c14f19cf846f33688324876dded06c38cc51d03df8038f70 + checksum: f83c0c545f46706379e04503abc1b9be9c8b11eaa78d75d54254eebfb8417ac7304c0df3b56f198d58a8c35947425bf9a691ff5391812d564602710d8c56f848 languageName: node linkType: hard "@apollo/query-planner@npm:^2.1.1": - version: 2.1.3 - resolution: "@apollo/query-planner@npm:2.1.3" + version: 2.9.3 + resolution: "@apollo/query-planner@npm:2.9.3" dependencies: - "@apollo/federation-internals": ^2.1.3 - "@apollo/query-graphs": ^2.1.3 + "@apollo/federation-internals": 2.9.3 + "@apollo/query-graphs": 2.9.3 + "@apollo/utils.keyvaluecache": ^2.1.0 chalk: ^4.1.0 deep-equal: ^2.0.5 - pretty-format: ^28.0.0 + pretty-format: ^29.0.0 peerDependencies: graphql: ^16.5.0 - checksum: e24fc504f944b7224278a8b528e5e5a7619955f0caa3e8ed2f65ca744bd26c2a60fe714baf378ca757ec372325abad1fb82154462ce7e497be7922bfbbaa81e7 + checksum: 65aaded0777e0ced4f9bd7bb770d2f28df2dc8661355f312fae74a942b11f2d6a42cf4101347f6f1a06f034c81b6b562501edbd4a00a615d4ab41287b43d4490 languageName: node linkType: hard "@apollo/server-gateway-interface@npm:^1.0.2": - version: 1.0.4 - resolution: "@apollo/server-gateway-interface@npm:1.0.4" + version: 1.1.1 + resolution: "@apollo/server-gateway-interface@npm:1.1.1" dependencies: - "@apollo/usage-reporting-protobuf": ^4.0.0 - "@apollo/utils.fetcher": ^1.0.0 - "@apollo/utils.keyvaluecache": ^1.0.1 - "@apollo/utils.logger": ^1.0.0 + "@apollo/usage-reporting-protobuf": ^4.1.1 + "@apollo/utils.fetcher": ^2.0.0 + "@apollo/utils.keyvaluecache": ^2.1.0 + "@apollo/utils.logger": ^2.0.0 peerDependencies: graphql: 14.x || 15.x || 16.x - checksum: 1931a038d5ad4331d9794143d91d579bdb136604b4df8feeac8e9b1653cc935c1674b803120fcacff3748bdd2f2e5dbfd99ec46fc4329507fecff99379ba283c + checksum: b85ca1682258f6d022b49acf4b6cb8147a4cc38fcc0e68fa3ca6a00843bee5b84f8317af26cbe3e6a41ede6990eb7eb733c50a123441a1efab56572b7d0fd6dc languageName: node linkType: hard @@ -453,12 +492,12 @@ __metadata: languageName: node linkType: hard -"@apollo/usage-reporting-protobuf@npm:^4.0.0": - version: 4.0.0 - resolution: "@apollo/usage-reporting-protobuf@npm:4.0.0" +"@apollo/usage-reporting-protobuf@npm:^4.1.1": + version: 4.1.1 + resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1" dependencies: - "@apollo/protobufjs": 1.2.6 - checksum: 86a0d392932d8103bc14d0900dcd5d209eedf8aeb598c9c54fb8aa44bda59f3fab4c03f1358acdbf9c523858c24ecad12677a45e46c17a259e21f18c13a7bf49 + "@apollo/protobufjs": 1.2.7 + checksum: 899f13cfb57cfe4320e50fff84254604c25538620aa5a56bad06fb4fc929a8842237b376a5ab6d82800d9aceacc8e79ccae01a1c11e85456d4a9ed50a6fe40ee languageName: node linkType: hard @@ -481,13 +520,20 @@ __metadata: languageName: node linkType: hard -"@apollo/utils.fetcher@npm:^1.0.0, @apollo/utils.fetcher@npm:^1.1.0": +"@apollo/utils.fetcher@npm:^1.1.0": version: 1.1.1 resolution: "@apollo/utils.fetcher@npm:1.1.1" checksum: 7f2284cfddeb59775dc471d20d0a447049f32c069df429ac4aa7b733bd341f6cc9b755fd37226a73b00a4c9fa7f598cb2f5ce0a98dc22a2ce9217cc6947f5f09 languageName: node linkType: hard +"@apollo/utils.fetcher@npm:^2.0.0": + version: 2.0.1 + resolution: "@apollo/utils.fetcher@npm:2.0.1" + checksum: 9cb0e759f61c6d2bfe3319eeb273e30e52212fa79e59da0ae29ac96fa735cb1bb333b6a97c39df62e36acb0c4a15d62d1bc6b0027a9ca41f5d1c995561b668f2 + languageName: node + linkType: hard + "@apollo/utils.isnodelike@npm:^1.1.0": version: 1.1.0 resolution: "@apollo/utils.isnodelike@npm:1.1.0" @@ -516,6 +562,16 @@ __metadata: languageName: node linkType: hard +"@apollo/utils.keyvaluecache@npm:^2.1.0": + version: 2.1.1 + resolution: "@apollo/utils.keyvaluecache@npm:2.1.1" + dependencies: + "@apollo/utils.logger": ^2.0.1 + lru-cache: ^7.14.1 + checksum: c49b297a30ef02336d605a9fd342443eb9ea7ea36b9331a2cd5f8cb1613656e5d06b4445ca09784b18c12b417bca17fe09d40e25196266e2a734da3200d27ea5 + languageName: node + linkType: hard + "@apollo/utils.keyvaluecache@npm:^3.0.0": version: 3.0.0 resolution: "@apollo/utils.keyvaluecache@npm:3.0.0" @@ -533,6 +589,13 @@ __metadata: languageName: node linkType: hard +"@apollo/utils.logger@npm:^2.0.0, @apollo/utils.logger@npm:^2.0.1": + version: 2.0.1 + resolution: "@apollo/utils.logger@npm:2.0.1" + checksum: f975c81fcc7e54669b975031349f292930dc4cc3dd6bdc58bc7fe2159e0398a7d18b28860ee324c23722b005848e258094a143d20f6989fde5837379240b0066 + languageName: node + linkType: hard + "@apollo/utils.logger@npm:^3.0.0": version: 3.0.0 resolution: "@apollo/utils.logger@npm:3.0.0" @@ -3810,7 +3873,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.0, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.3, @babel/parser@npm:^7.19.4": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.3, @babel/parser@npm:^7.19.4": version: 7.19.4 resolution: "@babel/parser@npm:7.19.4" bin: @@ -8110,7 +8173,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.0, @babel/types@npm:^7.12.11, @babel/types@npm:^7.16.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.10, @babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.19.0, @babel/types@npm:^7.19.3, @babel/types@npm:^7.19.4, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.11, @babel/types@npm:^7.16.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.10, @babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.19.0, @babel/types@npm:^7.19.3, @babel/types@npm:^7.19.4, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.19.4 resolution: "@babel/types@npm:7.19.4" dependencies: @@ -10096,7 +10159,7 @@ __metadata: languageName: node linkType: hard -"@contentful/forma-36-tokens@npm:0.10.1, @contentful/forma-36-tokens@npm:^0.10.1": +"@contentful/forma-36-tokens@npm:^0.10.1": version: 0.10.1 resolution: "@contentful/forma-36-tokens@npm:0.10.1" checksum: f5d0da85c8737e23ba56b47a7c95a18459df7f8219f42371526cca7e598dc3c3048186e50513ba692412915307e52a49673b269e794c0b24bc41334cd950a921 @@ -11786,32 +11849,6 @@ __metadata: languageName: node linkType: hard -"@formatjs/cli@npm:4.2.27": - version: 4.2.27 - resolution: "@formatjs/cli@npm:4.2.27" - dependencies: - "@formatjs/icu-messageformat-parser": 2.0.7 - "@formatjs/ts-transformer": 3.4.5 - "@types/json-stable-stringify": ^1.0.32 - "@types/lodash": ^4.14.150 - "@types/node": 14 - "@vue/compiler-core": ^3.0.0 - "@vue/compiler-sfc": ^3.0.5 - chalk: ^4.0.0 - commander: 8 - fast-glob: ^3.2.4 - fs-extra: ^9.0.0 - json-stable-stringify: ^1.0.1 - lodash: ^4.17.15 - loud-rejection: ^2.2.0 - tslib: ^2.1.0 - typescript: ^4.0 - bin: - formatjs: bin/formatjs - checksum: 136e7ebfe24b143e0b13c2a2a0200fcc7a5ed6f8a0b554e93fa667c47d0bc2514287e1cfbee67d1e6a85b34d7191c4d27138186f60b30a1bf3c9732f3dc26614 - languageName: node - linkType: hard - "@formatjs/ecma402-abstract@npm:1.14.3": version: 1.14.3 resolution: "@formatjs/ecma402-abstract@npm:1.14.3" @@ -11870,17 +11907,6 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-messageformat-parser@npm:2.0.7": - version: 2.0.7 - resolution: "@formatjs/icu-messageformat-parser@npm:2.0.7" - dependencies: - "@formatjs/ecma402-abstract": 1.9.4 - "@formatjs/icu-skeleton-parser": 1.2.8 - tslib: ^2.1.0 - checksum: 19c13e85cf6921c7414bafc1c75df210b9840973240ba75dff995f9fdb8aff32d42b45ddea273900b3ad1c64cd91424b9ca2ddfa1086707db52f12373fd4d44c - languageName: node - linkType: hard - "@formatjs/icu-skeleton-parser@npm:1.2.13": version: 1.2.13 resolution: "@formatjs/icu-skeleton-parser@npm:1.2.13" @@ -11891,16 +11917,6 @@ __metadata: languageName: node linkType: hard -"@formatjs/icu-skeleton-parser@npm:1.2.8": - version: 1.2.8 - resolution: "@formatjs/icu-skeleton-parser@npm:1.2.8" - dependencies: - "@formatjs/ecma402-abstract": 1.9.4 - tslib: ^2.1.0 - checksum: a908fda7451ee82a3369539f4f979a7fce0bd6a7ffd40207744824c335601d2e00ca5bc390d5e20e17683db568e55da373b7bc1b64ba75727e9ea2f43fc873f8 - languageName: node - linkType: hard - "@formatjs/intl-datetimeformat@npm:3.2.11": version: 3.2.11 resolution: "@formatjs/intl-datetimeformat@npm:3.2.11" @@ -12113,23 +12129,6 @@ __metadata: languageName: node linkType: hard -"@formatjs/ts-transformer@npm:3.4.5": - version: 3.4.5 - resolution: "@formatjs/ts-transformer@npm:3.4.5" - dependencies: - "@formatjs/icu-messageformat-parser": 2.0.7 - chalk: ^4.1.1 - tslib: ^2.1.0 - peerDependencies: - ts-jest: 27 - typescript: 4 - peerDependenciesMeta: - ts-jest: - optional: true - checksum: f3e708f4355fc45cc3237cd3f9c65b5d7753192fc57d50b48a75c4450a3b48e5af86e928cccdbd96d0cffd79fc2d737fe6a51e2e52a173b9be48f369f08ea65d - languageName: node - linkType: hard - "@formatjs/ts-transformer@npm:3.5.0": version: 3.5.0 resolution: "@formatjs/ts-transformer@npm:3.5.0" @@ -13600,15 +13599,6 @@ __metadata: languageName: node linkType: hard -"@jest/schemas@npm:^28.1.3": - version: 28.1.3 - resolution: "@jest/schemas@npm:28.1.3" - dependencies: - "@sinclair/typebox": ^0.24.1 - checksum: 3cf1d4b66c9c4ffda58b246de1ddcba8e6ad085af63dccdf07922511f13b68c0cc480a7bc620cb4f3099a6f134801c747e1df7bfc7a4ef4dceefbdea3e31e1de - languageName: node - linkType: hard - "@jest/schemas@npm:^29.4.3": version: 29.4.3 resolution: "@jest/schemas@npm:29.4.3" @@ -15732,9 +15722,9 @@ __metadata: linkType: hard "@opentelemetry/api@npm:^1.0.1": - version: 1.2.0 - resolution: "@opentelemetry/api@npm:1.2.0" - checksum: 764efa81bf939200a8e80520a4735b23038abafc60c80420b007ae2bbb7ad843d806894414e95d974c2ef1b81d4ae8a3106804e1af7b5090240cfeb2467db099 + version: 1.9.0 + resolution: "@opentelemetry/api@npm:1.9.0" + checksum: 9e88e59d53ced668f3daaecfd721071c5b85a67dd386f1c6f051d1be54375d850016c881f656ffbe9a03bedae85f7e89c2f2b635313f9c9b195ad033cdc31020 languageName: node linkType: hard @@ -17715,13 +17705,6 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.24.1": - version: 0.24.46 - resolution: "@sinclair/typebox@npm:0.24.46" - checksum: 19d708fe93a42dce4ed6452a58909c841ad3484a6388a5b5d82e7ab11f8bfbd013bf34c32d6234a55532e4ff5f8ab9e1df17bb13b389aca038c7f05a8950a72a - languageName: node - linkType: hard - "@sinclair/typebox@npm:^0.25.16": version: 0.25.24 resolution: "@sinclair/typebox@npm:0.25.24" @@ -21683,7 +21666,7 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.149, @types/lodash@npm:^4.14.150": +"@types/lodash@npm:^4.14.149": version: 4.14.168 resolution: "@types/lodash@npm:4.14.168" checksum: 3326966ee089debde7a7d819e13b64991756e879945852c3357df14a7be837130f697c2cb451be9dd599eb7213fed0975bc9ca0f8f56b46fa73c46a83815b79c @@ -21797,12 +21780,12 @@ __metadata: linkType: hard "@types/node-fetch@npm:^2.6.2": - version: 2.6.2 - resolution: "@types/node-fetch@npm:2.6.2" + version: 2.6.11 + resolution: "@types/node-fetch@npm:2.6.11" dependencies: "@types/node": "*" - form-data: ^3.0.0 - checksum: 6f73b1470000d303d25a6fb92875ea837a216656cb7474f66cdd67bb014aa81a5a11e7ac9c21fe19bee9ecb2ef87c1962bceeaec31386119d1ac86e4c30ad7a6 + form-data: ^4.0.0 + checksum: 180e4d44c432839bdf8a25251ef8c47d51e37355ddd78c64695225de8bc5dc2b50b7bb855956d471c026bb84bd7295688a0960085e7158cbbba803053492568b languageName: node linkType: hard @@ -21832,13 +21815,6 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:14": - version: 14.17.19 - resolution: "@types/node@npm:14.17.19" - checksum: 3365ee4fe7878b0f1d36dc4372146322c7f4db3b0574401753084144b04356e02d15cd55db79e77dda071a06cbcc37f57c8888441fd4c8b1c24f9765c7441b2a - languageName: node - linkType: hard - "@types/node@npm:14 || 16": version: 16.18.23 resolution: "@types/node@npm:16.18.23" @@ -22469,7 +22445,7 @@ __metadata: languageName: node linkType: hard -"@types/uuid@npm:^9.0.1": +"@types/uuid@npm:^9.0.0, @types/uuid@npm:^9.0.1": version: 9.0.8 resolution: "@types/uuid@npm:9.0.8" checksum: b8c60b7ba8250356b5088302583d1704a4e1a13558d143c549c408bf8920535602ffc12394ede77f8a8083511b023704bc66d1345792714002bfa261b17c5275 @@ -23661,72 +23637,6 @@ __metadata: languageName: node linkType: hard -"@vue/compiler-core@npm:3.0.7, @vue/compiler-core@npm:^3.0.0": - version: 3.0.7 - resolution: "@vue/compiler-core@npm:3.0.7" - dependencies: - "@babel/parser": ^7.12.0 - "@babel/types": ^7.12.0 - "@vue/shared": 3.0.7 - estree-walker: ^2.0.1 - source-map: ^0.6.1 - checksum: 141e0b23c2c2edcbca1488d5474787a6e47d1c4dc76cdeb5daf0c3841a65898574c2da69ae20a80c4f3383dc809a6645cde23bceff6dc5bcccf1aacff51e8c66 - languageName: node - linkType: hard - -"@vue/compiler-dom@npm:3.0.7": - version: 3.0.7 - resolution: "@vue/compiler-dom@npm:3.0.7" - dependencies: - "@vue/compiler-core": 3.0.7 - "@vue/shared": 3.0.7 - checksum: e6f336493b98000be6808ca4a9c4f58928d4b41807d864e0be8823cb0443022d81ba74c4300312c687e41643043231f5ea05ded1fb5b16674dfddaa5b3135fd2 - languageName: node - linkType: hard - -"@vue/compiler-sfc@npm:^3.0.5": - version: 3.0.7 - resolution: "@vue/compiler-sfc@npm:3.0.7" - dependencies: - "@babel/parser": ^7.12.0 - "@babel/types": ^7.12.0 - "@vue/compiler-core": 3.0.7 - "@vue/compiler-dom": 3.0.7 - "@vue/compiler-ssr": 3.0.7 - "@vue/shared": 3.0.7 - consolidate: ^0.16.0 - estree-walker: ^2.0.1 - hash-sum: ^2.0.0 - lru-cache: ^5.1.1 - magic-string: ^0.25.7 - merge-source-map: ^1.1.0 - postcss: ^8.1.10 - postcss-modules: ^4.0.0 - postcss-selector-parser: ^6.0.4 - source-map: ^0.6.1 - peerDependencies: - vue: 3.0.7 - checksum: 06ebaeeadabae32a648f35a7983a61126a48ea48eefa26528edc09da12a903fc3ef68f9f32d75a961a35acda3c296bcbbc1311a0c6c234e0cd87c4391fb4692b - languageName: node - linkType: hard - -"@vue/compiler-ssr@npm:3.0.7": - version: 3.0.7 - resolution: "@vue/compiler-ssr@npm:3.0.7" - dependencies: - "@vue/compiler-dom": 3.0.7 - "@vue/shared": 3.0.7 - checksum: 63fe30f9676942e7c44da6eb6ac5f8cb23df2344096b72a68fceffb7b9ca7760376987c29eac1e27a31b1b89385416ae524d98e06ada957f68bdc25a9f0e783f - languageName: node - linkType: hard - -"@vue/shared@npm:3.0.7": - version: 3.0.7 - resolution: "@vue/shared@npm:3.0.7" - checksum: 473a5acac3acb766ea6501b6ae9c7a30eb929bbb71064175052af0cdabb968fa106d112cbedb1d970d3cabaea1ef8341ab8c08249c85b9948118ce92c98081b7 - languageName: node - linkType: hard - "@webassemblyjs/ast@npm:1.11.6, @webassemblyjs/ast@npm:^1.11.5": version: 1.11.6 resolution: "@webassemblyjs/ast@npm:1.11.6" @@ -24617,21 +24527,21 @@ __metadata: languageName: node linkType: hard -"apollo-reporting-protobuf@npm:^0.8.0 || ^3.0.0, apollo-reporting-protobuf@npm:^3.3.1, apollo-reporting-protobuf@npm:^3.3.3": - version: 3.3.3 - resolution: "apollo-reporting-protobuf@npm:3.3.3" +"apollo-reporting-protobuf@npm:^0.8.0 || ^3.0.0, apollo-reporting-protobuf@npm:^3.4.0": + version: 3.4.0 + resolution: "apollo-reporting-protobuf@npm:3.4.0" dependencies: "@apollo/protobufjs": 1.2.6 - checksum: 6900db30476ef2e888ecef4c291e26579eba9695dc874ca8b3d1f93064bea307689172790b9d574849e5bdb371953ea38f2caddc5abb51e1ca197197f3d56d28 + checksum: 5bf50e9cecd3c2334cd12e0ebe59be6c4d7b1b9ee443c7d913011ea1b84513f57561fb6c3ceb66083321acb6d1c56f72e2ab0edf378cf742693409eb8dcdc46b languageName: node linkType: hard -"apollo-reporting-protobuf@npm:^3.4.0": - version: 3.4.0 - resolution: "apollo-reporting-protobuf@npm:3.4.0" +"apollo-reporting-protobuf@npm:^3.3.1, apollo-reporting-protobuf@npm:^3.3.3": + version: 3.3.3 + resolution: "apollo-reporting-protobuf@npm:3.3.3" dependencies: "@apollo/protobufjs": 1.2.6 - checksum: 5bf50e9cecd3c2334cd12e0ebe59be6c4d7b1b9ee443c7d913011ea1b84513f57561fb6c3ceb66083321acb6d1c56f72e2ab0edf378cf742693409eb8dcdc46b + checksum: 6900db30476ef2e888ecef4c291e26579eba9695dc874ca8b3d1f93064bea307689172790b9d574849e5bdb371953ea38f2caddc5abb51e1ca197197f3d56d28 languageName: node linkType: hard @@ -28405,13 +28315,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:8, commander@npm:^8.3.0": - version: 8.3.0 - resolution: "commander@npm:8.3.0" - checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 - languageName: node - linkType: hard - "commander@npm:^2.19.0, commander@npm:^2.20.0, commander@npm:^2.20.3": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -28440,6 +28343,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^8.3.0": + version: 8.3.0 + resolution: "commander@npm:8.3.0" + checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 + languageName: node + linkType: hard + "commander@npm:^9.4.1": version: 9.5.0 resolution: "commander@npm:9.5.0" @@ -28704,15 +28614,6 @@ __metadata: languageName: node linkType: hard -"consolidate@npm:^0.16.0": - version: 0.16.0 - resolution: "consolidate@npm:0.16.0" - dependencies: - bluebird: ^3.7.2 - checksum: f17164ffb2c4f79b4cbf685f1c76a49f59d329a40954b436425498861dc137b46fe821b2aadafa2dcfeb7eebd46846f35bd2c36b4a704d38521b4210a22a7515 - languageName: node - linkType: hard - "constant-case@npm:^3.0.4": version: 3.0.4 resolution: "constant-case@npm:3.0.4" @@ -33292,13 +33193,6 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^2.0.1": - version: 2.0.2 - resolution: "estree-walker@npm:2.0.2" - checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc - languageName: node - linkType: hard - "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -33960,7 +33854,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.2.11, fast-glob@npm:^3.2.4, fast-glob@npm:^3.2.7, fast-glob@npm:^3.2.9": +"fast-glob@npm:3.2.11, fast-glob@npm:^3.2.7, fast-glob@npm:^3.2.9": version: 3.2.11 resolution: "fast-glob@npm:3.2.11" dependencies: @@ -34904,9 +34798,9 @@ __metadata: languageName: node linkType: hard -"framer-motion@npm:11.11.9": - version: 11.11.9 - resolution: "framer-motion@npm:11.11.9" +"framer-motion@npm:11.11.11": + version: 11.11.11 + resolution: "framer-motion@npm:11.11.11" dependencies: tslib: ^2.4.0 peerDependencies: @@ -34920,7 +34814,7 @@ __metadata: optional: true react-dom: optional: true - checksum: d2918aa3de0746cadb60af7f940c72d17b0d2869b66992f47d6a187abc3599cbf6520188ea8131c9fd7fe65cd87783fbfce3d2115f833b1488a8d73509e5789a + checksum: 12a358dafdd5239ea6eaad87fa7783dad7c009b639b6e087574f3515dfa4c4bd02ed4fcde61522f6db3a311e353333455d0b0e9d413a2662265330055672eeb6 languageName: node linkType: hard @@ -35237,15 +35131,6 @@ __metadata: languageName: node linkType: hard -"generic-names@npm:^2.0.1": - version: 2.0.1 - resolution: "generic-names@npm:2.0.1" - dependencies: - loader-utils: ^1.1.0 - checksum: 5f2d6837dcddf4d7139f7c7ee4ff6ed82564123ae363aadc7a1c1c9967724da1e10d92c904b76b6ff58912465cf63cf47d87f3b400286845f289f54d5092e78f - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -36251,13 +36136,6 @@ __metadata: languageName: node linkType: hard -"hash-sum@npm:^2.0.0": - version: 2.0.0 - resolution: "hash-sum@npm:2.0.0" - checksum: efeeacf09ecbd467202865403c3a1991fa15d4f4903c1148ecbe13223fdbf9ec6d7dc661e17e5ce6e776cd70d67b6ee4c82e0171318962435be45c1155175f3f - languageName: node - linkType: hard - "hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": version: 1.1.7 resolution: "hash.js@npm:1.1.7" @@ -37037,13 +36915,6 @@ __metadata: languageName: node linkType: hard -"icss-replace-symbols@npm:^1.1.0": - version: 1.1.0 - resolution: "icss-replace-symbols@npm:1.1.0" - checksum: 24575b2c2f7e762bfc6f4beee31be9ba98a01cad521b5aa9954090a5de2b5e1bf67814c17e22f9e51b7d798238db8215a173d6c2b4726ce634ce06b68ece8045 - languageName: node - linkType: hard - "icss-utils@npm:^5.0.0, icss-utils@npm:^5.1.0": version: 5.1.0 resolution: "icss-utils@npm:5.1.0" @@ -38584,7 +38455,6 @@ __metadata: "@contentful/field-editor-reference": 5.20.0 "@contentful/field-editor-single-line": 1.1.8 "@contentful/forma-36-react-components": 3.78.4 - "@contentful/forma-36-tokens": 0.10.1 "@contentful/node-apps-toolkit": 2.0.2 "@contentful/react-apps-toolkit": 1.2.15 "@contentful/rich-text-from-markdown": 15.16.6 @@ -38596,7 +38466,6 @@ __metadata: "@dnd-kit/core": 6.1.0 "@dnd-kit/sortable": 8.0.0 "@elastic/elasticsearch": 7.7.1 - "@formatjs/cli": 4.2.27 "@formatjs/intl-datetimeformat": 4.1.6 "@formatjs/intl-locale": 2.4.33 "@formatjs/intl-numberformat": 7.1.5 @@ -38802,7 +38671,7 @@ __metadata: font-awesome: 4.7.0 form-data: 3.0.0 formik: 2.2.9 - framer-motion: 11.11.9 + framer-motion: 11.11.11 fridagar: ^3.2.0 fuse.js: 7.0.0 glob: 10.3.3 @@ -38897,7 +38766,7 @@ __metadata: react-popper: 2.3.0 react-remove-scroll: 2.5.6 react-router-dom: 6.11.2 - react-select: 5.7.3 + react-select: 5.8.2 react-table: 7.7.0 react-toastify: 6.0.8 react-top-loading-bar: 2.3.1 @@ -38949,7 +38818,6 @@ __metadata: uuidv4: 6.0.8 vm-browserify: 1.1.2 webpack-bundle-analyzer: 4.5.0 - whatwg-fetch: 3.6.2 winston: 3.7.2 winston-cloudwatch: 3.1.1 winston-transport: 4.6.0 @@ -41553,17 +41421,6 @@ __metadata: languageName: node linkType: hard -"loader-utils@npm:^1.1.0": - version: 1.4.0 - resolution: "loader-utils@npm:1.4.0" - dependencies: - big.js: ^5.2.2 - emojis-list: ^3.0.0 - json5: ^1.0.1 - checksum: d150b15e7a42ac47d935c8b484b79e44ff6ab4c75df7cc4cb9093350cf014ec0b17bdb60c5d6f91a37b8b218bd63b973e263c65944f58ca2573e402b9a27e717 - languageName: node - linkType: hard - "loader-utils@npm:^2.0.0": version: 2.0.2 resolution: "loader-utils@npm:2.0.2" @@ -41939,9 +41796,9 @@ __metadata: linkType: hard "loglevel@npm:^1.6.1": - version: 1.7.1 - resolution: "loglevel@npm:1.7.1" - checksum: 715a4ae69ad75d4d3bd04e4f6e9edbc4cae4db34d1e7f54f426d8cebe2dd9fef891ca3789e839d927cdbc5fad73d789e998db0af2f11f4c40219c272bc923823 + version: 1.9.2 + resolution: "loglevel@npm:1.9.2" + checksum: 896c67b90a507bfcfc1e9a4daa7bf789a441dd70d95cd13b998d6dd46233a3bfadfb8fadb07250432bbfb53bf61e95f2520f9b11f9d3175cc460e5c251eca0af languageName: node linkType: hard @@ -42019,16 +41876,6 @@ __metadata: languageName: node linkType: hard -"loud-rejection@npm:^2.2.0": - version: 2.2.0 - resolution: "loud-rejection@npm:2.2.0" - dependencies: - currently-unhandled: ^0.4.1 - signal-exit: ^3.0.2 - checksum: 2499c593d9a09a6fd305c6185826bcf546144b445ce730bdc275433674d1f411c23ce5dfcc7971feb22add7b47dc7e5f8c89c589f3720944d7e6945b617e392e - languageName: node - linkType: hard - "lower-case-first@npm:^2.0.2": version: 2.0.2 resolution: "lower-case-first@npm:2.0.2" @@ -42089,14 +41936,14 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.10.1, lru-cache@npm:^7.13.1, lru-cache@npm:^7.7.1": +"lru-cache@npm:^7.10.1, lru-cache@npm:^7.7.1": version: 7.14.0 resolution: "lru-cache@npm:7.14.0" checksum: efdd329f2c1bb790b71d497c6c59272e6bc2d7dd060ba55fc136becd3dd31fc8346edb446275504d94cb60d3c8385dbf5267b79b23789e409b2bdf302d13f0d7 languageName: node linkType: hard -"lru-cache@npm:^7.14.0, lru-cache@npm:^7.14.1": +"lru-cache@npm:^7.13.1, lru-cache@npm:^7.14.0, lru-cache@npm:^7.14.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 @@ -42196,15 +42043,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.25.7": - version: 0.25.7 - resolution: "magic-string@npm:0.25.7" - dependencies: - sourcemap-codec: ^1.4.4 - checksum: 727a1fb70f9610304fe384f1df0251eb7d1d9dd779c07ef1225690361b71b216f26f5d934bfb11c919b5b0e7ba50f6240c823a6f2e44cfd33d4a07d7747ca829 - languageName: node - linkType: hard - "magic-string@npm:^0.30.5": version: 0.30.11 resolution: "magic-string@npm:0.30.11" @@ -42968,15 +42806,6 @@ __metadata: languageName: node linkType: hard -"merge-source-map@npm:^1.1.0": - version: 1.1.0 - resolution: "merge-source-map@npm:1.1.0" - dependencies: - source-map: ^0.6.1 - checksum: 945a83dcc59eff77dde709be1d3d6cb575c11cd7164a7ccdc1c6f0d463aad7c12750a510bdf84af2c05fac4615c4305d97ac90477975348bb901a905c8e92c4b - languageName: node - linkType: hard - "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -44402,15 +44231,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.1": - version: 3.3.3 - resolution: "nanoid@npm:3.3.3" - bin: - nanoid: bin/nanoid.cjs - checksum: ada019402a07464a694553c61d2dca8a4353645a7d92f2830f0d487fedff403678a0bee5323a46522752b2eab95a0bc3da98b6cccaa7c0c55cd9975130e6d6f0 - languageName: node - linkType: hard - "nanoid@npm:^3.3.6": version: 3.3.6 resolution: "nanoid@npm:3.3.6" @@ -47227,19 +47047,6 @@ __metadata: languageName: node linkType: hard -"postcss-modules-local-by-default@npm:^4.0.0": - version: 4.0.0 - resolution: "postcss-modules-local-by-default@npm:4.0.0" - dependencies: - icss-utils: ^5.0.0 - postcss-selector-parser: ^6.0.2 - postcss-value-parser: ^4.1.0 - peerDependencies: - postcss: ^8.1.0 - checksum: 6cf570badc7bc26c265e073f3ff9596b69bb954bc6ac9c5c1b8cba2995b80834226b60e0a3cbb87d5f399dbb52e6466bba8aa1d244f6218f99d834aec431a69d - languageName: node - linkType: hard - "postcss-modules-local-by-default@npm:^4.0.3": version: 4.0.3 resolution: "postcss-modules-local-by-default@npm:4.0.3" @@ -47275,24 +47082,6 @@ __metadata: languageName: node linkType: hard -"postcss-modules@npm:^4.0.0": - version: 4.0.0 - resolution: "postcss-modules@npm:4.0.0" - dependencies: - generic-names: ^2.0.1 - icss-replace-symbols: ^1.1.0 - lodash.camelcase: ^4.3.0 - postcss-modules-extract-imports: ^3.0.0 - postcss-modules-local-by-default: ^4.0.0 - postcss-modules-scope: ^3.0.0 - postcss-modules-values: ^4.0.0 - string-hash: ^1.1.1 - peerDependencies: - postcss: ^8.0.0 - checksum: 8f50c241718955b94807b1066a843fc8c9a356bd28db7f9c30ddcc7dcf0b6a61d7e41c6b41ed5d6d7cfc341891f150fc69d57387910256588bbbe5bfd4ff74d6 - languageName: node - linkType: hard - "postcss-normalize-charset@npm:^6.0.0": version: 6.0.0 resolution: "postcss-normalize-charset@npm:6.0.0" @@ -47505,17 +47294,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.1.10": - version: 8.4.12 - resolution: "postcss@npm:8.4.12" - dependencies: - nanoid: ^3.3.1 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: 248e3d0f9bbb8efaafcfda7f91627a29bdc9a19f456896886330beb28c5abea0e14c7901b35191928602e2eccbed496b1e94097d27a0b2a980854cd00c7a835f - languageName: node - linkType: hard - "postcss@npm:^8.3.11, postcss@npm:^8.4.21, postcss@npm:^8.4.24": version: 8.4.24 resolution: "postcss@npm:8.4.24" @@ -47724,18 +47502,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^28.0.0": - version: 28.1.3 - resolution: "pretty-format@npm:28.1.3" - dependencies: - "@jest/schemas": ^28.1.3 - ansi-regex: ^5.0.1 - ansi-styles: ^5.0.0 - react-is: ^18.0.0 - checksum: e69f857358a3e03d271252d7524bec758c35e44680287f36c1cb905187fbc82da9981a6eb07edfd8a03bc3cbeebfa6f5234c13a3d5b59f2bbdf9b4c4053e0a7f - languageName: node - linkType: hard - "pretty-format@npm:^29.0.0, pretty-format@npm:^29.5.0": version: 29.5.0 resolution: "pretty-format@npm:29.5.0" @@ -49463,9 +49229,9 @@ __metadata: languageName: node linkType: hard -"react-select@npm:5.7.3": - version: 5.7.3 - resolution: "react-select@npm:5.7.3" +"react-select@npm:5.8.2": + version: 5.8.2 + resolution: "react-select@npm:5.8.2" dependencies: "@babel/runtime": ^7.12.0 "@emotion/cache": ^11.4.0 @@ -49479,7 +49245,7 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 9ffa75afb395e7077076521c529611494164ace0c6b1ceb249406991ac668947cfd0424812c15c2a45c792bb2794b22f2df93c4c2f2515962b7dfc7c91b029ec + checksum: d7b45e377e80731ef11dd0c00749f65c7ce6558c41679dbcfe0af4cfd1d77347275647d847bff1aa584128148863ea59e37cd9c90b754e29b955318fa896884c languageName: node linkType: hard @@ -52601,7 +52367,7 @@ __metadata: languageName: node linkType: hard -"sourcemap-codec@npm:^1.4.1, sourcemap-codec@npm:^1.4.4, sourcemap-codec@npm:^1.4.8": +"sourcemap-codec@npm:^1.4.1, sourcemap-codec@npm:^1.4.8": version: 1.4.8 resolution: "sourcemap-codec@npm:1.4.8" checksum: b57981c05611afef31605732b598ccf65124a9fcb03b833532659ac4d29ac0f7bfacbc0d6c5a28a03e84c7510e7e556d758d0bb57786e214660016fb94279316 @@ -53130,13 +52896,6 @@ __metadata: languageName: node linkType: hard -"string-hash@npm:^1.1.1": - version: 1.1.3 - resolution: "string-hash@npm:1.1.3" - checksum: 104b8667a5e0dc71bfcd29fee09cb88c6102e27bfb07c55f95535d90587d016731d52299380052e514266f4028a7a5172e0d9ac58e2f8f5001be61dc77c0754d - languageName: node - linkType: hard - "string-length@npm:^4.0.1": version: 4.0.2 resolution: "string-length@npm:4.0.2" @@ -54846,10 +54605,10 @@ __metadata: languageName: node linkType: hard -"ts-graphviz@npm:^0.16.0": - version: 0.16.0 - resolution: "ts-graphviz@npm:0.16.0" - checksum: 608f4bb240374717a01875d54e073191120bb5c23710706d31cb294814192586689fd22b8455293cabf8ffda2ba89e9302cda6ce937cf157c4495a6915969151 +"ts-graphviz@npm:^1.5.4": + version: 1.8.2 + resolution: "ts-graphviz@npm:1.8.2" + checksum: 73723d6d9b9b29073ff659b38e8a8443a024d515a30fd77dfb00a9df0e835739f2522c303a353e63bbd39115e23b34c9d92dd66f72590cf5f92d3a447255f9b9 languageName: node linkType: hard @@ -55426,16 +55185,6 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.0, typescript@npm:^4.5.3": - version: 4.6.3 - resolution: "typescript@npm:4.6.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 255bb26c8cb846ca689dd1c3a56587af4f69055907aa2c154796ea28ee0dea871535b1c78f85a6212c77f2657843a269c3a742d09d81495b97b914bf7920415b - languageName: node - linkType: hard - "typescript@npm:^4.3": version: 4.9.5 resolution: "typescript@npm:4.9.5" @@ -55456,6 +55205,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^4.5.3": + version: 4.6.3 + resolution: "typescript@npm:4.6.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 255bb26c8cb846ca689dd1c3a56587af4f69055907aa2c154796ea28ee0dea871535b1c78f85a6212c77f2657843a269c3a742d09d81495b97b914bf7920415b + languageName: node + linkType: hard + "typescript@patch:typescript@5.3.3#~builtin": version: 5.3.3 resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=a1c5e5" @@ -55476,16 +55235,6 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^4.0#~builtin, typescript@patch:typescript@^4.5.3#~builtin": - version: 4.6.3 - resolution: "typescript@patch:typescript@npm%3A4.6.3#~builtin::version=4.6.3&hash=a1c5e5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 6bf45caf847062420592e711bc9c28bf5f9a9a7fa8245343b81493e4ededae33f1774009d1234d911422d1646a2c839f44e1a23ecb111b40a60ac2ea4c1482a8 - languageName: node - linkType: hard - "typescript@patch:typescript@^4.3#~builtin": version: 4.9.5 resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=a1c5e5" @@ -55506,6 +55255,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^4.5.3#~builtin": + version: 4.6.3 + resolution: "typescript@patch:typescript@npm%3A4.6.3#~builtin::version=4.6.3&hash=a1c5e5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 6bf45caf847062420592e711bc9c28bf5f9a9a7fa8245343b81493e4ededae33f1774009d1234d911422d1646a2c839f44e1a23ecb111b40a60ac2ea4c1482a8 + languageName: node + linkType: hard + "ua-parser-js@npm:1.0.33": version: 1.0.33 resolution: "ua-parser-js@npm:1.0.33" @@ -57013,7 +56772,7 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:3.6.2, whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": +"whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": version: 3.6.2 resolution: "whatwg-fetch@npm:3.6.2" checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed From f48c80bcb4b2e46171f7489801ea1580091e854f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Fri, 8 Nov 2024 15:17:11 +0000 Subject: [PATCH 2/5] fix(application-system-api): add secret from aws parameter store for national registry client v3 (#16782) Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/application-system/api/infra/application-system-api.ts | 2 ++ charts/islandis/values.dev.yaml | 1 + charts/islandis/values.prod.yaml | 1 + charts/islandis/values.staging.yaml | 1 + 4 files changed, 5 insertions(+) diff --git a/apps/application-system/api/infra/application-system-api.ts b/apps/application-system/api/infra/application-system-api.ts index 41738c668a20..d7e2dec8ba98 100644 --- a/apps/application-system/api/infra/application-system-api.ts +++ b/apps/application-system/api/infra/application-system-api.ts @@ -339,6 +339,8 @@ export const serviceSetup = (services: { '/k8s/api/ALTHINGI_OMBUDSMAN_XROAD_USERNAME', ALTHINGI_OMBUDSMAN_XROAD_PASSWORD: '/k8s/api/ALTHINGI_OMBUDSMAN_XROAD_PASSWORD', + NATIONAL_REGISTRY_B2C_CLIENT_SECRET: + '/k8s/api/NATIONAL_REGISTRY_B2C_CLIENT_SECRET', }) .db() .migrations() diff --git a/charts/islandis/values.dev.yaml b/charts/islandis/values.dev.yaml index ca6d0b8694db..c623fa075f17 100644 --- a/charts/islandis/values.dev.yaml +++ b/charts/islandis/values.dev.yaml @@ -796,6 +796,7 @@ application-system-api: IDENTITY_SERVER_CLIENT_SECRET: '/k8s/application-system/api/IDENTITY_SERVER_CLIENT_SECRET' ISLYKILL_SERVICE_BASEPATH: '/k8s/api/ISLYKILL_SERVICE_BASEPATH' ISLYKILL_SERVICE_PASSPHRASE: '/k8s/api/ISLYKILL_SERVICE_PASSPHRASE' + NATIONAL_REGISTRY_B2C_CLIENT_SECRET: '/k8s/api/NATIONAL_REGISTRY_B2C_CLIENT_SECRET' NOVA_PASSWORD: '/k8s/application-system/api/NOVA_PASSWORD' NOVA_URL: '/k8s/application-system-api/NOVA_URL' SYSLUMENN_HOST: '/k8s/application-system-api/SYSLUMENN_HOST' diff --git a/charts/islandis/values.prod.yaml b/charts/islandis/values.prod.yaml index 0564cf2d03c7..475d6bf4064f 100644 --- a/charts/islandis/values.prod.yaml +++ b/charts/islandis/values.prod.yaml @@ -784,6 +784,7 @@ application-system-api: IDENTITY_SERVER_CLIENT_SECRET: '/k8s/application-system/api/IDENTITY_SERVER_CLIENT_SECRET' ISLYKILL_SERVICE_BASEPATH: '/k8s/api/ISLYKILL_SERVICE_BASEPATH' ISLYKILL_SERVICE_PASSPHRASE: '/k8s/api/ISLYKILL_SERVICE_PASSPHRASE' + NATIONAL_REGISTRY_B2C_CLIENT_SECRET: '/k8s/api/NATIONAL_REGISTRY_B2C_CLIENT_SECRET' NOVA_PASSWORD: '/k8s/application-system/api/NOVA_PASSWORD' NOVA_URL: '/k8s/application-system-api/NOVA_URL' SYSLUMENN_HOST: '/k8s/application-system-api/SYSLUMENN_HOST' diff --git a/charts/islandis/values.staging.yaml b/charts/islandis/values.staging.yaml index c7e4a2583b0d..402379a9766c 100644 --- a/charts/islandis/values.staging.yaml +++ b/charts/islandis/values.staging.yaml @@ -793,6 +793,7 @@ application-system-api: IDENTITY_SERVER_CLIENT_SECRET: '/k8s/application-system/api/IDENTITY_SERVER_CLIENT_SECRET' ISLYKILL_SERVICE_BASEPATH: '/k8s/api/ISLYKILL_SERVICE_BASEPATH' ISLYKILL_SERVICE_PASSPHRASE: '/k8s/api/ISLYKILL_SERVICE_PASSPHRASE' + NATIONAL_REGISTRY_B2C_CLIENT_SECRET: '/k8s/api/NATIONAL_REGISTRY_B2C_CLIENT_SECRET' NOVA_PASSWORD: '/k8s/application-system/api/NOVA_PASSWORD' NOVA_URL: '/k8s/application-system-api/NOVA_URL' SYSLUMENN_HOST: '/k8s/application-system-api/SYSLUMENN_HOST' From b2966259ccf32fac2c9aa9605ebed36576a12df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3hanna=20Magn=C3=BAsd=C3=B3ttir?= Date: Fri, 8 Nov 2024 15:31:48 +0000 Subject: [PATCH 3/5] fix(samgongustofa): Send email when deleting application in review state (#16766) * Send email when deleting application in review state * Change email/sms text * Add missing await --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../change-co-owner-of-vehicle.service.ts | 33 +++++++++++++------ .../applicationRejectedEmail.ts | 27 ++++++++++----- .../smsGenerators/applicationRejectedSms.ts | 17 +++++++--- .../change-co-owner-of-vehicle/types.ts | 5 +++ .../change-operator-of-vehicle.service.ts | 33 +++++++++++++------ .../applicationRejectedEmail.ts | 27 ++++++++++----- .../smsGenerators/applicationRejectedSms.ts | 17 +++++++--- .../change-operator-of-vehicle/types.ts | 5 +++ .../applicationRejectedEmail.ts | 27 ++++++++++----- .../smsGenerators/applicationRejectedSms.ts | 17 +++++++--- .../transfer-of-vehicle-ownership.service.ts | 33 +++++++++++++------ .../transfer-of-vehicle-ownership/types.ts | 5 +++ .../src/lib/ChangeCoOwnerOfVehicleTemplate.ts | 3 ++ .../src/shared/constants.ts | 1 + .../lib/ChangeOperatorOfVehicleTemplate.ts | 3 ++ .../src/shared/constants.ts | 1 + .../lib/TransferOfVehicleOwnershipTemplate.ts | 4 +++ .../src/shared/constants.ts | 1 + 18 files changed, 190 insertions(+), 69 deletions(-) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/change-co-owner-of-vehicle.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/change-co-owner-of-vehicle.service.ts index 0596529f329a..9fc9f0c56b2d 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/change-co-owner-of-vehicle.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/change-co-owner-of-vehicle.service.ts @@ -24,7 +24,7 @@ import { MileageReadingApi, MileageReadingDto, } from '@island.is/clients/vehicles-mileage' -import { EmailRecipient, EmailRole } from './types' +import { EmailRecipient, EmailRole, RejectType } from './types' import { getAllRoles, getRecipients, @@ -325,14 +325,25 @@ export class ChangeCoOwnerOfVehicleService extends BaseTemplateApiService { return recipientList } - async rejectApplication({ - application, - auth, - }: TemplateApiModuleActionProps): Promise { + async rejectApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.REJECT) + } + + async deleteApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.DELETE) + } + + private async doRejectApplication( + { application, auth }: TemplateApiModuleActionProps, + rejectType: RejectType, + ): Promise { // 1. Delete charge so that the seller gets reimburshed - const chargeId = getPaymentIdFromExternalData(application) - if (chargeId) { - await this.chargeFjsV2ClientService.deleteCharge(chargeId) + // Note: not necessary on delete, since that is done in the shared delete function + if (rejectType !== RejectType.DELETE) { + const chargeId = getPaymentIdFromExternalData(application) + if (chargeId) { + await this.chargeFjsV2ClientService.deleteCharge(chargeId) + } } // 2. Notify everyone in the process that the application has been withdrawn @@ -352,13 +363,14 @@ export class ChangeCoOwnerOfVehicleService extends BaseTemplateApiService { props, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) .catch((e) => { this.logger.error( `Error sending email about rejectApplication in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) @@ -372,6 +384,7 @@ export class ChangeCoOwnerOfVehicleService extends BaseTemplateApiService { application, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) @@ -379,7 +392,7 @@ export class ChangeCoOwnerOfVehicleService extends BaseTemplateApiService { this.logger.error( `Error sending sms about rejectApplication to a phonenumber in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/emailGenerators/applicationRejectedEmail.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/emailGenerators/applicationRejectedEmail.ts index c47d3a5aee47..56917cb647e3 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/emailGenerators/applicationRejectedEmail.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/emailGenerators/applicationRejectedEmail.ts @@ -1,7 +1,7 @@ import { ChangeCoOwnerOfVehicleAnswers } from '@island.is/application/templates/transport-authority/change-co-owner-of-vehicle' import { Message } from '@island.is/email-service' import { EmailTemplateGeneratorProps } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { getRoleNameById } from '../change-co-owner-of-vehicle.utils' import { pathToAsset } from '../change-co-owner-of-vehicle.utils' import { ApplicationConfigurations } from '@island.is/application/types' @@ -10,12 +10,14 @@ export type ApplicationRejectedEmail = ( props: EmailTemplateGeneratorProps, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => Message export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( props, recipient, rejectedBy, + rejectType, ): Message => { const { application, @@ -33,6 +35,21 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = + `Góðan dag,

` + + `Beiðni um breytingu á meðeigendum á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki:` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += + `
` + + `
  • ${rejectedByStr}

` + + `Til þess að skrá breytingu á meðeigendum rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + + `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um umsókn sem skilað hefur verið inn til Samgöngustofu á pappír.
` + + `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.` + return { from: { name: email.sender, @@ -64,13 +81,7 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( { component: 'Copy', context: { - copy: - `Góðan dag,

` + - `Beiðni um breytingu á meðeigendum á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki:
` + - `
  • ${rejectedByStr}

` + - `Til þess að skrá breytingu á meðeigendum rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + - `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um umsókn sem skilað hefur verið inn til Samgöngustofu á pappír.
` + - `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.`, + copy: message, }, }, { diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/smsGenerators/applicationRejectedSms.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/smsGenerators/applicationRejectedSms.ts index 526a502581b5..3711357b349a 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/smsGenerators/applicationRejectedSms.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/smsGenerators/applicationRejectedSms.ts @@ -1,5 +1,5 @@ import { SmsMessage } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { Application } from '@island.is/application/types' import { ChangeCoOwnerOfVehicleAnswers } from '@island.is/application/templates/transport-authority/change-co-owner-of-vehicle' import { getRoleNameById } from '../change-co-owner-of-vehicle.utils' @@ -8,12 +8,14 @@ export type ApplicationRejectedSms = ( application: Application, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => SmsMessage export const generateApplicationRejectedSms: ApplicationRejectedSms = ( application, recipient, rejectedBy, + rejectType, ) => { const answers = application.answers as ChangeCoOwnerOfVehicleAnswers const permno = answers?.pickVehicle?.plate @@ -26,11 +28,16 @@ export const generateApplicationRejectedSms: ApplicationRejectedSms = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = `Beiðni um breytingu á meðeigendum á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki: ` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += `${rejectedByStr}. Nánari upplýsingar á island.is/umsoknir. ` + return { phoneNumber: recipient.phone || '', - message: - `Beiðni um breytingu á meðeigendum á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki: ` + - `${rejectedByStr}. ` + - `Nánari upplýsingar á island.is/umsoknir. `, + message: message, } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/types.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/types.ts index 01b8da5b6945..a69cf8517a78 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/types.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-co-owner-of-vehicle/types.ts @@ -12,3 +12,8 @@ export interface EmailRecipient { role: EmailRole approved?: boolean } + +export enum RejectType { + REJECT, + DELETE, +} diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/change-operator-of-vehicle.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/change-operator-of-vehicle.service.ts index 5ff6a906b876..fd9d7a62ffb9 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/change-operator-of-vehicle.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/change-operator-of-vehicle.service.ts @@ -3,7 +3,7 @@ import { SharedTemplateApiService } from '../../../shared' import { TemplateApiModuleActionProps } from '../../../../types' import { BaseTemplateApiService } from '../../../base-template-api.service' import { ApplicationTypes } from '@island.is/application/types' -import { EmailRecipient, EmailRole } from './types' +import { EmailRecipient, EmailRole, RejectType } from './types' import { getAllRoles, getRecipients, @@ -297,14 +297,25 @@ export class ChangeOperatorOfVehicleService extends BaseTemplateApiService { return recipientList } - async rejectApplication({ - application, - auth, - }: TemplateApiModuleActionProps): Promise { + async rejectApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.REJECT) + } + + async deleteApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.DELETE) + } + + private async doRejectApplication( + { application, auth }: TemplateApiModuleActionProps, + rejectType: RejectType, + ): Promise { // 1. Delete charge so that the seller gets reimburshed - const chargeId = getPaymentIdFromExternalData(application) - if (chargeId) { - this.chargeFjsV2ClientService.deleteCharge(chargeId) + // Note: not necessary on delete, since that is done in the shared delete function + if (rejectType !== RejectType.DELETE) { + const chargeId = getPaymentIdFromExternalData(application) + if (chargeId) { + await this.chargeFjsV2ClientService.deleteCharge(chargeId) + } } // 2. Notify everyone in the process that the application has been withdrawn @@ -324,13 +335,14 @@ export class ChangeOperatorOfVehicleService extends BaseTemplateApiService { props, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) .catch((e) => { this.logger.error( `Error sending email about rejectApplication in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) @@ -344,6 +356,7 @@ export class ChangeOperatorOfVehicleService extends BaseTemplateApiService { application, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) @@ -351,7 +364,7 @@ export class ChangeOperatorOfVehicleService extends BaseTemplateApiService { this.logger.error( `Error sending sms about rejectApplication to a phonenumber in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/emailGenerators/applicationRejectedEmail.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/emailGenerators/applicationRejectedEmail.ts index 00c0b4599268..57cc4f0c60c7 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/emailGenerators/applicationRejectedEmail.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/emailGenerators/applicationRejectedEmail.ts @@ -1,7 +1,7 @@ import { ChangeOperatorOfVehicleAnswers } from '@island.is/application/templates/transport-authority/change-operator-of-vehicle' import { Message } from '@island.is/email-service' import { EmailTemplateGeneratorProps } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { getRoleNameById } from '../change-operator-of-vehicle.utils' import { pathToAsset } from '../change-operator-of-vehicle.utils' import { ApplicationConfigurations } from '@island.is/application/types' @@ -10,12 +10,14 @@ export type ApplicationRejectedEmail = ( props: EmailTemplateGeneratorProps, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => Message export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( props, recipient, rejectedBy, + rejectType, ): Message => { const { application, @@ -33,6 +35,21 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = + `Góðan dag,

` + + `Beiðni um breytingu á umráðamönnum á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki:` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += + `
` + + `
  • ${rejectedByStr}

` + + `Til þess að skrá breytingu á umráðamönnum rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + + `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um umsókn sem skilað hefur verið inn til Samgöngustofu á pappír.
` + + `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.` + return { from: { name: email.sender, @@ -64,13 +81,7 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( { component: 'Copy', context: { - copy: - `Góðan dag,

` + - `Beiðni um breytingu á umráðamönnum á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki:
` + - `
  • ${rejectedByStr}

` + - `Til þess að skrá breytingu á umráðamönnum rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + - `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um umsókn sem skilað hefur verið inn til Samgöngustofu á pappír.
` + - `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.`, + copy: message, }, }, { diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/smsGenerators/applicationRejectedSms.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/smsGenerators/applicationRejectedSms.ts index dc981534ec9c..a643d8d9966a 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/smsGenerators/applicationRejectedSms.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/smsGenerators/applicationRejectedSms.ts @@ -1,5 +1,5 @@ import { SmsMessage } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { Application } from '@island.is/application/types' import { ChangeOperatorOfVehicleAnswers } from '@island.is/application/templates/transport-authority/change-operator-of-vehicle' import { getRoleNameById } from '../change-operator-of-vehicle.utils' @@ -8,12 +8,14 @@ export type ApplicationRejectedSms = ( application: Application, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => SmsMessage export const generateApplicationRejectedSms: ApplicationRejectedSms = ( application, recipient, rejectedBy, + rejectType, ) => { const answers = application.answers as ChangeOperatorOfVehicleAnswers const permno = answers?.pickVehicle?.plate @@ -26,11 +28,16 @@ export const generateApplicationRejectedSms: ApplicationRejectedSms = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = `Beiðni um breytingu á umráðamönnum á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki: ` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += `${rejectedByStr}. Nánari upplýsingar á island.is/umsoknir. ` + return { phoneNumber: recipient.phone || '', - message: - `Beiðni um breytingu á umráðamönnum á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki: ` + - `${rejectedByStr}. ` + - `Nánari upplýsingar á island.is/umsoknir. `, + message: message, } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/types.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/types.ts index 2371c2f7e6ea..e9491c3c22b8 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/types.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/change-operator-of-vehicle/types.ts @@ -12,3 +12,8 @@ export interface EmailRecipient { role: EmailRole approved?: boolean } + +export enum RejectType { + REJECT, + DELETE, +} diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/emailGenerators/applicationRejectedEmail.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/emailGenerators/applicationRejectedEmail.ts index 7dfb7a43f00a..a04f6ecb4dd3 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/emailGenerators/applicationRejectedEmail.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/emailGenerators/applicationRejectedEmail.ts @@ -1,7 +1,7 @@ import { TransferOfVehicleOwnershipAnswers } from '@island.is/application/templates/transport-authority/transfer-of-vehicle-ownership' import { Message } from '@island.is/email-service' import { EmailTemplateGeneratorProps } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { getRoleNameById } from '../transfer-of-vehicle-ownership.utils' import { pathToAsset } from '../transfer-of-vehicle-ownership.utils' import { ApplicationConfigurations } from '@island.is/application/types' @@ -10,12 +10,14 @@ export type ApplicationRejectedEmail = ( props: EmailTemplateGeneratorProps, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => Message export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( props, recipient, rejectedBy, + rejectType, ): Message => { const { application, @@ -33,6 +35,21 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = + `Góðan dag,

` + + `Beiðni um eigendaskipti á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki:` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += + `
` + + `
  • ${rejectedByStr}

` + + `Til þess að skrá eigendaskiptin rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + + `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um eigendaskipti sem skilað hefur verið inn til Samgöngustofu á pappír.
` + + `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.` + return { from: { name: email.sender, @@ -64,13 +81,7 @@ export const generateApplicationRejectedEmail: ApplicationRejectedEmail = ( { component: 'Copy', context: { - copy: - `Góðan dag,

` + - `Beiðni um eigendaskipti á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki:
` + - `
  • ${rejectedByStr}

` + - `Til þess að skrá eigendaskiptin rafrænt verður að byrja ferlið að upp á nýtt á umsóknarvef island.is: island.is/umsoknir, ásamt því að allir aðilar þurfa að staðfesta rafrænt innan gefins tímafrests.
` + - `Þessi tilkynning á aðeins við um rafræna umsókn af umsóknarvef island.is en ekki um eigendaskipti sem skilað hefur verið inn til Samgöngustofu á pappír.
` + - `Vinsamlegast hafið samband við Þjónustuver Samgöngustofu (afgreidsla@samgongustofa.is) ef nánari upplýsinga er þörf.`, + copy: message, }, }, { diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/smsGenerators/applicationRejectedSms.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/smsGenerators/applicationRejectedSms.ts index bb1f60772d0f..ffc8dd664cdf 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/smsGenerators/applicationRejectedSms.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/smsGenerators/applicationRejectedSms.ts @@ -1,5 +1,5 @@ import { SmsMessage } from '../../../../../types' -import { EmailRecipient } from '../types' +import { EmailRecipient, RejectType } from '../types' import { Application } from '@island.is/application/types' import { TransferOfVehicleOwnershipAnswers } from '@island.is/application/templates/transport-authority/transfer-of-vehicle-ownership' import { getRoleNameById } from '../transfer-of-vehicle-ownership.utils' @@ -8,12 +8,14 @@ export type ApplicationRejectedSms = ( application: Application, recipient: EmailRecipient, rejectedBy: EmailRecipient | undefined, + rejectType: RejectType, ) => SmsMessage export const generateApplicationRejectedSms: ApplicationRejectedSms = ( application, recipient, rejectedBy, + rejectType, ) => { const answers = application.answers as TransferOfVehicleOwnershipAnswers const permno = answers?.pickVehicle?.plate @@ -26,11 +28,16 @@ export const generateApplicationRejectedSms: ApplicationRejectedSms = ( rejectedBy.ssn } (${getRoleNameById(rejectedBy.role)})` + let message = `Beiðni um eigendaskipti á ökutækinu ${permno} hefur verið afturkölluð, ` + if (rejectType === RejectType.REJECT) { + message += `þar sem eftirfarandi aðilar staðfestu ekki: ` + } else if (rejectType === RejectType.DELETE) { + message += `þar sem seljandinn eyddi umsókn:` + } + message += `${rejectedByStr}. Nánari upplýsingar á island.is/umsoknir. ` + return { phoneNumber: recipient.phone || '', - message: - `Beiðni um eigendaskipti á ökutækinu ${permno} hefur verið afturkölluð þar sem eftirfarandi aðilar staðfestu ekki: ` + - `${rejectedByStr}. ` + - `Nánari upplýsingar á island.is/umsoknir. `, + message: message, } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/transfer-of-vehicle-ownership.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/transfer-of-vehicle-ownership.service.ts index 0607ef16569a..7f31c0891d47 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/transfer-of-vehicle-ownership.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/transfer-of-vehicle-ownership.service.ts @@ -14,7 +14,7 @@ import { generateApplicationSubmittedSms, generateApplicationRejectedSms, } from './smsGenerators' -import { EmailRecipient, EmailRole } from './types' +import { EmailRecipient, EmailRole, RejectType } from './types' import { getAllRoles, getRecipients, @@ -455,14 +455,25 @@ export class TransferOfVehicleOwnershipService extends BaseTemplateApiService { } } - async rejectApplication({ - application, - auth, - }: TemplateApiModuleActionProps): Promise { + async rejectApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.REJECT) + } + + async deleteApplication(props: TemplateApiModuleActionProps): Promise { + return this.doRejectApplication(props, RejectType.DELETE) + } + + private async doRejectApplication( + { application, auth }: TemplateApiModuleActionProps, + rejectType: RejectType, + ): Promise { // 1. Delete charge so that the seller gets reimburshed - const chargeId = getPaymentIdFromExternalData(application) - if (chargeId) { - await this.chargeFjsV2ClientService.deleteCharge(chargeId) + // Note: not necessary on delete, since that is done in the shared delete function + if (rejectType !== RejectType.DELETE) { + const chargeId = getPaymentIdFromExternalData(application) + if (chargeId) { + await this.chargeFjsV2ClientService.deleteCharge(chargeId) + } } // 2. Notify everyone in the process that the application has been withdrawn @@ -482,13 +493,14 @@ export class TransferOfVehicleOwnershipService extends BaseTemplateApiService { props, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) .catch((e) => { this.logger.error( `Error sending email about rejectApplication in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) @@ -502,6 +514,7 @@ export class TransferOfVehicleOwnershipService extends BaseTemplateApiService { application, recipientList[i], rejectedByRecipient, + rejectType, ), application, ) @@ -509,7 +522,7 @@ export class TransferOfVehicleOwnershipService extends BaseTemplateApiService { this.logger.error( `Error sending sms about rejectApplication to a phonenumber in application: ID: ${application.id}, - role: ${recipientList[i].role}`, + role: ${recipientList[i].role} (${rejectType})`, e, ) }) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/types.ts b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/types.ts index cf3077ae8da1..fa7e8ec891f2 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/types.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/transport-authority/transfer-of-vehicle-ownership/types.ts @@ -14,3 +14,8 @@ export interface EmailRecipient { role: EmailRole approved?: boolean } + +export enum RejectType { + REJECT, + DELETE, +} diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/ChangeCoOwnerOfVehicleTemplate.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/ChangeCoOwnerOfVehicleTemplate.ts index 0ac37ef8ef6d..2837bd7bb640 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/ChangeCoOwnerOfVehicleTemplate.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/lib/ChangeCoOwnerOfVehicleTemplate.ts @@ -199,6 +199,9 @@ const template: ApplicationTemplate< pruneInDaysAtMidnight(application, 7), shouldDeleteChargeIfPaymentFulfilled: true, }, + onDelete: defineTemplateApi({ + action: ApiActions.deleteApplication, + }), roles: [ { id: Roles.APPLICANT, diff --git a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/shared/constants.ts b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/shared/constants.ts index 98c3166a29d7..ae14fa5832e6 100644 --- a/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/shared/constants.ts +++ b/libs/application/templates/transport-authority/change-co-owner-of-vehicle/src/shared/constants.ts @@ -3,4 +3,5 @@ export enum ApiActions { rejectApplication = 'rejectApplication', submitApplication = 'submitApplication', validateApplication = 'validateApplication', + deleteApplication = 'deleteApplication', } diff --git a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/ChangeOperatorOfVehicleTemplate.ts b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/ChangeOperatorOfVehicleTemplate.ts index ef0322b00fed..1d5144b1d48b 100644 --- a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/ChangeOperatorOfVehicleTemplate.ts +++ b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/lib/ChangeOperatorOfVehicleTemplate.ts @@ -201,6 +201,9 @@ const template: ApplicationTemplate< pruneInDaysAtMidnight(application, 7), shouldDeleteChargeIfPaymentFulfilled: true, }, + onDelete: defineTemplateApi({ + action: ApiActions.deleteApplication, + }), roles: [ { id: Roles.APPLICANT, diff --git a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/shared/constants.ts b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/shared/constants.ts index ab26b314a748..a8934dac6f6a 100644 --- a/libs/application/templates/transport-authority/change-operator-of-vehicle/src/shared/constants.ts +++ b/libs/application/templates/transport-authority/change-operator-of-vehicle/src/shared/constants.ts @@ -3,4 +3,5 @@ export enum ApiActions { initReview = 'initReview', rejectApplication = 'rejectApplication', submitApplication = 'submitApplication', + deleteApplication = 'deleteApplication', } diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/lib/TransferOfVehicleOwnershipTemplate.ts b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/lib/TransferOfVehicleOwnershipTemplate.ts index 21696404e7be..c77287a619be 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/lib/TransferOfVehicleOwnershipTemplate.ts +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/lib/TransferOfVehicleOwnershipTemplate.ts @@ -203,9 +203,13 @@ const template: ApplicationTemplate< action: ApiActions.addReview, shouldPersistToExternalData: true, }), + // Note: only re-validating because it is possible to add buyerCoOwners and buyerOperators in this step onExit: defineTemplateApi({ action: ApiActions.validateApplication, }), + onDelete: defineTemplateApi({ + action: ApiActions.deleteApplication, + }), roles: [ { id: Roles.APPLICANT, diff --git a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/shared/constants.ts b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/shared/constants.ts index 37948eb38598..81da9e3bab1c 100644 --- a/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/shared/constants.ts +++ b/libs/application/templates/transport-authority/transfer-of-vehicle-ownership/src/shared/constants.ts @@ -4,4 +4,5 @@ export enum ApiActions { addReview = 'addReview', rejectApplication = 'rejectApplication', submitApplication = 'submitApplication', + deleteApplication = 'deleteApplication', } From 369a35bc4cffb9e673b897c7f97f470c1d70a992 Mon Sep 17 00:00:00 2001 From: HjorturJ <34068269+HjorturJ@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:11:09 +0000 Subject: [PATCH 4/5] chore(application-system): More refactoring old s3 stuff (#16682) * Replacing more old s3 stuff * more replacing older stuff * chore: nx format:write update dirty files * replacing some weird imports * Fixing a few missteps * fixing a test suite * undoing changes to file.service.ts in judicial backend * undoing more judicial system changes * removing some more unused imports of aws sdk v2 * Addressing coderabbitai comments * undoing some coderabbitai suggestions that i cant make work * chore: nx format:write update dirty files * undoing accidental change to return type in file upload resolver * chore: nx format:write update dirty files * Removing unused s3 function after refactoring * Adding content type to education upload * chore: nx format:write update dirty files * adjusting content type and instance check * chore: nx format:write update dirty files * testing if including a change in the front end will help my deployment issues+ * undoing useless front end change * changing error logging in education service * chore: nx format:write update dirty files * removing unneeded await --------- Co-authored-by: andes-it Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../application/template-api.service.ts | 2 +- .../education/src/lib/education.module.ts | 4 +- .../education/src/lib/education.service.ts | 29 ++++- .../education/src/lib/education.spec.ts | 4 +- .../domains/education/src/lib/s3.service.ts | 69 ---------- .../src/lib/file-upload.resolver.ts | 4 +- .../shared/services/attachment-s3.service.ts | 110 ++++++++++++---- .../src/lib/modules/shared/shared.service.ts | 118 +----------------- .../accident-notification.service.spec.ts | 12 -- .../attachments/attachment-s3.service.ts | 31 +---- .../data-protection-complaint.module.ts | 2 + .../data-protection-complaint.service.ts | 6 +- .../citizenship/citizenship.service.ts | 4 +- .../financial-statements-inao.module.ts | 2 + .../financial-statements-inao.service.ts | 44 +++---- .../general-fishing-license.module.ts | 3 +- .../general-fishing-license.service.ts | 16 ++- .../health-insurance/bucket/bucket.service.ts | 45 ------- .../health-insurance.module.ts | 6 +- .../health-insurance.service.ts | 6 +- .../health-insurance.utils.ts | 13 +- .../university/university.service.ts | 6 +- .../src/lib/types/index.ts | 2 +- .../src/lib/file-storage.module.ts | 2 + .../src/lib/file-storage.service.spec.ts | 9 +- .../src/lib/file-storage.service.ts | 41 +++--- libs/nest/aws/src/lib/s3.service.spec.ts | 27 ++-- libs/nest/aws/src/lib/s3.service.ts | 109 +++++++++++++--- package.json | 1 + yarn.lock | 18 +++ 30 files changed, 336 insertions(+), 409 deletions(-) delete mode 100644 libs/api/domains/education/src/lib/s3.service.ts delete mode 100644 libs/application/template-api-modules/src/lib/modules/templates/health-insurance/bucket/bucket.service.ts diff --git a/apps/application-system/api/src/app/modules/application/template-api.service.ts b/apps/application-system/api/src/app/modules/application/template-api.service.ts index fb101db72327..fa75509e83b1 100644 --- a/apps/application-system/api/src/app/modules/application/template-api.service.ts +++ b/apps/application-system/api/src/app/modules/application/template-api.service.ts @@ -24,7 +24,7 @@ export class TemplateApiApplicationService extends BaseTemplateApiApplicationSer super() } - async saveAttachmentToApplicaton( + async saveAttachmentToApplication( application: ApplicationWithAttachments, fileName: string, buffer: Buffer, diff --git a/libs/api/domains/education/src/lib/education.module.ts b/libs/api/domains/education/src/lib/education.module.ts index 3cbbf8d1ad60..4f14e4649604 100644 --- a/libs/api/domains/education/src/lib/education.module.ts +++ b/libs/api/domains/education/src/lib/education.module.ts @@ -4,10 +4,10 @@ import { FeatureFlagModule } from '@island.is/nest/feature-flags' import { XRoadConfig, MMSApi } from '@island.is/clients/mms' import { FriggResolver, InnaResolver, MainResolver } from './graphql' import { EducationService } from './education.service' -import { S3Service } from './s3.service' import { InnaClientModule } from '@island.is/clients/inna' import { NationalRegistryV3ClientModule } from '@island.is/clients/national-registry-v3' import { FriggClientModule } from '@island.is/clients/mms/frigg' +import { AwsModule } from '@island.is/nest/aws' export interface Config { fileDownloadBucket: string @@ -23,7 +23,6 @@ export class EducationModule { FriggResolver, InnaResolver, MainResolver, - S3Service, EducationService, { provide: 'CONFIG', @@ -39,6 +38,7 @@ export class EducationModule { FeatureFlagModule, NationalRegistryV3ClientModule, FriggClientModule, + AwsModule, ], exports: [], } diff --git a/libs/api/domains/education/src/lib/education.service.ts b/libs/api/domains/education/src/lib/education.service.ts index ea20f287ed25..66e1c7e5b841 100644 --- a/libs/api/domains/education/src/lib/education.service.ts +++ b/libs/api/domains/education/src/lib/education.service.ts @@ -17,10 +17,11 @@ import { ExamResult, Student, } from './education.type' -import { S3Service } from './s3.service' import { getYearInterval } from './education.utils' import { NationalRegistryV3ClientService } from '@island.is/clients/national-registry-v3' import { isDefined } from '@island.is/shared/utils' +import { S3Service } from '@island.is/nest/aws' +import { LOGGER_PROVIDER, type Logger } from '@island.is/logging' @Injectable() export class EducationService { @@ -30,6 +31,7 @@ export class EducationService { @Inject('CONFIG') private readonly config: Config, private readonly nationalRegistryApi: NationalRegistryV3ClientService, + @Inject(LOGGER_PROVIDER) protected readonly logger: Logger, ) {} async getLicenses( @@ -53,11 +55,26 @@ export class EducationService { nationalId, licenseId, ) - - return this.s3Service.uploadFileFromStream(responseStream, { - fileName: uuid(), - bucket: this.config.fileDownloadBucket, - }) + try { + const fileLocation = await this.s3Service.uploadFile( + responseStream.body, + { bucket: this.config.fileDownloadBucket, key: uuid() }, + { + ContentType: + responseStream.headers?.get('content-type') || 'application/pdf', + }, + ) + + // Presigned URL expires in 65 seconds to allow for download initiation + const PRESIGNED_URL_EXPIRY = 65 + return await this.s3Service.getPresignedUrl( + fileLocation, + PRESIGNED_URL_EXPIRY, + ) + } catch (error) { + this.logger.error(`Failed to process PDF license:`, { error, licenseId }) + return null + } } async getFamily(nationalId: string): Promise> { diff --git a/libs/api/domains/education/src/lib/education.spec.ts b/libs/api/domains/education/src/lib/education.spec.ts index 44255097bc92..6bc726e39e58 100644 --- a/libs/api/domains/education/src/lib/education.spec.ts +++ b/libs/api/domains/education/src/lib/education.spec.ts @@ -15,7 +15,6 @@ import { ADULT_STUDENT1, } from './__mock-data__/my-family' import { MMSApi } from '@island.is/clients/mms' -import { S3Service } from './s3.service' import { NationalRegistryV3ClientConfig, NationalRegistryV3ClientModule, @@ -24,6 +23,7 @@ import { import { Student } from './education.type' import { ConfigModule } from '@nestjs/config' import { XRoadConfig } from '@island.is/nest/config' +import { AwsModule } from '@island.is/nest/aws' const config = { fileDownloadBucket: '', @@ -39,13 +39,13 @@ describe('EducationService', () => { imports: [ LoggingModule, NationalRegistryV3ClientModule, + AwsModule, ConfigModule.forRoot({ isGlobal: true, load: [XRoadConfig, NationalRegistryV3ClientConfig], }), ], providers: [ - S3Service, { provide: MMSApi, useValue: new MMSApi(config.xroad), diff --git a/libs/api/domains/education/src/lib/s3.service.ts b/libs/api/domains/education/src/lib/s3.service.ts deleted file mode 100644 index f49a723e6c1b..000000000000 --- a/libs/api/domains/education/src/lib/s3.service.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Injectable } from '@nestjs/common' -import { Inject } from '@nestjs/common' -import { S3 } from 'aws-sdk' -import { Response } from 'node-fetch' -import stream from 'stream' - -import type { Logger } from '@island.is/logging' -import { LOGGER_PROVIDER } from '@island.is/logging' - -type S3Location = { - fileName: string - bucket: string -} - -type FileUpload = { - passThrough: stream.PassThrough - promise: Promise -} - -@Injectable() -export class S3Service { - private readonly s3: S3 - - constructor( - @Inject(LOGGER_PROVIDER) - private readonly logger: Logger, - ) { - this.s3 = new S3({ apiVersion: '2006-03-01' }) - } - - private uploadFromStream( - fileResponse: Response, - { fileName, bucket }: S3Location, - ): FileUpload { - const passThrough = new stream.PassThrough() - const promise = this.s3 - .upload({ - Bucket: bucket, - Key: fileName, - ContentType: 'application/pdf', - Body: passThrough, - }) - .promise() - return { passThrough, promise } - } - - async uploadFileFromStream( - stream: Response, - s3Location: S3Location, - ): Promise { - const { passThrough, promise } = this.uploadFromStream(stream, s3Location) - - stream.body.pipe(passThrough) - - return promise - .then((result) => { - const oneMinutePlus = 65 // leave extra 5 seconds for network delay - return this.s3.getSignedUrlPromise('getObject', { - Bucket: s3Location.bucket, - Key: result.Key, - Expires: oneMinutePlus, - }) - }) - .catch((err) => { - this.logger.error(err) - return null - }) - } -} diff --git a/libs/api/domains/file-upload/src/lib/file-upload.resolver.ts b/libs/api/domains/file-upload/src/lib/file-upload.resolver.ts index fa2d482c50f5..e9c9536af0da 100644 --- a/libs/api/domains/file-upload/src/lib/file-upload.resolver.ts +++ b/libs/api/domains/file-upload/src/lib/file-upload.resolver.ts @@ -1,7 +1,7 @@ import { Args, Resolver, Mutation } from '@nestjs/graphql' -import { S3 } from 'aws-sdk' import { PresignedPost } from './presignedPost.model' import { FileStorageService } from '@island.is/file-storage' +import { PresignedPost as S3PresignedPost } from '@aws-sdk/s3-presigned-post' @Resolver() export class FileUploadResolver { @@ -10,7 +10,7 @@ export class FileUploadResolver { @Mutation(() => PresignedPost) createUploadUrl( @Args('filename') filename: string, - ): Promise { + ): Promise { return this.fileStorageService.generatePresignedPost(filename) } } diff --git a/libs/application/template-api-modules/src/lib/modules/shared/services/attachment-s3.service.ts b/libs/application/template-api-modules/src/lib/modules/shared/services/attachment-s3.service.ts index f1b5adde4890..be0ffebce113 100644 --- a/libs/application/template-api-modules/src/lib/modules/shared/services/attachment-s3.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/shared/services/attachment-s3.service.ts @@ -1,9 +1,12 @@ import { getValueViaPath } from '@island.is/application/core' -import { ApplicationWithAttachments as Application } from '@island.is/application/types' -import { S3 } from 'aws-sdk' -import AmazonS3URI from 'amazon-s3-uri' +import { ApplicationWithAttachments } from '@island.is/application/types' import { logger } from '@island.is/logging' -import { Injectable } from '@nestjs/common' +import { Inject, Injectable } from '@nestjs/common' +import { S3Service } from '@island.is/nest/aws' +import { ApplicationService } from '@island.is/application/api/core' +import { sharedModuleConfig } from '../shared.config' +import { ConfigType } from '@nestjs/config' +import { uuid } from 'uuidv4' export interface AttachmentData { key: string @@ -14,13 +17,15 @@ export interface AttachmentData { @Injectable() export class AttachmentS3Service { - private readonly s3: AWS.S3 - constructor() { - this.s3 = new S3() - } + constructor( + private readonly s3Service: S3Service, + @Inject(sharedModuleConfig.KEY) + private config: ConfigType, + private readonly applicationService: ApplicationService, + ) {} public async getFiles( - application: Application, + application: ApplicationWithAttachments, attachmentAnswerKeys: string[], ): Promise { const attachments: AttachmentData[] = [] @@ -43,7 +48,7 @@ export class AttachmentS3Service { name: string }>, answerKey: string, - application: Application, + application: ApplicationWithAttachments, ): Promise { return await Promise.all( answers.map(async ({ key, name }) => { @@ -58,30 +63,81 @@ export class AttachmentS3Service { return { key: '', fileContent: '', answerKey, fileName: '' } } const fileContent = - (await this.getApplicationFilecontentAsBase64(url)) ?? '' + (await this.s3Service.getFileContent(url, 'base64')) ?? '' return { key, fileContent, answerKey, fileName: name } }), ) } - private async getApplicationFilecontentAsBase64( + async addAttachment( + application: ApplicationWithAttachments, fileName: string, - ): Promise { - const { bucket, key } = AmazonS3URI(fileName) - const uploadBucket = bucket - try { - const file = await this.s3 - .getObject({ - Bucket: uploadBucket, - Key: key, - }) - .promise() - const fileContent = file.Body as Buffer - return fileContent?.toString('base64') - } catch (error) { - logger.error(error) - return undefined + buffer: Buffer, + uploadParameters?: { + ContentType?: string + ContentDisposition?: string + ContentEncoding?: string + }, + ): Promise { + return this.saveAttachmentToApplication( + application, + fileName, + buffer, + uploadParameters, + ) + } + + async saveAttachmentToApplication( + application: ApplicationWithAttachments, + fileName: string, + buffer: Buffer, + uploadParameters?: { + ContentType?: string + ContentDisposition?: string + ContentEncoding?: string + }, + ): Promise { + const uploadBucket = this.config.templateApi.attachmentBucket + if (!uploadBucket) throw new Error('No attachment bucket configured') + + const fileId = uuid() + const attachmentKey = `${fileId}-${fileName}` + const s3key = `${application.id}/${attachmentKey}` + const url = await this.s3Service.uploadFile( + buffer, + { bucket: uploadBucket, key: s3key }, + uploadParameters, + ) + + await this.applicationService.update(application.id, { + attachments: { + ...(application.attachments || {}), + [attachmentKey]: url, + }, + }) + + return attachmentKey + } + + async getAttachmentUrl( + application: ApplicationWithAttachments, + attachmentKey: string, + expiration: number, + ): Promise { + if (expiration <= 0) { + throw new Error('Expiration must be positive') } + const fileName = ( + application.attachments as { + [key: string]: string + } + )[attachmentKey] + + if (!fileName) { + throw new Error('Attachment not found') + } + + return this.s3Service.getPresignedUrl(fileName, expiration) } } diff --git a/libs/application/template-api-modules/src/lib/modules/shared/shared.service.ts b/libs/application/template-api-modules/src/lib/modules/shared/shared.service.ts index 97ad329e2b42..64fdabb796a1 100644 --- a/libs/application/template-api-modules/src/lib/modules/shared/shared.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/shared/shared.service.ts @@ -3,7 +3,6 @@ import { ConfigType } from '@nestjs/config' import { EmailService } from '@island.is/email-service' import { Application, - ApplicationWithAttachments, GraphqlGatewayResponse, } from '@island.is/application/types' import { @@ -16,8 +15,6 @@ import { import type { Logger } from '@island.is/logging' import { LOGGER_PROVIDER } from '@island.is/logging' import { SmsService } from '@island.is/nova-sms' -import { S3 } from 'aws-sdk' -import AmazonS3URI from 'amazon-s3-uri' import { PaymentService } from '@island.is/application/api/payment' import { User } from '@island.is/auth-nest-tools' import { ExtraData } from '@island.is/clients/charge-fjs-v2' @@ -25,11 +22,9 @@ import { sharedModuleConfig } from './shared.config' import { ApplicationService } from '@island.is/application/api/core' import jwt from 'jsonwebtoken' import { uuid } from 'uuidv4' -import { S3Service } from '@island.is/nest/aws' @Injectable() export class SharedTemplateApiService { - s3: S3 constructor( @Inject(LOGGER_PROVIDER) private readonly logger: Logger, @@ -41,10 +36,7 @@ export class SharedTemplateApiService { private config: ConfigType, private readonly applicationService: ApplicationService, private readonly paymentService: PaymentService, - private readonly s3Service: S3Service, - ) { - this.s3 = new S3() - } + ) {} async createAssignToken(application: Application, expiresIn: number) { const token = await this.createToken( @@ -197,92 +189,6 @@ export class SharedTemplateApiService { return this.paymentService.getStatus(user, applicationId) } - async addAttachment( - application: ApplicationWithAttachments, - fileName: string, - buffer: Buffer, - uploadParameters?: { - ContentType?: string - ContentDisposition?: string - ContentEncoding?: string - }, - ): Promise { - return this.saveAttachmentToApplicaton( - application, - fileName, - buffer, - uploadParameters, - ) - } - - async getS3File( - application: ApplicationWithAttachments, - attachmentKey: string, - ) { - const fileName = ( - application.attachments as { - [key: string]: string - } - )[attachmentKey] - const { bucket, key } = AmazonS3URI(fileName) - const file = await this.s3 - .getObject({ - Bucket: bucket, - Key: key, - }) - .promise() - return file - } - - async getAttachmentContentAsBase64( - application: ApplicationWithAttachments, - attachmentKey: string, - ): Promise { - const fileContent = (await this.getS3File(application, attachmentKey)) - ?.Body as Buffer - return fileContent?.toString('base64') || '' - } - - async getAttachmentContentAsBlob( - application: ApplicationWithAttachments, - attachmentKey: string, - ): Promise { - const file = await this.getS3File(application, attachmentKey) - return new Blob([file.Body as ArrayBuffer], { type: file.ContentType }) - } - - async saveAttachmentToApplicaton( - application: ApplicationWithAttachments, - fileName: string, - buffer: Buffer, - uploadParameters?: { - ContentType?: string - ContentDisposition?: string - ContentEncoding?: string - }, - ): Promise { - const uploadBucket = this.config.templateApi.attachmentBucket - if (!uploadBucket) throw new Error('No attachment bucket configured') - - const fileId = uuid() - const attachmentKey = `${fileId}-${fileName}` - const s3key = `${application.id}/${attachmentKey}` - const url = await this.s3Service.uploadFile( - buffer, - { bucket: uploadBucket, key: s3key }, - uploadParameters, - ) - - await this.applicationService.update(application.id, { - attachments: { - ...application.attachments, - [attachmentKey]: url, - }, - }) - - return attachmentKey - } - async storeNonceForApplication(application: Application): Promise { const nonce = uuid() @@ -314,26 +220,4 @@ export class SharedTemplateApiService { ) return token } - - async getAttachmentUrl( - application: ApplicationWithAttachments, - attachmentKey: string, - expiration: number, - ): Promise { - if (expiration <= 0) { - return Promise.reject('expiration must be positive') - } - const fileName = ( - application.attachments as { - [key: string]: string - } - )[attachmentKey] - const { bucket, key } = AmazonS3URI(fileName) - - return this.s3.getSignedUrlPromise('getObject', { - Bucket: bucket, - Key: key, - Expires: expiration, - }) - } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification.service.spec.ts b/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification.service.spec.ts index a13ae6180f2b..68dc20582618 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification.service.spec.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification.service.spec.ts @@ -8,7 +8,6 @@ import { AccidentNotificationService } from './accident-notification.service' import { AccidentNotificationAttachmentProvider } from './attachments/applicationAttachmentProvider' import { ApplicationAttachmentService } from './attachments/applicationAttachment.service' import { ACCIDENT_NOTIFICATION_CONFIG } from './config' -import { S3 } from 'aws-sdk' import { S3Service } from '@island.is/nest/aws' import { SmsService } from '@island.is/nova-sms' import { PaymentService } from '@island.is/application/api/payment' @@ -51,13 +50,6 @@ class MockSmsService { } } -const S3Instance = { - upload: jest.fn().mockReturnThis(), - promise: jest.fn(), - deleteObject: jest.fn().mockReturnThis(), - getObject: jest.fn().mockReturnThis(), -} - describe('AccidentNotificationService', () => { let accidentNotificationService: AccidentNotificationService let s3Service: S3Service @@ -109,10 +101,6 @@ describe('AccidentNotificationService', () => { withMiddleware: jest.fn().mockReturnThis(), })), }, - { - provide: S3, - useFactory: () => S3Instance, - }, { provide: ConfigService, useValue: {}, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/attachments/attachment-s3.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/attachments/attachment-s3.service.ts index 1be7582c8a7b..757484c023f9 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/attachments/attachment-s3.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/attachments/attachment-s3.service.ts @@ -1,9 +1,8 @@ import { getValueViaPath } from '@island.is/application/core' import { ApplicationWithAttachments as Application } from '@island.is/application/types' -import { S3 } from 'aws-sdk' -import AmazonS3URI from 'amazon-s3-uri' import { logger } from '@island.is/logging' import { Injectable } from '@nestjs/common' +import { S3Service } from '@island.is/nest/aws' export interface AttachmentData { key: string @@ -14,10 +13,7 @@ export interface AttachmentData { @Injectable() export class AttachmentS3Service { - private readonly s3: AWS.S3 - constructor() { - this.s3 = new S3() - } + constructor(private readonly s3Service: S3Service) {} public async getFiles( application: Application, @@ -65,31 +61,10 @@ export class AttachmentS3Service { return { key: '', fileContent: '', answerKey, fileName: '' } } const fileContent = - (await this.getApplicationFilecontentAsBase64(url)) ?? '' + (await this.s3Service.getFileContent(url, 'base64')) ?? '' return { key, fileContent, answerKey, fileName: name } }), ) } - - private async getApplicationFilecontentAsBase64( - fileName: string, - ): Promise { - const { bucket, key } = AmazonS3URI(fileName) - const uploadBucket = bucket - try { - const file = await this.s3 - .getObject({ - Bucket: uploadBucket, - Key: key, - }) - .promise() - const fileContent = file.Body as Buffer - return fileContent?.toString('base64') - } catch (error) { - logger.log('error ', error) - logger.error(error) - return undefined - } - } } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.module.ts b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.module.ts index 87480805b973..c080496a3311 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.module.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.module.ts @@ -10,12 +10,14 @@ import { FileStorageModule } from '@island.is/file-storage' import { ApplicationAttachmentProvider } from './attachments/providers/applicationAttachmentProvider' import { PdfFileProvider } from './attachments/providers/pdfFileProvider' import { AttachmentS3Service } from './attachments/attachment-s3.service' +import { AwsModule } from '@island.is/nest/aws' @Module({ imports: [ SharedTemplateAPIModule, FileStorageModule, ClientsDataProtectionComplaintModule, + AwsModule, ], providers: [ ApplicationAttachmentProvider, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.service.ts index f2c52cd40ace..93e8857f1bc4 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/data-protection-complaint/data-protection-complaint.service.ts @@ -9,9 +9,9 @@ import { LOGGER_PROVIDER } from '@island.is/logging' import type { Logger } from '@island.is/logging' import { PdfFileProvider } from './attachments/providers/pdfFileProvider' import { ApplicationAttachmentProvider } from './attachments/providers/applicationAttachmentProvider' -import { SharedTemplateApiService } from '../../shared' import { BaseTemplateApiService } from '../../base-template-api.service' import { ApplicationTypes } from '@island.is/application/types' +import { AttachmentS3Service } from '../../shared/services' @Injectable() export class DataProtectionComplaintService extends BaseTemplateApiService { @@ -21,7 +21,7 @@ export class DataProtectionComplaintService extends BaseTemplateApiService { private readonly tokenMiddleware: TokenMiddleware, private readonly applicationAttachmentProvider: ApplicationAttachmentProvider, private readonly pdfFileProvider: PdfFileProvider, - private readonly sharedService: SharedTemplateApiService, + private readonly attachmentService: AttachmentS3Service, ) { super(ApplicationTypes.DATA_PROTECTION_AUTHORITY_COMPLAINT) } @@ -59,7 +59,7 @@ export class DataProtectionComplaintService extends BaseTemplateApiService { const nowString = now.toISOString().replace(/:/g, '-') const complaintPdfFileName = `kvörtun-${nowString}.pdf` - const key = await this.sharedService.addAttachment( + const key = await this.attachmentService.addAttachment( application, complaintPdfFileName, complaintPdf.fileBuffer, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/directorate-of-immigration/citizenship/citizenship.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/directorate-of-immigration/citizenship/citizenship.service.ts index 5a2e462a78c9..9e8087e553fd 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/directorate-of-immigration/citizenship/citizenship.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/directorate-of-immigration/citizenship/citizenship.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common' import { SharedTemplateApiService } from '../../../shared' +import { AttachmentS3Service } from '../../../shared/services' import { TemplateApiModuleActionProps } from '../../../../types' import { BaseTemplateApiService } from '../../../base-template-api.service' import { @@ -32,6 +33,7 @@ import { ApplicantInformation } from './types' export class CitizenshipService extends BaseTemplateApiService { constructor( private readonly sharedTemplateAPIService: SharedTemplateApiService, + private readonly attachmentService: AttachmentS3Service, private readonly directorateOfImmigrationClient: DirectorateOfImmigrationClient, private readonly nationalRegistryApi: NationalRegistryClientService, ) { @@ -431,7 +433,7 @@ export class CitizenshipService extends BaseTemplateApiService { ): Promise<{ filename: string; fileUrl: string; countryId: string }[]> { return await Promise.all( attachments?.map(async (file) => { - const fileUrl = await this.sharedTemplateAPIService.getAttachmentUrl( + const fileUrl = await this.attachmentService.getAttachmentUrl( application, file.key, 300000, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.module.ts b/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.module.ts index 9d4de2899dfc..3c0fad6cbbab 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.module.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.module.ts @@ -7,6 +7,7 @@ import { Module } from '@nestjs/common' import { ConfigModule } from '@nestjs/config' import { SharedTemplateAPIModule } from '../../shared' import { FinancialStatementsInaoTemplateService } from './financial-statements-inao.service' +import { AwsModule } from '@island.is/nest/aws' @Module({ imports: [ @@ -15,6 +16,7 @@ import { FinancialStatementsInaoTemplateService } from './financial-statements-i load: [FinancialStatementsInaoClientConfig], }), FinancialStatementsInaoClientModule, + AwsModule, ], providers: [FinancialStatementsInaoTemplateService], exports: [FinancialStatementsInaoTemplateService], diff --git a/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.service.ts index 1d21f87122b1..fa89f321b22e 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/financial-statements-inao/financial-statements-inao.service.ts @@ -23,9 +23,6 @@ import { ApplicationWithAttachments as Application, } from '@island.is/application/types' import { getValueViaPath } from '@island.is/application/core' -import AmazonS3URI from 'amazon-s3-uri' - -import { S3 } from 'aws-sdk' import { mapValuesToIndividualtype, mapValuesToPartytype, @@ -33,6 +30,7 @@ import { } from './mappers/mapValuesToUsertype' import type { Logger } from '@island.is/logging' import { LOGGER_PROVIDER } from '@island.is/logging' +import { S3Service } from '@island.is/nest/aws' export interface AttachmentData { key: string @@ -56,16 +54,17 @@ export interface DataResponse { @Injectable() export class FinancialStatementsInaoTemplateService extends BaseTemplateApiService { - s3: S3 constructor( @Inject(LOGGER_PROVIDER) private logger: Logger, private financialStatementsClientService: FinancialStatementsInaoClientService, + private readonly s3Service: S3Service, ) { super(ApplicationTypes.FINANCIAL_STATEMENTS_INAO) - this.s3 = new S3() } - private async getAttachment(application: Application): Promise { + private async getAttachmentAsBase64( + application: Application, + ): Promise { const attachments: AttachmentData[] | undefined = getValueViaPath( application.answers, 'attachments.file', @@ -80,23 +79,22 @@ export class FinancialStatementsInaoTemplateService extends BaseTemplateApiServi )[attachmentKey] if (!fileName) { - return Promise.reject({}) + throw new Error( + `Attachment filename not found in application on attachment key: ${attachmentKey}`, + ) } - const { bucket, key } = AmazonS3URI(fileName) - - const uploadBucket = bucket try { - const file = await this.s3 - .getObject({ - Bucket: uploadBucket, - Key: key, - }) - .promise() - const fileContent = file.Body as Buffer - return fileContent?.toString('base64') || '' + const fileContent = await this.s3Service.getFileContent( + fileName, + 'base64', + ) + if (!fileContent) { + throw new Error(`File content not found for: ${fileName}`) + } + return fileContent } catch (error) { - throw new Error('Villa kom kom upp við að senda umsókn') + throw new Error(`Failed to retrieve attachment: ${error.message}`) } } @@ -139,7 +137,7 @@ export class FinancialStatementsInaoTemplateService extends BaseTemplateApiServi const fileName = noValueStatement ? undefined - : await this.getAttachment(application) + : await this.getAttachmentAsBase64(application) this.logger.info( `PostFinancialStatementForPersonalElection => clientNationalId: '${nationalId}', actorNationalId: '${ @@ -231,7 +229,7 @@ export class FinancialStatementsInaoTemplateService extends BaseTemplateApiServi ) as string const clientEmail = getValueViaPath(answers, 'about.email') as string - const fileName = await this.getAttachment(application) + const fileName = await this.getAttachmentAsBase64(application) const client = { nationalId: nationalId, @@ -306,7 +304,9 @@ export class FinancialStatementsInaoTemplateService extends BaseTemplateApiServi const file = getValueViaPath(answers, 'attachments.file') - const fileName = file ? await this.getAttachment(application) : undefined + const fileName = file + ? await this.getAttachmentAsBase64(application) + : undefined const client = { nationalId: nationalId, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.module.ts b/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.module.ts index 3d9ced39505f..29cb4bdd787f 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.module.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.module.ts @@ -2,9 +2,10 @@ import { Module } from '@nestjs/common' import { SharedTemplateAPIModule } from '../../shared' import { GeneralFishingLicenseService } from './general-fishing-license.service' import { FishingLicenseClientModule } from '@island.is/clients/fishing-license' +import { AwsModule } from '@island.is/nest/aws' @Module({ - imports: [SharedTemplateAPIModule, FishingLicenseClientModule], + imports: [SharedTemplateAPIModule, FishingLicenseClientModule, AwsModule], providers: [GeneralFishingLicenseService], exports: [GeneralFishingLicenseService], }) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.service.ts index b1de58d9c514..d66470a67f71 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/general-fishing-license/general-fishing-license.service.ts @@ -14,6 +14,7 @@ import { BaseTemplateApiService } from '../../base-template-api.service' import { ApplicationTypes } from '@island.is/application/types' import { TemplateApiError } from '@island.is/nest/problem' import { error } from '@island.is/application/templates/general-fishing-license' +import { S3Service } from '@island.is/nest/aws' @Injectable() export class GeneralFishingLicenseService extends BaseTemplateApiService { @@ -22,6 +23,7 @@ export class GeneralFishingLicenseService extends BaseTemplateApiService { private readonly sharedTemplateAPIService: SharedTemplateApiService, private readonly fishingLicenceApi: FishingLicenseService, private readonly umsoknirApi: UmsoknirApi, + private readonly s3Service: S3Service, ) { super(ApplicationTypes.GENERAL_FISHING_LICENSE) } @@ -87,13 +89,17 @@ export class GeneralFishingLicenseService extends BaseTemplateApiService { 'fishingLicenseFurtherInformation.attachments', [], ) as Array<{ key: string; name: string }> + + const attachmentDict = application.attachments as { + [key: string]: string + } const attachments = await Promise.all( attachmentsRaw?.map(async (a) => { - const vidhengiBase64 = - await this.sharedTemplateAPIService.getAttachmentContentAsBase64( - application, - a.key, - ) + const filename = attachmentDict[a.key] + const vidhengiBase64 = await this.s3Service.getFileContent( + filename, + 'base64', + ) return { vidhengiBase64, vidhengiNafn: a.name, diff --git a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/bucket/bucket.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/bucket/bucket.service.ts deleted file mode 100644 index dbad00ed1134..000000000000 --- a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/bucket/bucket.service.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common' -import * as AWS from 'aws-sdk' -import * as S3 from 'aws-sdk/clients/s3' -import type { Logger } from '@island.is/logging' -import { LOGGER_PROVIDER } from '@island.is/logging' -import AmazonS3URI from 'amazon-s3-uri' - -@Injectable() -export class BucketService { - private s3 = new AWS.S3({ apiVersion: '2006-03-01' }) - constructor(@Inject(LOGGER_PROVIDER) private logger: Logger) {} - - async getFileContentAsBase64(filename: string): Promise { - this.logger.info('getFileContent base64...') - - const { region, bucket, key } = AmazonS3URI(filename) - const sm = await this.getFile(key, bucket) - if (sm.Body) { - this.logger.info('found file:' + key) - return sm.Body.toString('base64') - } else { - throw new Error('error getting file:' + key) - } - } - - async getFile( - filename: string, - bucketName: string, - ): Promise { - this.logger.info('get bucket file:' + filename) - return new Promise((resolve, reject) => { - const params = { - Bucket: bucketName, - Key: filename, - } - this.s3.getObject(params, (err, data) => { - if (err) { - reject(err) - } else { - resolve(data) - } - }) - }) - } -} diff --git a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.module.ts b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.module.ts index d566dc3f38f5..e8bf14808144 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.module.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.module.ts @@ -6,11 +6,11 @@ import { SharedTemplateAPIModule } from '../../shared' // Here you import your module service import { HealthInsuranceService } from './health-insurance.service' import { HealthInsuranceV2ClientModule } from '@island.is/clients/icelandic-health-insurance/health-insurance' -import { BucketService } from './bucket/bucket.service' +import { AwsModule } from '@island.is/nest/aws' @Module({ - imports: [HealthInsuranceV2ClientModule, SharedTemplateAPIModule], - providers: [HealthInsuranceService, BucketService], + imports: [HealthInsuranceV2ClientModule, SharedTemplateAPIModule, AwsModule], + providers: [HealthInsuranceService], exports: [HealthInsuranceService], }) export class HealthInsuranceModule {} diff --git a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.service.ts index fe5ff84e7a58..97110c11f18d 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.service.ts @@ -10,20 +10,20 @@ import { DocumentApi, PersonApi, } from '@island.is/clients/icelandic-health-insurance/health-insurance' -import { BucketService } from './bucket/bucket.service' import { BaseTemplateApiService } from '../../base-template-api.service' import { ApplicationTypes } from '@island.is/application/types' import format from 'date-fns/format' import is from 'date-fns/locale/is' import { TemplateApiError } from '@island.is/nest/problem' import { coreErrorMessages } from '@island.is/application/core/messages' +import { S3Service } from '@island.is/nest/aws' @Injectable() export class HealthInsuranceService extends BaseTemplateApiService { constructor( private documentApi: DocumentApi, - private bucketService: BucketService, private personApi: PersonApi, + private readonly s3Service: S3Service, ) { super(ApplicationTypes.HEALTH_INSURANCE) } @@ -64,7 +64,7 @@ export class HealthInsuranceService extends BaseTemplateApiService { const xml = await insuranceToXML( inputs.vistaskjal, inputs.attachmentNames, - this.bucketService, + this.s3Service, ) try { diff --git a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.utils.ts b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.utils.ts index b8d26ffcf71f..e0165c68cd87 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.utils.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/health-insurance/health-insurance.utils.ts @@ -5,7 +5,6 @@ import { logger } from '@island.is/logging' import { ApplicationWithAttachments as Application } from '@island.is/application/types' import { objectToXML } from '../../shared/shared.utils' import is from 'date-fns/locale/is' -import { BucketService } from './bucket/bucket.service' import format from 'date-fns/format' import { ApplyHealthInsuranceInputs, @@ -14,6 +13,7 @@ import { GetVistaSkjalBody, VistaSkjalInput, } from './types/health-insurance-types' +import { S3Service } from '@island.is/nest/aws' const formatDate = (date: Date) => { return format(new Date(date), 'yyyy-MM-dd', { @@ -34,7 +34,7 @@ const formatDate = (date: Date) => { export const insuranceToXML = async ( inputObj: VistaSkjalInput, attachmentNames: string[], - bucketService: BucketService, + s3Service: S3Service, ) => { logger.debug(`--- Starting to convert application to XML ---`) const vistaSkjalBody: GetVistaSkjalBody = { @@ -93,11 +93,14 @@ export const insuranceToXML = async ( } for (let i = 0; i < arrAttachments.length; i++) { const filename = arrAttachments[i] + const fileContent = await s3Service.getFileContent(filename, 'base64') + + if (!fileContent) + throw new Error(`Unable to fetch file content for: ${filename}`) + const fylgiskjal: Fylgiskjal = { heiti: filename, - innihald: await bucketService.getFileContentAsBase64( - attachmentNames[i], - ), + innihald: fileContent, } fylgiskjol.fylgiskjal.push(fylgiskjal) } diff --git a/libs/application/template-api-modules/src/lib/modules/templates/university/university.service.ts b/libs/application/template-api-modules/src/lib/modules/templates/university/university.service.ts index 68110b280cc2..13e456a549e4 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/university/university.service.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/university/university.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@nestjs/common' -import { SharedTemplateApiService } from '../../shared' import { TemplateApiModuleActionProps } from '../../../types' import { BaseTemplateApiService } from '../../base-template-api.service' import { @@ -32,11 +31,12 @@ import { } from '@island.is/application/templates/university' import { Auth, AuthMiddleware } from '@island.is/auth-nest-tools' import { InnaClientService } from '@island.is/clients/inna' +import { AttachmentS3Service } from '../../shared/services' @Injectable() export class UniversityService extends BaseTemplateApiService { constructor( - private readonly sharedTemplateAPIService: SharedTemplateApiService, + private readonly attachmentService: AttachmentS3Service, private readonly nationalRegistryApi: NationalRegistryClientService, private readonly programApi: ProgramApi, private readonly universityApi: UniversityApi, @@ -298,7 +298,7 @@ export class UniversityService extends BaseTemplateApiService { attachments?.map(async (file) => { return { fileName: file.name, - fileUrl: await this.sharedTemplateAPIService.getAttachmentUrl( + fileUrl: await this.attachmentService.getAttachmentUrl( application, file.key, expiry, diff --git a/libs/application/template-api-modules/src/lib/types/index.ts b/libs/application/template-api-modules/src/lib/types/index.ts index b934402f6731..c4640536863b 100644 --- a/libs/application/template-api-modules/src/lib/types/index.ts +++ b/libs/application/template-api-modules/src/lib/types/index.ts @@ -75,7 +75,7 @@ export type AttachmentEmailTemplateGenerator = ( @Injectable() export abstract class BaseTemplateApiApplicationService { - abstract saveAttachmentToApplicaton( + abstract saveAttachmentToApplication( application: ApplicationWithAttachments, fileName: string, buffer: Buffer, diff --git a/libs/file-storage/src/lib/file-storage.module.ts b/libs/file-storage/src/lib/file-storage.module.ts index 85de00a46897..ba7480ca14ec 100644 --- a/libs/file-storage/src/lib/file-storage.module.ts +++ b/libs/file-storage/src/lib/file-storage.module.ts @@ -1,7 +1,9 @@ import { Module } from '@nestjs/common' import { FileStorageService } from './file-storage.service' +import { AwsModule } from '@island.is/nest/aws' @Module({ + imports: [AwsModule], providers: [FileStorageService], exports: [FileStorageService], }) diff --git a/libs/file-storage/src/lib/file-storage.service.spec.ts b/libs/file-storage/src/lib/file-storage.service.spec.ts index dc4543713066..95342a1a462d 100644 --- a/libs/file-storage/src/lib/file-storage.service.spec.ts +++ b/libs/file-storage/src/lib/file-storage.service.spec.ts @@ -2,6 +2,7 @@ import { ConfigModule } from '@nestjs/config' import { Test } from '@nestjs/testing' import { FileStorageConfig } from './file-storage.configuration' import { FileStorageService } from './file-storage.service' +import { S3Service } from '@island.is/nest/aws' describe('FileStorageService', () => { let service: FileStorageService @@ -14,7 +15,13 @@ describe('FileStorageService', () => { load: [FileStorageConfig], }), ], - providers: [FileStorageService], + providers: [ + FileStorageService, + { + provide: S3Service, + useValue: {}, + }, + ], }).compile() service = module.get(FileStorageService) diff --git a/libs/file-storage/src/lib/file-storage.service.ts b/libs/file-storage/src/lib/file-storage.service.ts index 8059fb66b043..5cace94fd2c1 100644 --- a/libs/file-storage/src/lib/file-storage.service.ts +++ b/libs/file-storage/src/lib/file-storage.service.ts @@ -1,24 +1,23 @@ import { Inject, Injectable } from '@nestjs/common' -import * as AWS from 'aws-sdk' +import { S3Service } from '@island.is/nest/aws' import { uuid } from 'uuidv4' -import AmazonS3URI from 'amazon-s3-uri' import kebabCase from 'lodash/kebabCase' import { ConfigType } from '@nestjs/config' import { FileStorageConfig } from './file-storage.configuration' +import { PresignedPost } from '@aws-sdk/s3-presigned-post' const PRESIGNED_POST_EXPIRES = 1000 * 60 * 5 const SIGNED_GET_EXPIRES = 10 * 60 @Injectable() export class FileStorageService { - private s3 = new AWS.S3({ apiVersion: '2006-03-01' }) - constructor( @Inject(FileStorageConfig.KEY) private config: ConfigType, + private readonly s3Service: S3Service, ) {} - generatePresignedPost(filename: string): Promise { + generatePresignedPost(filename: string): Promise { if (!this.config.uploadBucket) { throw new Error('Upload bucket not configured.') } @@ -39,6 +38,7 @@ export class FileStorageService { const params = { Bucket: this.config.uploadBucket, + Key: key, Expires: PRESIGNED_POST_EXPIRES, Fields: { key, @@ -46,22 +46,11 @@ export class FileStorageService { conditions: [['content-length-range', 0, 10000000]], // Max 10MB } - return new Promise((resolve, reject) => { - this.s3.createPresignedPost(params, (err, data) => { - if (err) { - reject(err) - } else { - resolve(data) - } - }) - }) + return this.s3Service.createPresignedPost(params) } public generateSignedUrl(url: string): Promise { - const { bucket, key } = AmazonS3URI(url) - const params = { Bucket: bucket, Expires: SIGNED_GET_EXPIRES, Key: key } - - return this.s3.getSignedUrlPromise('getObject', params) + return this.s3Service.getPresignedUrl(url, SIGNED_GET_EXPIRES) } public getObjectUrl(key: string): string { @@ -76,15 +65,15 @@ export class FileStorageService { if (!this.config.uploadBucket) { throw new Error('Upload bucket not configured.') } + const region = await this.s3Service.getClientRegion() - const params = { - Key: destinationKey, - Bucket: destinationBucket, - CopySource: `${this.config.uploadBucket}/${sourceKey}`, - } - const region = this.s3.config.region - - await this.s3.copyObject(params).promise() + await this.s3Service.copyObject( + { + bucket: destinationBucket, + key: destinationKey, + }, + `${this.config.uploadBucket}/${sourceKey}`, + ) return `https://${destinationBucket}.s3-${region}.amazonaws.com/${destinationKey}` } } diff --git a/libs/nest/aws/src/lib/s3.service.spec.ts b/libs/nest/aws/src/lib/s3.service.spec.ts index 8f87dc3bf0ed..5a16618b671b 100644 --- a/libs/nest/aws/src/lib/s3.service.spec.ts +++ b/libs/nest/aws/src/lib/s3.service.spec.ts @@ -130,7 +130,7 @@ describe('S3Service', () => { expect(logger.error).toBeCalledTimes(1) expect(logger.error).toBeCalledWith( - 'Error occurred while checking if file exists in S3', + 'Error occurred while checking if file: y exists in S3 bucket: x', Error(), ) @@ -145,13 +145,13 @@ describe('S3Service', () => { expect(logger.error).toBeCalledTimes(1) expect(logger.error).toBeCalledWith( - 'Error occurred while checking if file exists in S3', + 'Error occurred while checking if file: y exists in S3 bucket: x', TypeError( "Cannot read properties of undefined (reading 'httpStatusCode')", ), ) - expect(result).toEqual(false) + expect(result).toBe(false) }) it.each([200, 204])( @@ -160,8 +160,9 @@ describe('S3Service', () => { const metadata = { httpStatusCode: code } s3Mock.on(DeleteObjectCommand).resolvesOnce({ $metadata: metadata }) - await s3Service.deleteObject({ bucket: 'x', key: 'y' }) + const result = await s3Service.deleteObject({ bucket: 'x', key: 'y' }) + expect(result).toBe(true) expect(logger.error).toBeCalledTimes(0) }, ) @@ -172,18 +173,30 @@ describe('S3Service', () => { const metadata = { httpStatusCode: code } s3Mock.on(DeleteObjectCommand).resolvesOnce({ $metadata: metadata }) - const act = () => s3Service.deleteObject({ bucket: 'x', key: 'y' }) + const result = await s3Service.deleteObject({ bucket: 'x', key: 'y' }) - await expect(act()).rejects.toThrow() + expect(result).toBe(false) expect(logger.error).toBeCalledTimes(1) expect(logger.error).toBeCalledWith( - 'Error occurred while deleting file from S3', + 'Error occurred while deleting file: y from S3 bucket: x', Error('Unexpected http response when deleting object from S3'), ) }, ) + it('should handle DeleteObjectCommand throwing an error', async () => { + s3Mock.on(DeleteObjectCommand).rejects(new Error('Network error')) + + const result = await s3Service.deleteObject({ bucket: 'x', key: 'y' }) + + expect(result).toBe(false) + expect(logger.error).toBeCalledWith( + 'Error occurred while deleting file: y from S3 bucket: x', + expect.any(Error), + ) + }) + it('should return correct bucket and key strings', async () => { const bucketKeyPair = { bucket: 'abc', key: 'def' } const fileUri = 'https://abc.s3.amazonaws.com/def' diff --git a/libs/nest/aws/src/lib/s3.service.ts b/libs/nest/aws/src/lib/s3.service.ts index 54cde417dc2a..caa898cd2218 100644 --- a/libs/nest/aws/src/lib/s3.service.ts +++ b/libs/nest/aws/src/lib/s3.service.ts @@ -1,8 +1,12 @@ import { + CopyObjectCommand, + CopyObjectCommandOutput, + CopyObjectRequest, DeleteObjectCommand, GetObjectCommand, GetObjectCommandOutput, HeadObjectCommand, + PutObjectCommandInput, S3Client, } from '@aws-sdk/client-s3' import AmazonS3URI from 'amazon-s3-uri' @@ -10,6 +14,12 @@ import { Inject, Injectable } from '@nestjs/common' import { getSignedUrl } from '@aws-sdk/s3-request-presigner' import { LOGGER_PROVIDER, type Logger } from '@island.is/logging' import { Upload } from '@aws-sdk/lib-storage' +import { + createPresignedPost, + PresignedPost, + PresignedPostOptions, +} from '@aws-sdk/s3-presigned-post' +import stream, { Readable } from 'stream' export interface BucketKeyPair { bucket: string @@ -25,6 +35,10 @@ export class S3Service { @Inject(LOGGER_PROVIDER) protected readonly logger: Logger, ) {} + public async getClientRegion(): Promise { + return this.s3Client.config.region() + } + public async getFile( BucketKeyPairOrFilename: BucketKeyPair | string, ): Promise { @@ -38,11 +52,32 @@ export class S3Service { ): Promise { const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) const result = await this.getFileResponse(bucket, key) - return await result?.Body?.transformToString(encoding) + return result?.Body?.transformToString(encoding) + } + + public async copyObject( + BucketKeyPairOrFilename: BucketKeyPair | string, + copySource: string, + ): Promise { + const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) + const input: CopyObjectRequest = { + Bucket: bucket, + Key: key, + CopySource: copySource, + } + try { + return await this.s3Client.send(new CopyObjectCommand(input)) + } catch (error) { + this.logger.error( + `Error occurred while copying file: ${key} to S3 bucket: ${bucket} from ${copySource}`, + error, + ) + throw error + } } public async uploadFile( - content: Buffer, + content: Buffer | NodeJS.ReadableStream, BucketKeyPairOrFilename: BucketKeyPair | string, uploadParameters?: { ContentType?: string @@ -51,27 +86,37 @@ export class S3Service { }, ): Promise { const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) - const uploadParams = { + const isStreaming = this.isReadableStream(content) + let uploadStream: stream.PassThrough | undefined + + if (isStreaming) uploadStream = new stream.PassThrough() + + const uploadParams: PutObjectCommandInput = { Bucket: bucket, Key: key, - Body: content, + Body: isStreaming ? uploadStream : content, ...uploadParameters, } try { - const parallelUploads3 = new Upload({ + const parallelUpload = new Upload({ client: this.s3Client, params: uploadParams, }) - const { Location: url } = await parallelUploads3.done() + if (isStreaming && uploadStream) content.pipe(uploadStream) + + const { Location: url } = await parallelUpload.done() if (!url) throw new Error('No location url found after uploading file to S3') return url } catch (error) { - this.logger.error('Error occurred while uploading file to S3', error) + this.logger.error( + `Error occurred while uploading file: ${key} to S3 bucket: ${bucket}`, + error, + ) throw error } } @@ -87,18 +132,32 @@ export class S3Service { const expiration = expirationOverride ?? oneMinute * 120 const command = new GetObjectCommand({ Bucket: bucket, Key: key }) - const url = await getSignedUrl(this.s3Client, command, { + return getSignedUrl(this.s3Client, command, { expiresIn: expiration, }) + } - return url + public async createPresignedPost( + params: PresignedPostOptions, + ): Promise { + try { + return await createPresignedPost(this.s3Client, params) + } catch (error) { + this.logger.error( + `An error occurred while trying to create a presigned post for file: ${params.Key} in bucket: ${params.Bucket}`, + error, + ) + throw new Error( + `An error occurred while trying to create a presigned post ${error.message}`, + ) + } } public async fileExists( BucketKeyPairOrFilename: BucketKeyPair | string, ): Promise { + const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) try { - const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) const command = new HeadObjectCommand({ Bucket: bucket, Key: key, @@ -115,7 +174,7 @@ export class S3Service { return false this.logger.error( - 'Error occurred while checking if file exists in S3', + `Error occurred while checking if file: ${key} exists in S3 bucket: ${bucket}`, error, ) return false @@ -124,9 +183,9 @@ export class S3Service { public async deleteObject( BucketKeyPairOrFilename: BucketKeyPair | string, - ): Promise { + ): Promise { + const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) try { - const { bucket, key } = this.getBucketKey(BucketKeyPairOrFilename) const result = await this.s3Client.send( new DeleteObjectCommand({ Bucket: bucket, @@ -140,9 +199,13 @@ export class S3Service { ) { throw new Error('Unexpected http response when deleting object from S3') } + return true } catch (error) { - this.logger.error('Error occurred while deleting file from S3', error) - throw error + this.logger.error( + `Error occurred while deleting file: ${key} from S3 bucket: ${bucket}`, + error, + ) + return false } } @@ -156,7 +219,10 @@ export class S3Service { try { return AmazonS3URI(BucketKeyPairOrFilename) } catch (error) { - this.logger.error('Invalid S3 URI provided', error) + this.logger.error( + `Invalid S3 URI provided: ${BucketKeyPairOrFilename}`, + error, + ) throw new Error('Invalid S3 URI provided') } } @@ -174,8 +240,17 @@ export class S3Service { }), ) } catch (error) { - this.logger.error('Error occurred while fetching file from S3', error) + this.logger.error( + `Error occurred while fetching file: ${key} from S3 bucket: ${bucket}`, + error, + ) return undefined } } + + private isReadableStream( + content: Buffer | NodeJS.ReadableStream, + ): content is NodeJS.ReadableStream { + return content instanceof Readable && typeof content.pipe === 'function' + } } diff --git a/package.json b/package.json index 655d9542310a..dcd042c6c891 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "@aws-sdk/client-sqs": "3.662.0", "@aws-sdk/credential-provider-node": "3.662.0", "@aws-sdk/lib-storage": "3.662.0", + "@aws-sdk/s3-presigned-post": "3.662.0", "@aws-sdk/s3-request-presigner": "3.662.0", "@azure/msal-node": "1.14.4", "@contentful/app-sdk": "4.16.0", diff --git a/yarn.lock b/yarn.lock index 3c8a12cb1d90..e57675f470da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1946,6 +1946,23 @@ __metadata: languageName: node linkType: hard +"@aws-sdk/s3-presigned-post@npm:3.662.0": + version: 3.662.0 + resolution: "@aws-sdk/s3-presigned-post@npm:3.662.0" + dependencies: + "@aws-sdk/client-s3": 3.662.0 + "@aws-sdk/types": 3.662.0 + "@aws-sdk/util-format-url": 3.662.0 + "@smithy/middleware-endpoint": ^3.1.4 + "@smithy/signature-v4": ^4.2.0 + "@smithy/types": ^3.5.0 + "@smithy/util-hex-encoding": ^3.0.0 + "@smithy/util-utf8": ^3.0.0 + tslib: ^2.6.2 + checksum: 5514900727f092ae46e7136acacc4baaa6949fc311bdef93b4fc29eb258c44397f2e49719c5b58796d45816242caa15ee3118011c02b8458b0749af910b89f91 + languageName: node + linkType: hard + "@aws-sdk/s3-request-presigner@npm:3.662.0": version: 3.662.0 resolution: "@aws-sdk/s3-request-presigner@npm:3.662.0" @@ -38438,6 +38455,7 @@ __metadata: "@aws-sdk/client-ssm": 3.145.0 "@aws-sdk/credential-provider-node": 3.662.0 "@aws-sdk/lib-storage": 3.662.0 + "@aws-sdk/s3-presigned-post": 3.662.0 "@aws-sdk/s3-request-presigner": 3.662.0 "@azure/msal-node": 1.14.4 "@babel/core": 7.22.5 From b68eea7f7f5a601e50dbe7fe467efe3b531b6868 Mon Sep 17 00:00:00 2001 From: HjorturJ <34068269+HjorturJ@users.noreply.github.com> Date: Fri, 8 Nov 2024 17:19:58 +0000 Subject: [PATCH 5/5] fix(health-insurance): Fixing zod schema (#16778) Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../templates/health-insurance/src/lib/dataSchema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/application/templates/health-insurance/src/lib/dataSchema.ts b/libs/application/templates/health-insurance/src/lib/dataSchema.ts index 3190c3b98ec7..dbd38b200a0b 100644 --- a/libs/application/templates/health-insurance/src/lib/dataSchema.ts +++ b/libs/application/templates/health-insurance/src/lib/dataSchema.ts @@ -13,7 +13,7 @@ const formerInsurance = z.object({ country: z.string().min(1), personalId: z.string().min(1), institution: z.string().min(1), - confirmationOfResidencyDocument: FileSchema.optional(), + confirmationOfResidencyDocument: z.array(FileSchema).optional(), entitlement: z.nativeEnum(YesOrNo).optional(), entitlementReason: z.string().optional(), })