diff --git a/.circleci/config.yml b/.circleci/config.yml index 28182707..2c8347dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,8 +21,8 @@ jobs: version: 20.10.12 docker_layer_caching: true - run: docker login rg.fr-par.scw.cloud/lecoffre -u nologin -p $SCW_SECRET_KEY - - run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:$TAG . - - run: docker push rg.fr-par.scw.cloud/lecoffre/back:$TAG + - run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7} . + - run: docker push rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7} deploy-docker-image: @@ -30,6 +30,10 @@ jobs: - image: cimg/base:stable environment: TAG: << pipeline.git.tag >> + parameters: + env: + type: string + default: stg steps: - checkout - kubernetes/install-kubeconfig: @@ -39,31 +43,63 @@ jobs: name: Deploy command: > helm upgrade - lecoffre-back devops/ -i -f devops/values.yaml - -n lecoffre + lecoffre-back devops/ -i -f devops/<>.values.yaml + -n lecoffre-<> --create-namespace --set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back' - --set lecoffreBack.image.tag=$TAG + --set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7} + --set lecoffreCron.image.repository='rg.fr-par.scw.cloud/lecoffre/back' + --set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7} + workflows: version: 2 - build-and-register: + build-and-register-stg: jobs: - build-push-docker-image: filters: - tags: - only: /^v.*/ branches: - ignore: /.*/ + only: staging - deploy-docker-image: + env: stg requires: - build-push-docker-image context: - - staging + - sc-shared-prd filters: - tags: - only: /^v.*/ branches: - ignore: /.*/ + only: staging + + build-and-register-ppd: + jobs: + - build-push-docker-image: + filters: + branches: + only: preprod + - deploy-docker-image: + env: ppd + requires: + - build-push-docker-image + context: + - sc-shared-prd + filters: + branches: + only: preprod + + build-and-register-prd: + jobs: + - build-push-docker-image: + filters: + branches: + only: main + - deploy-docker-image: + env: prd + requires: + - build-push-docker-image + context: + - sc-shared-prd + filters: + branches: + only: main diff --git a/devops/Chart.yaml b/devops/Chart.yaml index 208511fb..91793269 100644 --- a/devops/Chart.yaml +++ b/devops/Chart.yaml @@ -21,5 +21,5 @@ version: 0.0.1 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: 0.5.6 +appVersion: 0.5.7 diff --git a/devops/ppd.values.yaml b/devops/ppd.values.yaml new file mode 100644 index 00000000..ba5c13a9 --- /dev/null +++ b/devops/ppd.values.yaml @@ -0,0 +1,54 @@ +dockerPullSecret: docker-pull-secret + +scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy1ulbB34v6vpZI2kxnGNqERA/U5BaYDAyfKSBwMAy4br7HVKhhuwkoF5qoG5JzJXseSmqB1U9vncVIGOZWzJc1Y4/eGlWcvLcLyfw2z/WEpyeNiWJfEhTYpJOB7gv0XnRb2U/JM3jRy1QgEUIk1WR6kgBalF+xaczPQ6uKh+PR2pqkbZa3WaKUrddmzNsgEz4d8PZMWt8IBwR2JOQEHUqCd34p/pJNyLdUgcdDhg02DKwn1oRoAxKTbAio/a7WrMbodjCb3TNWIYGal5mFmItZ7Ok/EBmUf4E85eOkTR+j8ynuuiexld3Q5Kw3o8LsHjgzVL9uP+T2rYaKkjtVt+YQRX1U8l9CrsdUEz0/wEBA0jwCWMfnh1qhD5pM/xwwjsEEAcK4rYV+Q7iAgGZZvZBCQ5aEHzrtn5D95tr1GZCV2hmrW6Seu+LKKLVBS1JmsuEsOuhudYsEK9m2RYVcxbjuS5eokKEjNrGobf2oB8rhBByavfw1JTBixR5JrI8lcYlnCa+oEhxXKJY+4Fx5SAB4YaLCMSo5vw6zsFQ3WKQzlEmCFt+EnapS+a+MGrdlwq07OHTDpvgk/1z39hopoCuhhKckGGfErLXsTYQvDOkFu+EPzgY7m7qDw/d9pSiht5tuSOkAqeOgm7tpNkUufZhaXmP+1aT7i+H5gq1JILGAmXzTI5Wc= + +lecoffreBack: + serviceAccountName: lecoffre-back-sa + command: "'sh', '-c', 'export $(xargs =6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.9", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", @@ -91,25 +163,25 @@ } }, "node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz", + "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.22.15", + "@babel/helpers": "^7.22.15", + "@babel/parser": "^7.22.15", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -150,12 +222,12 @@ "dev": true }, "node_modules/@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", + "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.22.15", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -165,22 +237,19 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-environment-visitor": { @@ -218,28 +287,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz", + "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -291,45 +360,45 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz", + "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", + "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", + "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -408,9 +477,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.22.16", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", + "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -597,33 +666,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz", + "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.22.15", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -655,13 +724,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz", + "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.15", "to-fast-properties": "^2.0.0" }, "engines": { @@ -720,16 +789,16 @@ } }, "node_modules/@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.4.tgz", + "integrity": "sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "slash": "^3.0.0" }, "engines": { @@ -737,37 +806,37 @@ } }, "node_modules/@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.4.tgz", + "integrity": "sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/reporters": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", + "jest-changed-files": "^29.6.3", + "jest-config": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-resolve-dependencies": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", + "jest-watcher": "^29.6.4", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -784,88 +853,88 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.4.tgz", + "integrity": "sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.1" + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA==", "dev": true, "dependencies": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" + "expect": "^29.6.4", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.4.tgz", + "integrity": "sha512-FEhkJhqtvBwgSpiTrocquJCdXPsyvNKcl/n7A3u7X4pVoF4bswm11c9d4AV+kfq2Gpv/mM8x7E7DsRvH+djkrg==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.4.tgz", + "integrity": "sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.4.tgz", + "integrity": "sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/types": "^29.6.3", + "jest-mock": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.4.tgz", + "integrity": "sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", @@ -874,13 +943,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -899,9 +968,9 @@ } }, "node_modules/@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { "@sinclair/typebox": "^0.27.8" @@ -911,9 +980,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", @@ -925,13 +994,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.4.tgz", + "integrity": "sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -940,14 +1009,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz", + "integrity": "sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.4", "slash": "^3.0.0" }, "engines": { @@ -955,22 +1024,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.4.tgz", + "integrity": "sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", + "jest-haste-map": "^29.6.4", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -981,12 +1050,12 @@ } }, "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1012,9 +1081,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "engines": { "node": ">=6.0.0" } @@ -1034,21 +1103,15 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@mailchimp/mailchimp_transactional": { "version": "1.0.50", "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_transactional/-/mailchimp_transactional-1.0.50.tgz", @@ -1061,14 +1124,14 @@ } }, "node_modules/@next/env": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", - "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==" + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.19.tgz", + "integrity": "sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ==" }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.10.tgz", - "integrity": "sha512-4bsdfKmmg7mgFGph0UorD1xWfZ5jZEw4kKRHYEeTK9bT1QnMbPVPlVXQRIiFPrhoDQnZUoa6duuPUJIEGLV1Jg==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz", + "integrity": "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==", "cpu": [ "arm64" ], @@ -1081,9 +1144,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.10.tgz", - "integrity": "sha512-ngXhUBbcZIWZWqNbQSNxQrB9T1V+wgfCzAor2olYuo/YpaL6mUYNUEgeBMhr8qwV0ARSgKaOp35lRvB7EmCRBg==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz", + "integrity": "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==", "cpu": [ "x64" ], @@ -1096,9 +1159,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.10.tgz", - "integrity": "sha512-SjCZZCOmHD4uyM75MVArSAmF5Y+IJSGroPRj2v9/jnBT36SYFTORN8Ag/lhw81W9EeexKY/CUg2e9mdebZOwsg==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz", + "integrity": "sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==", "cpu": [ "arm64" ], @@ -1111,9 +1174,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.10.tgz", - "integrity": "sha512-F+VlcWijX5qteoYIOxNiBbNE8ruaWuRlcYyIRK10CugqI/BIeCDzEDyrHIHY8AWwbkTwe6GRHabMdE688Rqq4Q==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz", + "integrity": "sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==", "cpu": [ "arm64" ], @@ -1126,9 +1189,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.10.tgz", - "integrity": "sha512-WDv1YtAV07nhfy3i1visr5p/tjiH6CeXp4wX78lzP1jI07t4PnHHG1WEDFOduXh3WT4hG6yN82EQBQHDi7hBrQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz", + "integrity": "sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==", "cpu": [ "x64" ], @@ -1141,9 +1204,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.10.tgz", - "integrity": "sha512-zFkzqc737xr6qoBgDa3AwC7jPQzGLjDlkNmt/ljvQJ/Veri5ECdHjZCUuiTUfVjshNIIpki6FuP0RaQYK9iCRg==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz", + "integrity": "sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==", "cpu": [ "x64" ], @@ -1156,9 +1219,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.10.tgz", - "integrity": "sha512-IboRS8IWz5mWfnjAdCekkl8s0B7ijpWeDwK2O8CdgZkoCDY0ZQHBSGiJ2KViAG6+BJVfLvcP+a2fh6cdyBr9QQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz", + "integrity": "sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==", "cpu": [ "arm64" ], @@ -1171,9 +1234,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.10.tgz", - "integrity": "sha512-bSA+4j8jY4EEiwD/M2bol4uVEu1lBlgsGdvM+mmBm/BbqofNBfaZ2qwSbwE2OwbAmzNdVJRFRXQZ0dkjopTRaQ==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz", + "integrity": "sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==", "cpu": [ "ia32" ], @@ -1186,9 +1249,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.10.tgz", - "integrity": "sha512-g2+tU63yTWmcVQKDGY0MV1PjjqgZtwM4rB1oVVi/v0brdZAcrcTV+04agKzWtvWroyFz6IqtT0MoZJA7PNyLVw==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz", + "integrity": "sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==", "cpu": [ "x64" ], @@ -1347,31 +1410,31 @@ } }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.14", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz", + "integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/cron": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.0.1.tgz", - "integrity": "sha512-WHa/1rtNtD2Q/H0+YTTZoty+/5rcE66iAFX2IY+JuUoOACsevYyFkSYu/2vdw+G5LrmO7Lxowrqm0av4k3qWNQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/cron/-/cron-2.4.0.tgz", + "integrity": "sha512-5bBaAkqvSFBX8JMi/xCofNzG5E594TNsApMz68dLd/sQYz/HGQqgcxGHTRjOvD4G3Y+YF1Oo3S7QdCvKt1KAJQ==", + "deprecated": "This is a stub types definition. cron provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "@types/luxon": "*", - "@types/node": "*" + "cron": "*" } }, "node_modules/@types/express": { @@ -1387,9 +1450,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "version": "4.17.36", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", + "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", "dev": true, "dependencies": { "@types/node": "*", @@ -1438,9 +1501,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", - "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", + "version": "29.5.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.4.tgz", + "integrity": "sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1457,10 +1520,9 @@ } }, "node_modules/@types/luxon": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.1.tgz", - "integrity": "sha512-XOS5nBcgEeP2PpcqJHjCWhUCAzGfXIU8ILOSLpx2FhxqMW9KdxgCGXNOEKGVBfveKtIpztHzKK5vSRVLyW/NqA==", - "dev": true + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.2.tgz", + "integrity": "sha512-l5cpE57br4BIjK+9BSkFBOsWtwv6J9bJpC7gdXIzZyI0vuKvNTk0wZZrkQxMGsUAuGW9+WMNWF2IJMD7br2yeQ==" }, "node_modules/@types/mailchimp__mailchimp_transactional": { "version": "1.0.5", @@ -1478,9 +1540,9 @@ "dev": true }, "node_modules/@types/module-alias": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.1.tgz", - "integrity": "sha512-DN/CCT1HQG6HquBNJdLkvV+4v5l/oEuwOHUPLxI+Eub0NED+lk0YUfba04WGH90EINiUrNgClkNnwGmbICeWMQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.2.tgz", + "integrity": "sha512-Oeo5NEjAceFgN8OzGiLXPswgv2GBmrDGuTnLS0sQ8g4Mq5sB5c97Hu5B+n9Gu/j+5Y+oUb4TSawHXkZ8MENGyw==", "dev": true }, "node_modules/@types/multer": { @@ -1493,9 +1555,9 @@ } }, "node_modules/@types/node": { - "version": "18.17.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.0.tgz", - "integrity": "sha512-GXZxEtOxYGFchyUzxvKI14iff9KZ2DI+A6a37o6EQevtg6uO9t+aUZKcaC1Te5Ng1OnLM7K9NVVj+FbecD9cJg==" + "version": "18.17.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz", + "integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw==" }, "node_modules/@types/node-fetch": { "version": "2.6.4", @@ -1530,16 +1592,10 @@ "@types/node": "*" } }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "version": "6.9.8", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", + "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", "dev": true }, "node_modules/@types/range-parser": { @@ -1576,15 +1632,15 @@ "dev": true }, "node_modules/@types/uuid": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.2.tgz", - "integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.3.tgz", + "integrity": "sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==", "dev": true }, "node_modules/@types/validator": { - "version": "13.7.17", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.17.tgz", - "integrity": "sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==" + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" }, "node_modules/@types/yargs": { "version": "17.0.24", @@ -1728,15 +1784,15 @@ } }, "node_modules/babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.4.tgz", + "integrity": "sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw==", "dev": true, "dependencies": { - "@jest/transform": "^29.6.1", + "@jest/transform": "^29.6.4", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -1764,10 +1820,26 @@ "node": ">=8" } }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -1803,12 +1875,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -1906,9 +1978,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "dev": true, "funding": [ { @@ -1925,9 +1997,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.11" }, "bin": { @@ -2049,9 +2121,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001516", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", - "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "version": "1.0.30001528", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz", + "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==", "funding": [ { "type": "opencollective", @@ -2335,17 +2407,18 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cron": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/cron/-/cron-2.3.1.tgz", - "integrity": "sha512-1eRRlIT0UfIqauwbG9pkg3J6CX9A6My2ytJWqAXoK0T9oJnUZTzGBNPxao0zjodIbPgf8UQWjE62BMb9eVllSQ==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/cron/-/cron-2.4.3.tgz", + "integrity": "sha512-YBvExkQYF7w0PxyeFLRyr817YVDhGxaCi5/uRRMqa4aWD3IFKRd+uNbpW1VWMdqQy8PZ7CElc+accXJcauPKzQ==", "dependencies": { - "luxon": "^3.2.1" + "@types/luxon": "~3.3.0", + "luxon": "~3.3.0" } }, "node_modules/cron-parser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.8.1.tgz", - "integrity": "sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", "dependencies": { "luxon": "^3.2.1" }, @@ -2376,10 +2449,18 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deepmerge": { "version": "4.3.1", @@ -2433,9 +2514,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2467,9 +2548,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.461", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz", - "integrity": "sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==", + "version": "1.4.510", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz", + "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==", "dev": true }, "node_modules/emittery": { @@ -2584,17 +2665,16 @@ } }, "node_modules/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.4.tgz", + "integrity": "sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.6.1", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" + "@jest/expect-utils": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2753,9 +2833,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3061,9 +3141,9 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -3177,33 +3257,66 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -3244,9 +3357,9 @@ "dev": true }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -3257,15 +3370,15 @@ } }, "node_modules/jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", + "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.1" + "jest-cli": "^29.6.4" }, "bin": { "jest": "bin/jest.js" @@ -3283,12 +3396,13 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.6.3.tgz", + "integrity": "sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg==", "dev": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.6.3", "p-limit": "^3.1.0" }, "engines": { @@ -3296,28 +3410,28 @@ } }, "node_modules/jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.4.tgz", + "integrity": "sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/expect": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-each": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-runtime": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.3", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3327,21 +3441,21 @@ } }, "node_modules/jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.4.tgz", + "integrity": "sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ==", "dev": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/core": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-config": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -3361,31 +3475,31 @@ } }, "node_modules/jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.4.tgz", + "integrity": "sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", + "@jest/test-sequencer": "^29.6.4", + "@jest/types": "^29.6.3", + "babel-jest": "^29.6.4", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-circus": "^29.6.4", + "jest-environment-node": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runner": "^29.6.4", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3406,24 +3520,24 @@ } }, "node_modules/jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.4.tgz", + "integrity": "sha512-9F48UxR9e4XOEZvoUXEHSWY4qC4zERJaOfrbBg9JpbJOO43R1vN76REt/aMGZoY6GD5g84nnJiBIVlscegefpw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.6.3.tgz", + "integrity": "sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" @@ -3433,62 +3547,62 @@ } }, "node_modules/jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.3.tgz", + "integrity": "sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" + "jest-get-type": "^29.6.3", + "jest-util": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.4.tgz", + "integrity": "sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-mock": "^29.6.3", + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.4.tgz", + "integrity": "sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.6.3", + "jest-worker": "^29.6.4", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3500,46 +3614,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz", + "integrity": "sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q==", "dev": true, "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.4.tgz", + "integrity": "sha512-KSzwyzGvK4HcfnserYqJHYi7sZVqdREJ9DMPAKVbS98JsIAvumihaNUbjrWw0St7p9IY7A9UskCW5MYlGmBQFQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.3.tgz", + "integrity": "sha512-FtzaEEHzjDpQp51HX4UMkPZjy46ati4T5pEMyM6Ik48ztu4T9LQplZ6OsimHx7EuM9dfEh5HJa6D3trEftu3dA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.3", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3548,14 +3662,14 @@ } }, "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.3.tgz", + "integrity": "sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.1" + "jest-util": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3579,26 +3693,26 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.4.tgz", + "integrity": "sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.6.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-util": "^29.6.3", + "jest-validate": "^29.6.3", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3608,43 +3722,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz", + "integrity": "sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA==", "dev": true, "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.6.4" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.4.tgz", + "integrity": "sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw==", "dev": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.6.4", + "@jest/environment": "^29.6.4", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-docblock": "^29.6.3", + "jest-environment-node": "^29.6.4", + "jest-haste-map": "^29.6.4", + "jest-leak-detector": "^29.6.3", + "jest-message-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-runtime": "^29.6.4", + "jest-util": "^29.6.3", + "jest-watcher": "^29.6.4", + "jest-worker": "^29.6.4", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3653,31 +3767,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.4.tgz", + "integrity": "sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA==", "dev": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.6.4", + "@jest/fake-timers": "^29.6.4", + "@jest/globals": "^29.6.4", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-haste-map": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-mock": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.6.4", + "jest-snapshot": "^29.6.4", + "jest-util": "^29.6.3", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3686,9 +3800,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.4.tgz", + "integrity": "sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -3696,21 +3810,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.6.4", + "@jest/transform": "^29.6.4", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.1", + "expect": "^29.6.4", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-diff": "^29.6.4", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.6.4", + "jest-message-util": "^29.6.3", + "jest-util": "^29.6.3", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.6.3", "semver": "^7.5.3" }, "engines": { @@ -3751,12 +3864,12 @@ "dev": true }, "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.3.tgz", + "integrity": "sha512-QUjna/xSy4B32fzcKTSz1w7YYzgiHrjjJjevdRf61HYk998R5vVMMNmrHESYZVDS5DSWs+1srPLPKxXPkeSDOA==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -3768,17 +3881,17 @@ } }, "node_modules/jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.3.tgz", + "integrity": "sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.1" + "pretty-format": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3797,18 +3910,18 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.4.tgz", + "integrity": "sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/test-result": "^29.6.4", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.1", + "jest-util": "^29.6.3", "string-length": "^4.0.1" }, "engines": { @@ -3816,13 +3929,13 @@ } }, "node_modules/jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", + "version": "29.6.4", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.4.tgz", + "integrity": "sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.1", + "jest-util": "^29.6.3", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -3894,14 +4007,20 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">=12", @@ -3972,7 +4091,7 @@ } }, "node_modules/le-coffre-resources": { - "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#dffc2429ba6ceb4129deb56e308962799b9b572c", + "resolved": "git+ssh://git@github.com/smart-chain-fr/leCoffre-resources.git#1d27e0dacb6fe9c5637601818d3ff26434cf663c", "license": "MIT", "dependencies": { "class-transformer": "^0.5.1", @@ -3990,9 +4109,9 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.10.37", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.37.tgz", - "integrity": "sha512-Z10PCaOCiAxbUxLyR31DNeeNugSVP6iv/m7UrSKS5JHziEMApJtgku4e9Q69pzzSC9LnQiM09sqsGf2ticZnMw==" + "version": "1.10.44", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.44.tgz", + "integrity": "sha512-svlRdNBI5WgBjRC20GrCfbFiclbF0Cx+sCcQob/C1r57nsoq0xg8r65QbTyVyweQIlB33P+Uahyho6EMYgcOyQ==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -4012,10 +4131,35 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -4023,6 +4167,11 @@ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long-timeout": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", @@ -4066,20 +4215,53 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4386,11 +4568,11 @@ } }, "node_modules/next": { - "version": "13.4.10", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.10.tgz", - "integrity": "sha512-4ep6aKxVTQ7rkUW2fBLhpBr/5oceCuf4KmlUpvG/aXuDTIf9mexNSpabUD6RWPspu6wiJJvozZREhXhueYO36A==", + "version": "13.4.19", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.19.tgz", + "integrity": "sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==", "dependencies": { - "@next/env": "13.4.10", + "@next/env": "13.4.19", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -4406,19 +4588,18 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.10", - "@next/swc-darwin-x64": "13.4.10", - "@next/swc-linux-arm64-gnu": "13.4.10", - "@next/swc-linux-arm64-musl": "13.4.10", - "@next/swc-linux-x64-gnu": "13.4.10", - "@next/swc-linux-x64-musl": "13.4.10", - "@next/swc-win32-arm64-msvc": "13.4.10", - "@next/swc-win32-ia32-msvc": "13.4.10", - "@next/swc-win32-x64-msvc": "13.4.10" + "@next/swc-darwin-arm64": "13.4.19", + "@next/swc-darwin-x64": "13.4.19", + "@next/swc-linux-arm64-gnu": "13.4.19", + "@next/swc-linux-arm64-musl": "13.4.19", + "@next/swc-linux-x64-gnu": "13.4.19", + "@next/swc-linux-x64-musl": "13.4.19", + "@next/swc-win32-arm64-msvc": "13.4.19", + "@next/swc-win32-ia32-msvc": "13.4.19", + "@next/swc-win32-x64-msvc": "13.4.19" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "fibers": ">= 3.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -4427,9 +4608,6 @@ "@opentelemetry/api": { "optional": true }, - "fibers": { - "optional": true - }, "sass": { "optional": true } @@ -4447,9 +4625,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -4851,12 +5029,12 @@ } }, "node_modules/pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.3.tgz", + "integrity": "sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -4943,9 +5121,9 @@ "dev": true }, "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", + "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", "dev": true, "funding": [ { @@ -5071,12 +5249,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -5661,9 +5839,9 @@ } }, "node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/type-detect": { "version": "4.0.8", @@ -5846,9 +6024,9 @@ "dev": true }, "node_modules/validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", "engines": { "node": ">= 0.10" } diff --git a/package.json b/package.json index 7467bbf0..45621fda 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "cron": "^2.3.1", "express": "^4.18.2", "jsonwebtoken": "^9.0.0", - "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.63", + "le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.71", "module-alias": "^2.2.2", "multer": "^1.4.5-lts.1", "next": "^13.1.5", diff --git a/src/app/api/admin/CustomersController.ts b/src/app/api/admin/CustomersController.ts index 3b7ea244..90e429cf 100644 --- a/src/app/api/admin/CustomersController.ts +++ b/src/app/api/admin/CustomersController.ts @@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/Admin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class CustomersController extends ApiController { /** * @description Get all customers */ - @Get("/api/v1/admin/customers", [authHandler, ruleHandler]) + @Get("/api/v1/admin/customers", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -70,7 +71,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/admin/customers/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -111,7 +112,7 @@ export default class CustomersController extends ApiController { /** * @description Get a specific customer by uid */ - @Get("/api/v1/admin/customers/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DeedTypesController.ts b/src/app/api/admin/DeedTypesController.ts index bb42d6de..d1273879 100644 --- a/src/app/api/admin/DeedTypesController.ts +++ b/src/app/api/admin/DeedTypesController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController { * @description Get all deedtypes * @returns Deedtype[] list of deedtypes */ - @Get("/api/v1/admin/deed-types", [authHandler, ruleHandler]) + @Get("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,14 +66,19 @@ export default class DeedTypesController extends ApiController { * @description Create a new deedtype * @returns Deedtype created */ - @Post("/api/v1/admin/deed-types", [authHandler, ruleHandler, deedTypeHandler]) + @Post("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async post(req: Request, response: Response) { try { //init DeedType resource with request body values const deedTypeEntity = DeedType.hydrate(req.body); - //validate deed type + //validate deed type await validateOrReject(deedTypeEntity, { groups: ["createDeedType"], forbidUnknownValues: false }); + const doesExist = await this.deedTypesService.get({ where: { name: deedTypeEntity.name } }); + if (doesExist.length > 0) { + this.httpBadRequest(response, "Deed type name already used"); + return; + } //call service to get prisma entity const deedTypeEntityCreated = await this.deedTypesService.create(deedTypeEntity); @@ -84,7 +90,7 @@ export default class DeedTypesController extends ApiController { //success this.httpCreated(response, deedType); - } catch (error) { + } catch (error) { this.httpInternalError(response, error); return; } @@ -94,7 +100,7 @@ export default class DeedTypesController extends ApiController { * @description Modify a specific deedtype by uid * @returns Deedtype modified */ - @Put("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Put("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -136,7 +142,7 @@ export default class DeedTypesController extends ApiController { * @description Get a specific deedtype by uid * @returns IDeedtype */ - @Get("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Get("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DeedsController.ts b/src/app/api/admin/DeedsController.ts index ae35aa4b..00a2fa20 100644 --- a/src/app/api/admin/DeedsController.ts +++ b/src/app/api/admin/DeedsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedsController extends ApiController { * @description Get all deeds * @returns Deed[] list of deeds */ - @Get("/api/v1/admin/deeds", [authHandler, ruleHandler]) + @Get("/api/v1/admin/deeds", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DeedsController extends ApiController { * @description Get a specific deed by uid * @returns Deed */ - @Get("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Get("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -87,7 +88,7 @@ export default class DeedsController extends ApiController { /** * @description Modify a specific deed by uid */ - @Put("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Put("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DocumentTypesController.ts b/src/app/api/admin/DocumentTypesController.ts index 9089bd6a..582cd2f2 100644 --- a/src/app/api/admin/DocumentTypesController.ts +++ b/src/app/api/admin/DocumentTypesController.ts @@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get all document-types */ - @Get("/api/v1/admin/document-types", [authHandler, ruleHandler]) + @Get("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,7 +54,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Create a new documentType */ - @Post("/api/v1/admin/document-types", [authHandler, ruleHandler, documentTypeHandler]) + @Post("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async post(req: Request, response: Response) { try { //init DocumentType resource with request body values @@ -77,7 +78,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Modify a specific documentType by uid */ - @Put("/api/v1/admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Put("/api/v1/admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/DocumentsController.ts b/src/app/api/admin/DocumentsController.ts index 5696450c..05a21c1e 100644 --- a/src/app/api/admin/DocumentsController.ts +++ b/src/app/api/admin/DocumentsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController { * @description Get all documents * @returns IDocument[] list of documents */ - @Get("/api/v1/admin/documents", [authHandler, ruleHandler]) + @Get("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DocumentsController extends ApiController { * @description Create a new document * @returns IDocument created */ - @Post("/api/v1/admin/documents", [authHandler, ruleHandler, documentHandler]) + @Post("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async post(req: Request, response: Response) { try { //init Document resource with request body values @@ -80,7 +81,7 @@ export default class DocumentsController extends ApiController { /** * @description Update a specific document */ - @Put("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Put("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async update(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -119,7 +120,7 @@ export default class DocumentsController extends ApiController { /** * @description Delete a specific document */ - @Delete("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Delete("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -152,7 +153,7 @@ export default class DocumentsController extends ApiController { /** * @description Get a specific document by uid */ - @Get("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Get("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/FilesController.ts b/src/app/api/admin/FilesController.ts index 0317d12f..583d3ddc 100644 --- a/src/app/api/admin/FilesController.ts +++ b/src/app/api/admin/FilesController.ts @@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class FilesController extends ApiController { * @description Get all Files * @returns File[] list of Files */ - @Get("/api/v1/admin/files", [authHandler, ruleHandler]) + @Get("/api/v1/admin/files", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -49,7 +50,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/admin/files/download/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async download(req: Request, response: Response) { const uid = req.params["uid"]; if (!uid) { @@ -77,7 +78,7 @@ export default class FilesController extends ApiController { /** * @description Delete a specific File */ - @Delete("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Delete("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -115,7 +116,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficeFoldersController.ts b/src/app/api/admin/OfficeFoldersController.ts index b5906906..42fbdc58 100644 --- a/src/app/api/admin/OfficeFoldersController.ts +++ b/src/app/api/admin/OfficeFoldersController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Get all folders */ - @Get("/api/v1/admin/folders", [authHandler, ruleHandler]) + @Get("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -80,7 +81,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Create a new folder */ - @Post("/api/v1/admin/folders", [authHandler, ruleHandler, folderHandler]) + @Post("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async post(req: Request, response: Response) { try { //init OfficeFolder resource with request body values @@ -104,7 +105,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Modify a specific folder by uid */ - @Put("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Put("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -146,7 +147,7 @@ export default class OfficeFoldersController extends ApiController { * @description Get a specific folder by uid * @returns IFolder */ - @Get("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Get("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -182,7 +183,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Delete a specific folder */ - @Delete("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Delete("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficeRolesController.ts b/src/app/api/admin/OfficeRolesController.ts index 9dfb2022..5c06e471 100644 --- a/src/app/api/admin/OfficeRolesController.ts +++ b/src/app/api/admin/OfficeRolesController.ts @@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get all officeRoles */ - @Get("/api/v1/admin/office-roles", [authHandler, ruleHandler]) + @Get("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -63,7 +64,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Create a new officeRole */ - @Post("/api/v1/admin/office-roles", [authHandler, ruleHandler, officeRoleHandler]) + @Post("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IOfficeRole resource with request body values @@ -91,7 +92,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Modify a specific officeRole by uid */ - @Put("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Put("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -132,7 +133,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get a specific officeRole by uid */ - @Get("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Get("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/OfficesController.ts b/src/app/api/admin/OfficesController.ts index 99433c13..546d240f 100644 --- a/src/app/api/admin/OfficesController.ts +++ b/src/app/api/admin/OfficesController.ts @@ -7,6 +7,7 @@ import { Offices } from "@prisma/client"; import { Office as OfficeResource } from "le-coffre-resources/dist/Admin"; import ruleHandler from "@App/middlewares/RulesHandler"; import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class OfficesController extends ApiController { /** * @description Get all offices */ - @Get("/api/v1/admin/offices", [authHandler, ruleHandler]) + @Get("/api/v1/admin/offices", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -40,7 +41,7 @@ export default class OfficesController extends ApiController { /** * @description Get a specific office by uid */ - @Get("/api/v1/admin/offices/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/RolesController.ts b/src/app/api/admin/RolesController.ts index 32ab6440..634bd92e 100644 --- a/src/app/api/admin/RolesController.ts +++ b/src/app/api/admin/RolesController.ts @@ -6,6 +6,7 @@ import { Service } from "typedi"; import { Role } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class RolesController extends ApiController { /** * @description Get all roles */ - @Get("/api/v1/admin/roles", [authHandler, ruleHandler]) + @Get("/api/v1/admin/roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -43,7 +44,7 @@ export default class RolesController extends ApiController { /** * @description Get a specific role by uid */ - @Get("/api/v1/admin/roles/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/RulesController.ts b/src/app/api/admin/RulesController.ts index de343769..55526601 100644 --- a/src/app/api/admin/RulesController.ts +++ b/src/app/api/admin/RulesController.ts @@ -6,6 +6,7 @@ import { Service } from "typedi"; import { Rule } from "le-coffre-resources/dist/Admin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -17,7 +18,7 @@ export default class RulesController extends ApiController { /** * @description Get all rules */ - @Get("/api/v1/admin/rules", [authHandler, ruleHandler]) + @Get("/api/v1/admin/rules", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -43,7 +44,7 @@ export default class RulesController extends ApiController { /** * @description Get a specific rule by uid */ - @Get("/api/v1/admin/rules/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/admin/UsersController.ts b/src/app/api/admin/UsersController.ts index 2d6d3465..cc4cde87 100644 --- a/src/app/api/admin/UsersController.ts +++ b/src/app/api/admin/UsersController.ts @@ -8,19 +8,21 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler"; -import { validateOrReject } from "class-validator"; +import roleHandler from "@App/middlewares/RolesHandler"; +import RolesService from "@Services/admin/RolesService/RolesService"; +import OfficeRolesService from "@Services/admin/OfficeRolesService/OfficeRolesService"; @Controller() @Service() export default class UsersController extends ApiController { - constructor(private usersService: UsersService) { + constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) { super(); } /** * @description Get all users */ - @Get("/api/v1/admin/users", [authHandler, ruleHandler]) + @Get("/api/v1/admin/users", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,7 +67,7 @@ export default class UsersController extends ApiController { /** * @description Modify a specific user by uid */ - @Put("/api/v1/admin/users/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -74,7 +76,7 @@ export default class UsersController extends ApiController { return; } - const userFound = await this.usersService.getByUid(uid); + const userFound = await this.usersService.getByUidWithRole(uid); if (!userFound) { this.httpNotFoundRequest(response, "user not found"); @@ -84,9 +86,29 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); - //validate user - await validateOrReject(userEntity, { groups: ["updateUser"] }); - + if(userEntity.role) { + const role = await this.roleService.getByUid(userEntity.role.uid!); + if(!role) { + this.httpBadRequest(response, "Role not found"); + return; + } + if (role.name === "super-admin" || userFound.role.name === "super-admin" ) { + this.httpBadRequest(response, "Cannot assign or remove super-admin role"); + return; + } + } + + if(userEntity.office_role) { + const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!); + if(!officeRole) { + this.httpBadRequest(response, "Office role not found"); + return; + } + if (officeRole.office_uid != userFound.office_uid) { + this.httpBadRequest(response, "Cannot assign an office role from another office"); + return; + } + } //call service to get prisma entity const userEntityUpdated = await this.usersService.update(uid, userEntity); @@ -106,7 +128,7 @@ export default class UsersController extends ApiController { /** * @description Get a specific user by uid */ - @Get("/api/v1/admin/users/:uid", [authHandler, ruleHandler, userHandler]) + @Get("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler, userHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/customer/CustomersController.ts b/src/app/api/customer/CustomersController.ts new file mode 100644 index 00000000..f958ab7e --- /dev/null +++ b/src/app/api/customer/CustomersController.ts @@ -0,0 +1,79 @@ +import { Response, Request } from "express"; +import { Controller, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import CustomersService from "@Services/customer/CustomersService/CustomersService"; +import { Service } from "typedi"; +import Customer from "le-coffre-resources/dist/Customer"; +import authHandler from "@App/middlewares/AuthHandler"; +import ruleHandler from "@App/middlewares/RulesHandler"; + +@Controller() +@Service() +export default class CustomersController extends ApiController { + constructor(private customersService: CustomersService) { + super(); + } + + /** + * @description Get all customers + */ + @Get("/api/v1/customer/customers") + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + + //call service to get prisma entity + const customersEntities = await this.customersService.get(query); + + //Hydrate ressource with prisma entity + const customers = Customer.hydrateArray(customersEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, customers); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + + /** + * @description Get a specific customer by uid + */ + @Get("/api/v1/customer/customers/:uid", [authHandler, ruleHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const customerEntity = await this.customersService.getByUid(uid, query); + + if (!customerEntity) { + this.httpNotFoundRequest(response, "customer not found"); + return; + } + + //Hydrate ressource with prisma entity + const customer = Customer.hydrate(customerEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, customer); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/customer/DocumentsController.ts b/src/app/api/customer/DocumentsController.ts index 7b7784c9..42fdd63b 100644 --- a/src/app/api/customer/DocumentsController.ts +++ b/src/app/api/customer/DocumentsController.ts @@ -1,5 +1,5 @@ import { Response, Request } from "express"; -import { Controller, Get } from "@ControllerPattern/index"; +import { Controller, Get, Post } from "@ControllerPattern/index"; import ApiController from "@Common/system/controller-pattern/ApiController"; import { Service } from "typedi"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; @@ -7,6 +7,7 @@ import { Documents, Prisma } from "@prisma/client"; import { Document } from "le-coffre-resources/dist/Customer"; import authHandler from "@App/middlewares/AuthHandler"; import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler"; +import { validateOrReject } from "class-validator"; @Controller() @Service() @@ -27,12 +28,15 @@ export default class DocumentsController extends ApiController { if (req.query["q"]) { query = JSON.parse(req.query["q"] as string); } + const customerId: string = req.body.user.customerId; const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } }; query.where = customerWhereInput; + //call service to get prisma entity const documentEntities: Documents[] = await this.documentsService.get(query); + //Hydrate ressource with prisma entity const documents = Document.hydrateArray(documentEntities, { strategy: "excludeAll" }); @@ -79,4 +83,35 @@ export default class DocumentsController extends ApiController { return; } } + + /** + * @description Create a new File + * @returns File created + */ + @Post("/api/v1/customer/documents", [authHandler]) + protected async post(req: Request, response: Response) { + try { + //init Document resource with request body values + const documentEntity = Document.hydrate(req.body); + console.log(documentEntity); + + + //validate document + await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false }); + + //call service to get prisma entity + const documentEntityCreated = await this.documentsService.create(documentEntity); + + //Hydrate ressource with prisma entity + const document = Document.hydrate(documentEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, document); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } } diff --git a/src/app/api/customer/FilesController.ts b/src/app/api/customer/FilesController.ts index 76dd93ee..83f595ec 100644 --- a/src/app/api/customer/FilesController.ts +++ b/src/app/api/customer/FilesController.ts @@ -10,11 +10,14 @@ import { validateOrReject } from "class-validator"; import DocumentsService from "@Services/customer/DocumentsService/DocumentsService"; import authHandler from "@App/middlewares/AuthHandler"; import fileHandler from "@App/middlewares/CustomerHandler/FileHandler"; +import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService"; +import { DocumentType } from "le-coffre-resources/dist/SuperAdmin"; +import ObjectHydrate from "@Common/helpers/ObjectHydrate"; @Controller() @Service() export default class FilesController extends ApiController { - constructor(private filesService: FilesService, private documentService: DocumentsService) { + constructor(private filesService: FilesService, private documentService: DocumentsService, private documentTypesService : DocumentTypesService) { super(); } @@ -87,9 +90,10 @@ export default class FilesController extends ApiController { //init File resource with request body values const fileEntity = File.hydrate(JSON.parse(req.body["q"])); + console.log(fileEntity); //validate File - await validateOrReject(fileEntity, { groups: ["createFile"] }); + // await validateOrReject(fileEntity, { groups: ["createFile"] }); //call service to get prisma entity const fileEntityCreated = await this.filesService.create(fileEntity, req.file); @@ -135,9 +139,6 @@ export default class FilesController extends ApiController { //init File resource with request body values const fileEntity = File.hydrate(req.body); - //validate file - await validateOrReject(fileEntity, { groups: ["updateFile"] }); - //call service to get prisma entity const fileEntityUpdated: Files = await this.filesService.update(uid, fileEntity); @@ -224,4 +225,52 @@ export default class FilesController extends ApiController { return; } } + + /** + * @description Create a new File + * @returns File created + */ + @Post("/api/v1/customer/addPersonalFile", [authHandler, fileHandler]) + protected async addPersonalFile(req: Request, response: Response) { + try { + //get file + if (!req.file) throw new Error("No file provided"); + + //init File resource with request body values + const fileEntity = File.hydrate(JSON.parse(req.body["q"])); + + const documentTypeEntities = await this.documentTypesService.get({ where: { name: "Other"} }); + const documentTypeEntity = documentTypeEntities[0]; + const documentType = ObjectHydrate.hydrate(new DocumentType(), documentTypeEntity!, { strategy: "excludeAll" }); + + const documentEntity = Document.hydrate({document_type: documentType}); + await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false }); + const documentEntityCreated = await this.documentService.create(documentEntity); + + const document = Document.hydrate(documentEntityCreated, { + strategy: "excludeAll", + }); + + fileEntity.document = document; + + const fileEntityCreated = await this.filesService.create(fileEntity, req.file); + + const documentToUpdate = Document.hydrate(document!); + + documentToUpdate!.document_status = "DEPOSITED"; + await this.documentService.update(document!.uid!, documentToUpdate); + + //Hydrate ressource with prisma entity + const fileEntityHydrated = File.hydrate(fileEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, fileEntityHydrated); + + } catch (error) { + this.httpBadRequest(response, error); + return; + } + } } diff --git a/src/app/api/customer/OfficeFoldersController.ts b/src/app/api/customer/OfficeFoldersController.ts new file mode 100644 index 00000000..e524b445 --- /dev/null +++ b/src/app/api/customer/OfficeFoldersController.ts @@ -0,0 +1,113 @@ +import { Response, Request } from "express"; +import { Controller, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService"; +import { Service } from "typedi"; +import { OfficeFolders, Prisma } from "@prisma/client"; +import { OfficeFolder } from "le-coffre-resources/dist/Customer"; +// import authHandler from "@App/middlewares/AuthHandler"; +// import ruleHandler from "@App/middlewares/RulesHandler"; +// import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; + +@Controller() +@Service() +export default class OfficeFoldersController extends ApiController { + constructor(private officeFoldersService: OfficeFoldersService) { + super(); + } + + /** + * @description Get all folders + */ + @Get("/api/v1/customer/folders") + protected async get(req: Request, response: Response) { + try { + //get query + let query: Prisma.OfficeFoldersFindManyArgs = {}; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + + if (req.query["search"] && typeof req.query["search"] === "string") { + const filter = req.query["search"]; + query = { + where: { + OR: [ + { + name: { contains: filter, mode: "insensitive" }, + }, + { + folder_number: { contains: filter, mode: "insensitive" }, + }, + { + customers: { + some: { + contact: { + OR: [ + { first_name: { contains: filter, mode: "insensitive" } }, + { last_name: { contains: filter, mode: "insensitive" } }, + ], + }, + }, + }, + }, + ], + }, + }; + } + const officeWhereInput: Prisma.OfficesWhereInput = {}; + if (!query.where) query.where = { office: officeWhereInput }; + query.where.office = officeWhereInput; + + //call service to get prisma entity + const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query); + + //Hydrate ressource with prisma entity + const officeFolders = OfficeFolder.hydrateArray(officeFolderEntities, { + strategy: "excludeAll", + }); + //success + this.httpSuccess(response, officeFolders); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific folder by uid + * @returns IFolder + */ + @Get("/api/v1/customer/folders/:uid") + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query); + + if (!officeFolderEntity) { + this.httpNotFoundRequest(response, "folder not found"); + return; + } + + //Hydrate ressource with prisma entity + const officeFolder = OfficeFolder.hydrate(officeFolderEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, officeFolder); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/franceConnect/CustomerController.ts b/src/app/api/franceConnect/CustomerController.ts index 54e19b12..633bed86 100644 --- a/src/app/api/franceConnect/CustomerController.ts +++ b/src/app/api/franceConnect/CustomerController.ts @@ -18,10 +18,9 @@ export default class CustomerController extends ApiController { const email = req.params["email"]; if (!email) throw new Error("email is required"); - const payload = await this.authService.getCustomerJwtPayload(email); + const payload = await this.authService.getCustomerJwtPayload(email); const accessToken = this.authService.generateAccessToken(payload); - const refreshToken = this.authService.generateRefreshToken(payload); - + const refreshToken = this.authService.generateRefreshToken(payload); //success this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { diff --git a/src/app/api/idnot/UserController.ts b/src/app/api/idnot/UserController.ts index 2dd2029a..b63d3fec 100644 --- a/src/app/api/idnot/UserController.ts +++ b/src/app/api/idnot/UserController.ts @@ -42,13 +42,14 @@ export default class UserController extends ApiController { const id = req.params["idnot"]; if (!id) throw new Error("idnot is required"); - const payload = await this.authService.getUserJwtPayload(id!); + const payload = await this.authService.getUserJwtPayload(id); const accessToken = this.authService.generateAccessToken(payload); const refreshToken = this.authService.generateRefreshToken(payload); //success this.httpSuccess(response, { accessToken, refreshToken }); } catch (error) { + console.log(error); this.httpInternalError(response); return; } diff --git a/src/app/api/notary/OfficeFoldersController.ts b/src/app/api/notary/OfficeFoldersController.ts index af46d774..85b80173 100644 --- a/src/app/api/notary/OfficeFoldersController.ts +++ b/src/app/api/notary/OfficeFoldersController.ts @@ -175,7 +175,6 @@ export default class OfficeFoldersController extends ApiController { this.httpInternalError(response, error); return; } - this.httpSuccess(response, await this.officeFoldersService.getByUid("uid")); } /** diff --git a/src/app/api/super-admin/AppointmentsController.ts b/src/app/api/super-admin/AppointmentsController.ts new file mode 100644 index 00000000..1c3f7346 --- /dev/null +++ b/src/app/api/super-admin/AppointmentsController.ts @@ -0,0 +1,77 @@ +import { Response, Request } from "express"; +import { Controller, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import { Service } from "typedi"; +import { Appointment } from "le-coffre-resources/dist/SuperAdmin"; +import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; + +@Controller() +@Service() +export default class AppointmentsController extends ApiController { + constructor(private appointmentsService: AppointmentsService) { + super(); + } + + /** + * @description Get all appointments + */ + @Get("/api/v1/super-admin/appointments", [authHandler, roleHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + //call service to get prisma entity + const appointmentsEntities = await this.appointmentsService.get(query); + + //Hydrate ressource with prisma entity + const appointments = Appointment.hydrateArray(appointmentsEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, appointments); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific appointment by uid + */ + @Get("/api/v1/super-admin/appointments/:uid", [authHandler, roleHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const appointmentEntity = await this.appointmentsService.getByUid(uid, query); + + if (!appointmentEntity) { + this.httpNotFoundRequest(response, "appointment not found"); + return; + } + + //Hydrate ressource with prisma entity + const appointment = Appointment.hydrate(appointmentEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, appointment); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/super-admin/CustomersController.ts b/src/app/api/super-admin/CustomersController.ts index 56c718b0..d1a15fd2 100644 --- a/src/app/api/super-admin/CustomersController.ts +++ b/src/app/api/super-admin/CustomersController.ts @@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class CustomersController extends ApiController { /** * @description Get all customers */ - @Get("/api/v1/super-admin/customers", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class CustomersController extends ApiController { /** * @description Create a new customer */ - @Post("/api/v1/super-admin/customers", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -70,7 +71,7 @@ export default class CustomersController extends ApiController { /** * @description Modify a specific customer by uid */ - @Put("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -111,7 +112,7 @@ export default class CustomersController extends ApiController { /** * @description Get a specific customer by uid */ - @Get("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DeedTypesController.ts b/src/app/api/super-admin/DeedTypesController.ts index 0a499a8f..5ab62ce1 100644 --- a/src/app/api/super-admin/DeedTypesController.ts +++ b/src/app/api/super-admin/DeedTypesController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController { * @description Get all deedtypes * @returns Deedtype[] list of deedtypes */ - @Get("/api/v1/super-admin/deed-types", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -65,7 +66,7 @@ export default class DeedTypesController extends ApiController { * @description Create a new deedtype * @returns Deedtype created */ - @Post("/api/v1/super-admin/deed-types", [authHandler, ruleHandler, deedTypeHandler]) + @Post("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async post(req: Request, response: Response) { try { //init DeedType resource with request body values @@ -94,7 +95,7 @@ export default class DeedTypesController extends ApiController { * @description Modify a specific deedtype by uid * @returns Deedtype modified */ - @Put("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Put("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -136,7 +137,7 @@ export default class DeedTypesController extends ApiController { * @description Get a specific deedtype by uid * @returns IDeedtype */ - @Get("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler]) + @Get("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DeedsController.ts b/src/app/api/super-admin/DeedsController.ts index 06e20d9d..a06de5ad 100644 --- a/src/app/api/super-admin/DeedsController.ts +++ b/src/app/api/super-admin/DeedsController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DeedsController extends ApiController { * @description Get all deeds * @returns Deed[] list of deeds */ - @Get("/api/v1/super-admin/deeds", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/deeds", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -52,7 +53,7 @@ export default class DeedsController extends ApiController { * @description Get a specific deed by uid * @returns Deed */ - @Get("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Get("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -87,7 +88,7 @@ export default class DeedsController extends ApiController { /** * @description Modify a specific deed by uid */ - @Put("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler]) + @Put("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DocumentTypesController.ts b/src/app/api/super-admin/DocumentTypesController.ts index baceb4db..85dc6896 100644 --- a/src/app/api/super-admin/DocumentTypesController.ts +++ b/src/app/api/super-admin/DocumentTypesController.ts @@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get all document-types */ - @Get("/api/v1/super-admin/document-types", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,11 +54,16 @@ export default class DocumentTypesController extends ApiController { /** * @description Create a new documentType */ - @Post("/api/v1/super-admin/document-types", [authHandler, ruleHandler, documentTypeHandler]) + @Post("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async post(req: Request, response: Response) { try { //init DocumentType resource with request body values const documentTypeEntity = DocumentType.hydrate(req.body); + const doesExist = await this.documentTypesService.get({ where: { name: documentTypeEntity.name } }); + if (doesExist.length > 0) { + this.httpBadRequest(response, "Document type name already used"); + return; + } //validate user await validateOrReject(documentTypeEntity, { groups: ["createDocumentType"], forbidUnknownValues: false }); //call service to get prisma entity @@ -77,7 +83,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Modify a specific documentType by uid */ - @Put("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Put("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -117,7 +123,7 @@ export default class DocumentTypesController extends ApiController { /** * @description Get a specific documentType by uid */ - @Get("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler]) + @Get("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/DocumentsController.ts b/src/app/api/super-admin/DocumentsController.ts index 7ccdb18c..f589ce4c 100644 --- a/src/app/api/super-admin/DocumentsController.ts +++ b/src/app/api/super-admin/DocumentsController.ts @@ -1,14 +1,15 @@ -import { Response, Request } from "express"; -import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; -import ApiController from "@Common/system/controller-pattern/ApiController"; -import { Service } from "typedi"; -import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; -import { Documents, Prisma } from "@prisma/client"; -import { Document } from "le-coffre-resources/dist/SuperAdmin"; -import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; -import ruleHandler from "@App/middlewares/RulesHandler"; import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; +import ruleHandler from "@App/middlewares/RulesHandler"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index"; +import { Documents, Prisma } from "@prisma/client"; +import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService"; +import { validateOrReject } from "class-validator"; +import { Request, Response } from "express"; +import { Document } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; @Controller() @Service() @@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController { * @description Get all documents * @returns IDocument[] list of documents */ - @Get("/api/v1/super-admin/documents", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -30,12 +31,16 @@ export default class DocumentsController extends ApiController { query = JSON.parse(req.query["q"] as string); } const officeId: string = req.body.user.office_Id; + const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ; + if(!query.where) query.where = { document_type : {office: officeWhereInput}}; - query.where.document_type!.office = officeWhereInput; + + // query.where.document_type!.office = officeWhereInput; //call service to get prisma entity - const documentEntities = await this.documentsService.get(query); + + const documentEntities = await this.documentsService.get(query); //Hydrate ressource with prisma entity const documents = Document.hydrateArray(documentEntities, { strategy: "excludeAll" }); @@ -52,7 +57,7 @@ export default class DocumentsController extends ApiController { * @description Create a new document * @returns IDocument created */ - @Post("/api/v1/super-admin/documents", [authHandler, ruleHandler, documentHandler]) + @Post("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async post(req: Request, response: Response) { try { //init Document resource with request body values @@ -80,7 +85,7 @@ export default class DocumentsController extends ApiController { /** * @description Update a specific document */ - @Put("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Put("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async update(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -119,7 +124,7 @@ export default class DocumentsController extends ApiController { /** * @description Delete a specific document */ - @Delete("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Delete("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -152,7 +157,7 @@ export default class DocumentsController extends ApiController { /** * @description Get a specific document by uid */ - @Get("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler]) + @Get("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/FilesController.ts b/src/app/api/super-admin/FilesController.ts index cf085d5f..cb1b7f8d 100644 --- a/src/app/api/super-admin/FilesController.ts +++ b/src/app/api/super-admin/FilesController.ts @@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class FilesController extends ApiController { * @description Get all Files * @returns File[] list of Files */ - @Get("/api/v1/super-admin/files", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/files", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -50,7 +51,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/super-admin/files/download/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/super-admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async download(req: Request, response: Response) { const uid = req.params["uid"]; if (!uid) { @@ -78,7 +79,7 @@ export default class FilesController extends ApiController { /** * @description Delete a specific File */ - @Delete("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Delete("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -116,7 +117,7 @@ export default class FilesController extends ApiController { /** * @description Get a specific File by uid */ - @Get("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler]) + @Get("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/LiveVoteController.ts b/src/app/api/super-admin/LiveVoteController.ts new file mode 100644 index 00000000..4a9104ca --- /dev/null +++ b/src/app/api/super-admin/LiveVoteController.ts @@ -0,0 +1,95 @@ +import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import { Controller, Post } from "@ControllerPattern/index"; +import { EAppointmentStatus } from "@prisma/client"; +import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService"; +import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService"; +import UsersService from "@Services/super-admin/UsersService/UsersService"; +import VotesService from "@Services/super-admin/VotesService/VotesService"; +import { validateOrReject } from "class-validator"; +import { Request, Response } from "express"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; + +@Controller() +@Service() +export default class LiveVoteController extends ApiController { + constructor( + private liveVoteService: LiveVoteService, + private votesService: VotesService, + private usersService: UsersService, + private appointmentService: AppointmentService, + ) { + super(); + } + + /** + * @description Create a new vote + */ + @Post("/api/v1/super-admin/live-votes", [authHandler, roleHandler]) + protected async post(req: Request, response: Response) { + try { + const userId = req.body.user.userId; + //init IUser resource with request body values + const voteEntity = Vote.hydrate(req.body); + //validate user + await validateOrReject(voteEntity, { groups: ["createVote"] }); + + let voteFound = []; + if (voteEntity.appointment.uid) { + const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid); + if (!appointment) { + this.httpNotFoundRequest(response, "Appointment not found"); + return; + } + if (appointment.status === EAppointmentStatus.CLOSED) { + this.httpBadRequest(response, "Appointment is closed"); + return; + } + voteFound = await this.votesService.get({ + where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] }, + }); + } else { + voteFound = await this.votesService.get({ + where: { + AND: [ + { + appointment: { + AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }], + }, + }, + { voter: { uid: userId } }, + ], + }, + }); + } + + if (voteFound.length) { + this.httpBadRequest(response, "Voter already voted for this appointment"); + return; + } + + const voter = await this.usersService.getByUid(userId); + + voteEntity.voter = voter!; + //call service to get prisma entity + const voteEntityCreated = await this.liveVoteService.create(voteEntity); + + if (!voteEntityCreated) { + this.httpBadRequest(response, "Appointment choice is not valid"); + return; + } + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntityCreated, { + strategy: "excludeAll", + }); + + //success + this.httpCreated(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/api/super-admin/OfficeFoldersController.ts b/src/app/api/super-admin/OfficeFoldersController.ts index dcd1b29c..e0b01345 100644 --- a/src/app/api/super-admin/OfficeFoldersController.ts +++ b/src/app/api/super-admin/OfficeFoldersController.ts @@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Get all folders */ - @Get("/api/v1/super-admin/folders", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -79,7 +80,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Create a new folder */ - @Post("/api/v1/super-admin/folders", [authHandler, ruleHandler, folderHandler]) + @Post("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async post(req: Request, response: Response) { try { //init OfficeFolder resource with request body values @@ -103,7 +104,7 @@ export default class OfficeFoldersController extends ApiController { /** * @description Modify a specific folder by uid */ - @Put("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Put("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -145,7 +146,7 @@ export default class OfficeFoldersController extends ApiController { * @description Get a specific folder by uid * @returns IFolder */ - @Get("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Get("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -175,13 +176,12 @@ export default class OfficeFoldersController extends ApiController { this.httpInternalError(response, error); return; } - this.httpSuccess(response, await this.officeFoldersService.getByUid("uid")); } /** * @description Delete a specific folder */ - @Delete("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler]) + @Delete("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler]) protected async delete(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/OfficeRolesController.ts b/src/app/api/super-admin/OfficeRolesController.ts index 80d54d7e..802c223e 100644 --- a/src/app/api/super-admin/OfficeRolesController.ts +++ b/src/app/api/super-admin/OfficeRolesController.ts @@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get all officeRoles */ - @Get("/api/v1/super-admin/office-roles", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -62,7 +63,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Create a new officeRole */ - @Post("/api/v1/super-admin/office-roles", [authHandler, ruleHandler, officeRoleHandler]) + @Post("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IOfficeRole resource with request body values @@ -90,7 +91,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Modify a specific officeRole by uid */ - @Put("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Put("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -131,7 +132,7 @@ export default class OfficeRolesController extends ApiController { /** * @description Get a specific officeRole by uid */ - @Get("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler]) + @Get("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/OfficesController.ts b/src/app/api/super-admin/OfficesController.ts index e6702675..f4edab79 100644 --- a/src/app/api/super-admin/OfficesController.ts +++ b/src/app/api/super-admin/OfficesController.ts @@ -8,6 +8,7 @@ import { Office as OfficeResource } from "le-coffre-resources/dist/SuperAdmin"; import { validateOrReject } from "class-validator"; import ruleHandler from "@App/middlewares/RulesHandler"; import authHandler from "@App/middlewares/AuthHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class OfficesController extends ApiController { /** * @description Get all offices */ - @Get("/api/v1/super-admin/offices", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -53,7 +54,7 @@ export default class OfficesController extends ApiController { /** * @description Create a new office */ - @Post("/api/v1/super-admin/offices", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler]) protected async post(req: Request, response: Response) { try { //init IUser resource with request body values @@ -76,7 +77,7 @@ export default class OfficesController extends ApiController { /** * @description Modify a specific office by uid */ - @Put("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -93,8 +94,7 @@ export default class OfficesController extends ApiController { } //init IUser resource with request body values const officeEntity = OfficeResource.hydrate(req.body); - //validate user - await validateOrReject(officeEntity, { groups: ["updateOffice"] }); + //call service to get prisma entity const officeEntityUpdated = await this.officesService.update(uid, officeEntity); //Hydrate ressource with prisma entity @@ -111,7 +111,7 @@ export default class OfficesController extends ApiController { /** * @description Get a specific office by uid */ - @Get("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/RolesController.ts b/src/app/api/super-admin/RolesController.ts index ba0683ab..372c02c5 100644 --- a/src/app/api/super-admin/RolesController.ts +++ b/src/app/api/super-admin/RolesController.ts @@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator"; import { Role } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class RolesController extends ApiController { /** * @description Get all roles */ - @Get("/api/v1/super-admin/roles", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class RolesController extends ApiController { /** * @description Create a new role */ - @Post("/api/v1/super-admin/roles", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IRole resource with request body values @@ -72,7 +73,7 @@ export default class RolesController extends ApiController { /** * @description Modify a specific role by uid */ - @Put("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -113,7 +114,7 @@ export default class RolesController extends ApiController { /** * @description Get a specific role by uid */ - @Get("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/RulesController.ts b/src/app/api/super-admin/RulesController.ts index c0bc87c1..6f2f21a4 100644 --- a/src/app/api/super-admin/RulesController.ts +++ b/src/app/api/super-admin/RulesController.ts @@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator"; import { Rule } from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; @Controller() @Service() @@ -18,7 +19,7 @@ export default class RulesController extends ApiController { /** * @description Get all rules */ - @Get("/api/v1/super-admin/rules", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -44,7 +45,7 @@ export default class RulesController extends ApiController { /** * @description Create a new rule */ - @Post("/api/v1/super-admin/rules", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler]) protected async getAddresses(req: Request, response: Response) { try { //init IRule resource with request body values @@ -72,7 +73,7 @@ export default class RulesController extends ApiController { /** * @description Modify a specific rule by uid */ - @Put("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; @@ -91,9 +92,6 @@ export default class RulesController extends ApiController { //init IRule resource with request body values const ruleEntity = Rule.hydrate(req.body); - //validate rule - await validateOrReject(ruleEntity, { groups: ["updateRule"] }); - //call service to get prisma entity const ruleEntityUpdated = await this.rulesService.update(ruleEntity); @@ -113,7 +111,7 @@ export default class RulesController extends ApiController { /** * @description Get a specific rule by uid */ - @Get("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/UsersController.ts b/src/app/api/super-admin/UsersController.ts index a96b3f5a..fd135312 100644 --- a/src/app/api/super-admin/UsersController.ts +++ b/src/app/api/super-admin/UsersController.ts @@ -7,18 +7,21 @@ import { validateOrReject } from "class-validator"; import User from "le-coffre-resources/dist/SuperAdmin"; import authHandler from "@App/middlewares/AuthHandler"; import ruleHandler from "@App/middlewares/RulesHandler"; +import roleHandler from "@App/middlewares/RolesHandler"; +import RolesService from "@Services/super-admin/RolesService/RolesService"; +import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService"; @Controller() @Service() export default class UsersController extends ApiController { - constructor(private usersService: UsersService) { + constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) { super(); } /** * @description Get all users */ - @Get("/api/v1/super-admin/users", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler]) protected async get(req: Request, response: Response) { try { //get query @@ -58,7 +61,7 @@ export default class UsersController extends ApiController { /** * @description Create a new user */ - @Post("/api/v1/super-admin/users", [authHandler, ruleHandler]) + @Post("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler]) protected async create(req: Request, response: Response) { try { //init IUser resource with request body values @@ -86,16 +89,17 @@ export default class UsersController extends ApiController { /** * @description Modify a specific user by uid */ - @Put("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler]) + @Put("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async put(req: Request, response: Response) { try { const uid = req.params["uid"]; + if (!uid) { this.httpBadRequest(response, "No uid provided"); return; } - const userFound = await this.usersService.getByUid(uid); + const userFound = await this.usersService.getByUidWithRole(uid); if (!userFound) { this.httpNotFoundRequest(response, "user not found"); @@ -105,9 +109,30 @@ export default class UsersController extends ApiController { //init IUser resource with request body values const userEntity = User.hydrate(req.body); - //validate user - await validateOrReject(userEntity, { groups: ["updateUser"] }); + if(userEntity.role) { + const role = await this.roleService.getByUid(userEntity.role.uid!); + if(!role) { + this.httpBadRequest(response, "Role not found"); + return; + } + if (role.name === "super-admin" || userFound.role.name === "super-admin" ) { + this.httpBadRequest(response, "Cannot assign or remove super-admin role"); + return; + } + } + if(userEntity.office_role) { + const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!); + if(!officeRole) { + this.httpBadRequest(response, "Office role not found"); + return; + } + if (officeRole.office_uid != userFound.office_uid) { + this.httpBadRequest(response, "Cannot assign an office role from another office"); + return; + } + } + //call service to get prisma entity const userEntityUpdated = await this.usersService.update(uid, userEntity); @@ -127,7 +152,7 @@ export default class UsersController extends ApiController { /** * @description Get a specific user by uid */ - @Get("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler]) + @Get("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler]) protected async getOneByUid(req: Request, response: Response) { try { const uid = req.params["uid"]; diff --git a/src/app/api/super-admin/VotesController.ts b/src/app/api/super-admin/VotesController.ts new file mode 100644 index 00000000..308e46e3 --- /dev/null +++ b/src/app/api/super-admin/VotesController.ts @@ -0,0 +1,116 @@ +import { Response, Request } from "express"; +import { Controller, Delete, Get } from "@ControllerPattern/index"; +import ApiController from "@Common/system/controller-pattern/ApiController"; +import VotesService from "@Services/super-admin/VotesService/VotesService"; +import { Service } from "typedi"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import authHandler from "@App/middlewares/AuthHandler"; +import { Votes } from "@prisma/client"; +import roleHandler from "@App/middlewares/RolesHandler"; + +@Controller() +@Service() +export default class VotesController extends ApiController { + constructor(private votesService: VotesService) { + super(); + } + + /** + * @description Get all votes + */ + @Get("/api/v1/super-admin/votes", [authHandler, roleHandler]) + protected async get(req: Request, response: Response) { + try { + //get query + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + //call service to get prisma entity + const votesEntities = await this.votesService.get(query); + + //Hydrate ressource with prisma entity + const votes = Vote.hydrateArray(votesEntities, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, votes); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Get a specific vote by uid + */ + @Get("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) + protected async getOneByUid(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + let query; + if (req.query["q"]) { + query = JSON.parse(req.query["q"] as string); + } + + const voteEntity = await this.votesService.getByUid(uid, query); + + if (!voteEntity) { + this.httpNotFoundRequest(response, "vote not found"); + return; + } + + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(voteEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } + + /** + * @description Delete a specific vote + */ + @Delete("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler]) + protected async delete(req: Request, response: Response) { + try { + const uid = req.params["uid"]; + if (!uid) { + this.httpBadRequest(response, "No uid provided"); + return; + } + + const voteFound = await this.votesService.getByUid(uid); + + if (!voteFound) { + this.httpNotFoundRequest(response, "vote not found"); + return; + } + + if (voteFound.voter_uid !== req.body.user.userId) { + this.httpUnauthorized(response, "Can't delete a vote that's not yours"); + return; + } + + //call service to get prisma entity + const votetEntity: Votes = await this.votesService.delete(uid); + + //Hydrate ressource with prisma entity + const vote = Vote.hydrate(votetEntity, { strategy: "excludeAll" }); + + //success + this.httpSuccess(response, vote); + } catch (error) { + this.httpInternalError(response, error); + return; + } + } +} diff --git a/src/app/index.ts b/src/app/index.ts index 22f4d1f3..dc98b2e4 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -40,6 +40,11 @@ import RolesControllerNotary from "./api/notary/RolesController"; import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController"; import FilesControllerCustomer from "./api/customer/FilesController"; import DocumentsControllerCustomer from "./api/customer/DocumentsController"; +import OfficeFoldersController from "./api/customer/OfficeFoldersController"; +import CustomersController from "./api/customer/CustomersController"; +import AppointmentsController from "./api/super-admin/AppointmentsController"; +import VotesController from "./api/super-admin/VotesController"; +import LiveVoteController from "./api/super-admin/LiveVoteController"; /** @@ -56,6 +61,9 @@ export default { Container.get(DeedTypesControllerSuperAdmin); Container.get(DocumentsControllerSuperAdmin); Container.get(DocumentTypesControllerSuperAdmin); + Container.get(AppointmentsController); + Container.get(VotesController); + Container.get(LiveVoteController); Container.get(IdNotUserController); Container.get(FranceConnectCustomerController); Container.get(FilesControllerSuperAdmin); @@ -89,5 +97,7 @@ export default { Container.get(OfficeRolesControllerNotary); Container.get(FilesControllerCustomer); Container.get(DocumentsControllerCustomer); + Container.get(OfficeFoldersController); + Container.get(CustomersController) }, }; diff --git a/src/app/middlewares/RolesHandler.ts b/src/app/middlewares/RolesHandler.ts new file mode 100644 index 00000000..3a4a9c77 --- /dev/null +++ b/src/app/middlewares/RolesHandler.ts @@ -0,0 +1,22 @@ +import HttpCodes from "@Common/system/controller-pattern/HttpCodes"; +import { NextFunction, Request, Response } from "express"; + +export default async function roleHandler(req: Request, response: Response, next: NextFunction) { + try { + + const namespace = req.path && req.path.split("/")[3]; + const role = req.body.user.role; + + if (namespace != "notary" && role != namespace && role != "super-admin") { + response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role"); + return; + } + + next(); + + } catch (error) { + console.log(error); + response.status(HttpCodes.INTERNAL_ERROR).send("Internal server error"); + return; + } +} diff --git a/src/app/middlewares/RulesHandler.ts b/src/app/middlewares/RulesHandler.ts index 83baab87..ff677652 100644 --- a/src/app/middlewares/RulesHandler.ts +++ b/src/app/middlewares/RulesHandler.ts @@ -7,14 +7,7 @@ export default async function ruleHandler(req: Request, response: Response, next const service = req.path && req.path.split("/")[4]; if (!rules) { - response.status(HttpCodes.UNAUTHORIZED).send("Missing rules in JWT"); - return; - } - const namespace = req.path && req.path.split("/")[3]; - const role = req.body.user.role; - - if (namespace != "notary" && role != namespace && role != "super-admin") { - response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role"); + response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized without rules"); return; } diff --git a/src/common/config/variables/Variables.ts b/src/common/config/variables/Variables.ts index 3747545e..a7b3cf3d 100644 --- a/src/common/config/variables/Variables.ts +++ b/src/common/config/variables/Variables.ts @@ -19,6 +19,9 @@ export class BackendVariables { @IsNotEmpty() public readonly DATABASE_NAME!: string; + @IsNotEmpty() + public readonly DATABASE_URL!: string; + @IsNotEmpty() public readonly API_ROOT_URL!: string; @@ -72,6 +75,7 @@ export class BackendVariables { this.DATABASE_USERNAME = process.env["DATABASE_USERNAME"]!; this.DATABASE_PASSWORD = process.env["DATABASE_PASSWORD"]!; this.DATABASE_NAME = process.env["DATABASE_NAME"]!; + this.DATABASE_URL = process.env["DEV_PRISMA_STUDIO_DB_URL"]!; this.API_ROOT_URL = process.env["API_ROOT_URL"]!; this.APP_PORT = process.env["APP_PORT"]!; this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!; diff --git a/src/common/databases/migrations/20230713145026_v12/migration.sql b/src/common/databases/migrations/20230713145026_v12/migration.sql new file mode 100644 index 00000000..c5dac8d4 --- /dev/null +++ b/src/common/databases/migrations/20230713145026_v12/migration.sql @@ -0,0 +1,38 @@ +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_contact_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_office_role_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_office_uid_fkey"; + +-- DropForeignKey +ALTER TABLE "users" DROP CONSTRAINT "users_roles_uid_fkey"; + +-- CreateTable +CREATE TABLE "votes" ( + "uid" TEXT NOT NULL, + "user_uid" VARCHAR(255) NOT NULL, + "voters" TEXT[], + + CONSTRAINT "votes_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "votes_uid_key" ON "votes"("uid"); + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_roles_uid_fkey" FOREIGN KEY ("roles_uid") REFERENCES "roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_office_role_uid_fkey" FOREIGN KEY ("office_role_uid") REFERENCES "office_roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "users" ADD CONSTRAINT "users_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/common/databases/migrations/20230725084826_v12/migration.sql b/src/common/databases/migrations/20230725084826_v12/migration.sql new file mode 100644 index 00000000..0b7f1455 --- /dev/null +++ b/src/common/databases/migrations/20230725084826_v12/migration.sql @@ -0,0 +1,45 @@ +/* + Warnings: + + - You are about to drop the column `user_uid` on the `votes` table. All the data in the column will be lost. + - You are about to drop the column `voters` on the `votes` table. All the data in the column will be lost. + - Added the required column `appointment_uid` to the `votes` table without a default value. This is not possible if the table is not empty. + - Added the required column `voter_uid` to the `votes` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateEnum +CREATE TYPE "EVote" AS ENUM ('NOMINATE', 'DISMISS'); + +-- CreateEnum +CREATE TYPE "EAppointmentStatus" AS ENUM ('OPEN', 'CLOSED'); + +-- DropForeignKey +ALTER TABLE "votes" DROP CONSTRAINT "votes_user_uid_fkey"; + +-- AlterTable +ALTER TABLE "votes" DROP COLUMN "user_uid", +DROP COLUMN "voters", +ADD COLUMN "appointment_uid" VARCHAR(255) NOT NULL, +ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE', +ADD COLUMN "voter_uid" VARCHAR(255) NOT NULL; + +-- CreateTable +CREATE TABLE "appointments" ( + "uid" TEXT NOT NULL, + "user_uid" VARCHAR(255) NOT NULL, + "status" "EAppointmentStatus" NOT NULL DEFAULT 'OPEN', + + CONSTRAINT "appointments_pkey" PRIMARY KEY ("uid") +); + +-- CreateIndex +CREATE UNIQUE INDEX "appointments_uid_key" ON "appointments"("uid"); + +-- AddForeignKey +ALTER TABLE "appointments" ADD CONSTRAINT "appointments_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_appointment_uid_fkey" FOREIGN KEY ("appointment_uid") REFERENCES "appointments"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "votes" ADD CONSTRAINT "votes_voter_uid_fkey" FOREIGN KEY ("voter_uid") REFERENCES "users"("uid") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/src/common/databases/migrations/20230725151748_v13/migration.sql b/src/common/databases/migrations/20230725151748_v13/migration.sql new file mode 100644 index 00000000..b8c667d7 --- /dev/null +++ b/src/common/databases/migrations/20230725151748_v13/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the column `choice` on the `votes` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "appointments" ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE'; + +-- AlterTable +ALTER TABLE "votes" DROP COLUMN "choice"; diff --git a/src/common/databases/migrations/20230726095252_v25/migration.sql b/src/common/databases/migrations/20230726095252_v25/migration.sql new file mode 100644 index 00000000..389c4749 --- /dev/null +++ b/src/common/databases/migrations/20230726095252_v25/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - A unique constraint covering the columns `[user_uid,choice,status]` on the table `appointments` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "appointments_user_uid_choice_status_key" ON "appointments"("user_uid", "choice", "status"); diff --git a/src/common/databases/migrations/20230816144031_v22/migration.sql b/src/common/databases/migrations/20230816144031_v22/migration.sql new file mode 100644 index 00000000..59a287ba --- /dev/null +++ b/src/common/databases/migrations/20230816144031_v22/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - Added the required column `label` to the `roles` table without a default value. This is not possible if the table is not empty. + - Added the required column `label` to the `rules` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "roles" ADD COLUMN "label" VARCHAR(255) NOT NULL; + +-- AlterTable +ALTER TABLE "rules" ADD COLUMN "label" VARCHAR(255) NOT NULL; diff --git a/src/common/databases/schema.prisma b/src/common/databases/schema.prisma index b8d91539..582bdc81 100644 --- a/src/common/databases/schema.prisma +++ b/src/common/databases/schema.prisma @@ -65,6 +65,8 @@ model Users { office_uid String @db.VarChar(255) notifications Notifications[] @relation("UserHasNotifications") office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders") + appointment Appointments[] + votes Votes[] @@map("users") } @@ -240,6 +242,7 @@ model DeedTypes { model Roles { uid String @id @unique @default(uuid()) name String @db.VarChar(255) + label String @db.VarChar(255) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt rules Rules[] @relation("RolesHasRules") @@ -264,6 +267,7 @@ model OfficeRoles { model Rules { uid String @id @unique @default(uuid()) name String @db.VarChar(255) + label String @db.VarChar(255) created_at DateTime? @default(now()) updated_at DateTime? @updatedAt role Roles[] @relation("RolesHasRules") @@ -288,6 +292,28 @@ model Emails { @@map("email") } +model Appointments { + uid String @id @unique @default(uuid()) + user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade) + user_uid String @db.VarChar(255) + choice EVote @default(NOMINATE) + status EAppointmentStatus @default(OPEN) + votes Votes[] + + @@unique([user_uid, choice, status]) + @@map("appointments") +} + +model Votes { + uid String @id @unique @default(uuid()) + appointment Appointments @relation(fields: [appointment_uid], references: [uid], onDelete: Cascade) + appointment_uid String @db.VarChar(255) + voter Users @relation(fields: [voter_uid], references: [uid]) + voter_uid String @db.VarChar(255) + + @@map("votes") +} + enum ECivility { MALE FEMALE @@ -322,3 +348,13 @@ enum EDocumentStatus { ANCHORED REFUSED } + +enum EVote { + NOMINATE + DISMISS +} + +enum EAppointmentStatus { + OPEN + CLOSED +} diff --git a/src/common/databases/seeders/seeder.ts b/src/common/databases/seeders/seeder.ts index cf0129f4..8e85cd93 100644 --- a/src/common/databases/seeders/seeder.ts +++ b/src/common/databases/seeders/seeder.ts @@ -1,18 +1,7 @@ +import { ECivility, ECustomerStatus, EFolderStatus, EOfficeStatus, Prisma, PrismaClient } from "@prisma/client"; +import User, { Address, Contact, Customer, Deed, DeedType, DocumentType, Office, OfficeFolder, OfficeRole, Role, Rule } from "le-coffre-resources/dist/SuperAdmin"; + import "module-alias/register"; -import { EFolderStatus, EOfficeStatus, ECivility, ECustomerStatus, PrismaClient, Prisma } from "@prisma/client"; -import User, { - Address, - Contact, - Customer, - Deed, - DeedType, - Office, - OfficeFolder, - OfficeRole, - Role, - Rule, - DocumentType, -} from "le-coffre-resources/dist/SuperAdmin"; export default async function main() { try{ @@ -526,301 +515,289 @@ export default async function main() { const rules: Rule[] = [ { name: "GET users", + label: "Lecture des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "GET offices", + label: "Lecture des offices", created_at: new Date(), updated_at: new Date(), }, { name: "GET customers", + label: "Lecture des clients", created_at: new Date(), updated_at: new Date(), }, { name: "GET deeds", + label: "Lecture des actes", created_at: new Date(), updated_at: new Date(), }, { name: "GET deed-types", + label: "Lecture des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "GET documents", + label: "Lecture des documents", created_at: new Date(), updated_at: new Date(), }, { name: "GET document-types", + label: "Lecture des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "GET files", + label: "Lecture des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "GET folders", + label: "Lecture des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "GET roles", + label: "Lecture utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "GET rules", + label: "Lecture des droits", created_at: new Date(), updated_at: new Date(), }, { name: "GET office-roles", + label: "Lecture des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "PUT users", + label: "Modification des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "PUT offices", + label: "Modification des offices", created_at: new Date(), updated_at: new Date(), }, { name: "PUT customers", + label: "Modification des clients", created_at: new Date(), updated_at: new Date(), }, { name: "PUT deeds", + label: "Modification des actes", created_at: new Date(), updated_at: new Date(), }, { - name: "PUT deedtypes", + name: "PUT deed-types", + label: "Modification des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "PUT documents", + label: "Modification des documents", created_at: new Date(), updated_at: new Date(), }, { name: "PUT document-types", + label: "Modification des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "PUT files", + label: "Modification des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "PUT folders", + label: "Modification des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "PUT roles", + label: "Modification des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "PUT rules", + label: "Modification des droits", created_at: new Date(), updated_at: new Date(), }, { name: "PUT office-roles", + label: "Modification des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "POST users", + label: "Création des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "POST offices", + label: "Création des offices", created_at: new Date(), updated_at: new Date(), }, { name: "POST customers", + label: "Création des clients", created_at: new Date(), updated_at: new Date(), }, { name: "POST deeds", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST deedtypes", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST documents", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST document-types", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST files", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST folders", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST roles", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST rules", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST office-roles", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST users", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST offices", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST customers", - created_at: new Date(), - updated_at: new Date(), - }, - { - name: "POST deeds", + label: "Création des actes", created_at: new Date(), updated_at: new Date(), }, { name: "POST deed-types", + label: "Création des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "POST documents", + label: "Création des documents", created_at: new Date(), updated_at: new Date(), }, { name: "POST document-types", + label: "Création des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "POST files", + label: "Création des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "POST folders", + label: "Création des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "POST roles", + label: "Création des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "POST rules", + label: "Création des droits", created_at: new Date(), updated_at: new Date(), }, { name: "POST office-roles", + label: "Création des rôles d'office", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE users", + label: "Suppression des utilisateurs", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE offices", + label: "Suppression des offices", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE customers", + label: "Suppression des clients", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE deeds", + label: "Suppression des actes", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE deed-types", + label: "Suppression des types d'actes", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE documents", + label: "Suppression des documents", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE document-types", + label: "Suppression des types de documents", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE files", + label: "Suppression des fichiers", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE folders", + label: "Suppression des dossiers", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE roles", + label: "Suppression des rôles", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE rules", + label: "Suppression des droits", created_at: new Date(), updated_at: new Date(), }, { name: "DELETE office-roles", + label: "Suppression des rôles d'office", created_at: new Date(), updated_at: new Date(), }, @@ -829,24 +806,28 @@ export default async function main() { const roles: Role[] = [ { name: "super-admin", + label: "Super administrateur", created_at: new Date(), updated_at: new Date(), rules: rules, }, { name: "admin", + label: "Administrateur", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 33), }, { name: "notary", + label: "Notaire", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 22), }, { name: "default", + label: "Utilisateur", created_at: new Date(), updated_at: new Date(), rules: rules.slice(0, 11), @@ -855,33 +836,19 @@ export default async function main() { const officeRoles: OfficeRole[] = [ { - name: "admin", - created_at: new Date(), - updated_at: new Date(), - office: offices[0]!, - rules: rules.slice(0, 40), - }, - { - name: "notary", + name: "Notaire", created_at: new Date(), updated_at: new Date(), office: offices[0]!, rules: rules.slice(0, 33), }, { - name: "deputy", + name: "Collaborateur", created_at: new Date(), updated_at: new Date(), office: offices[0]!, rules: rules.slice(0, 22), - }, - { - name: "listener", - created_at: new Date(), - updated_at: new Date(), - office: offices[0]!, - rules: rules.slice(0, 11), - }, + } ]; const users: User[] = [ @@ -1264,6 +1231,15 @@ export default async function main() { created_at: new Date(), updated_at: new Date(), }, + { + archived_at: null, + name: "Other", + office: offices[0], + private_description: "Other", + public_description: "Other", + created_at: new Date(), + updated_at: new Date(), + }, ]; const officeFolders: OfficeFolder[] = [ @@ -1371,7 +1347,7 @@ export default async function main() { for (const office of offices) { const officeCreated = await prisma.offices.create({ data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { @@ -1390,6 +1366,7 @@ export default async function main() { const ruleCreated = await prisma.rules.create({ data: { name: rule.name, + label: rule.label, }, }); rule.uid = ruleCreated.uid; @@ -1399,6 +1376,7 @@ export default async function main() { const roleCreated = await prisma.roles.create({ data: { name: role.name, + label: role.label, rules: { connect: role.rules?.map((rule) => ({ uid: rule.uid!, @@ -1438,7 +1416,7 @@ export default async function main() { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: { diff --git a/src/common/repositories/AppointmentsRepository.ts b/src/common/repositories/AppointmentsRepository.ts new file mode 100644 index 00000000..62b74d34 --- /dev/null +++ b/src/common/repositories/AppointmentsRepository.ts @@ -0,0 +1,76 @@ +import Database from "@Common/databases/database"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Service } from "typedi"; +import { Appointments, EAppointmentStatus, Prisma } from "@prisma/client"; + +@Service() +export default class AppointmentsRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().appointments; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many appointments + */ + public async findMany(query: Prisma.AppointmentsFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + return this.model.findMany(query); + } + + /** + * @description : Update data of a appointment + */ + public async update(uid: string, status: EAppointmentStatus): Promise { + const updateArgs: Prisma.AppointmentsUpdateArgs = { + where: { + uid: uid, + }, + data: { + status: status, + }, + }; + + return this.model.update(updateArgs); + } + + /** + * @description : Find one appointment + */ + public async findOneByUid(uid: string, query?: Prisma.AppointmentsInclude) { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: query, + }); + } + + /** + * @description : Find one appointment with votes + */ + public async findOneByUidWithVotes(uid: string) { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: {votes: true}, + }); + } + + /** + * @description : delete a appointment + */ + public async delete(uid: string): Promise { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } +} diff --git a/src/common/repositories/DocumentsRepository.ts b/src/common/repositories/DocumentsRepository.ts index c5110e6d..6a86cdd8 100644 --- a/src/common/repositories/DocumentsRepository.ts +++ b/src/common/repositories/DocumentsRepository.ts @@ -28,7 +28,7 @@ export default class DocumentsRepository extends BaseRepository { /** * @description : Create a document */ - public async create(document: Document): Promise { + public async create(document: DocumentCustomer): Promise { const createArgs: Prisma.DocumentsCreateArgs = { data: { folder: { diff --git a/src/common/repositories/OfficesRepository.ts b/src/common/repositories/OfficesRepository.ts index cdc85202..0e0c83ed 100644 --- a/src/common/repositories/OfficesRepository.ts +++ b/src/common/repositories/OfficesRepository.ts @@ -33,7 +33,7 @@ export default class OfficesRepository extends BaseRepository { public async create(office: OfficeRessource): Promise { const createArgs: Prisma.OfficesCreateArgs = { data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { diff --git a/src/common/repositories/RolesRepository.ts b/src/common/repositories/RolesRepository.ts index 20d203c7..5467f0a0 100644 --- a/src/common/repositories/RolesRepository.ts +++ b/src/common/repositories/RolesRepository.ts @@ -31,6 +31,7 @@ export default class RolesRepository extends BaseRepository { const createArgs: Prisma.RolesCreateArgs = { data: { name: role.name, + label: role.label, rules: { connect: role.rules?.map((rule) => ({ uid: rule.uid!, @@ -52,6 +53,7 @@ export default class RolesRepository extends BaseRepository { }, data: { name: role.name, + label: role.label, rules: { set: role.rules?.map((rule) => ({ uid: rule.uid!, diff --git a/src/common/repositories/RulesRepository.ts b/src/common/repositories/RulesRepository.ts index 7781290b..281e505b 100644 --- a/src/common/repositories/RulesRepository.ts +++ b/src/common/repositories/RulesRepository.ts @@ -31,6 +31,7 @@ export default class RulesRepository extends BaseRepository { const createArgs: Prisma.RulesCreateArgs = { data: { name: rule.name, + label: rule.label }, }; @@ -47,6 +48,7 @@ export default class RulesRepository extends BaseRepository { }, data: { name: rule.name, + label: rule.label }, }; diff --git a/src/common/repositories/UsersRepository.ts b/src/common/repositories/UsersRepository.ts index b472a8ec..6df40fb6 100644 --- a/src/common/repositories/UsersRepository.ts +++ b/src/common/repositories/UsersRepository.ts @@ -2,7 +2,7 @@ import Database from "@Common/databases/database"; import BaseRepository from "@Repositories/BaseRepository"; import { Service } from "typedi"; import { ECivility, Prisma, Users } from "@prisma/client"; -import User from "le-coffre-resources/dist/SuperAdmin"; +import User, { Role } from "le-coffre-resources/dist/SuperAdmin"; @Service() export default class UsersRepository extends BaseRepository { @@ -37,7 +37,7 @@ export default class UsersRepository extends BaseRepository { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: { @@ -87,6 +87,7 @@ export default class UsersRepository extends BaseRepository { /** * @description : Update data from a user */ + public async update(uid: string, user: User): Promise { const updateArgs: Prisma.UsersUpdateArgs = { where: { @@ -196,6 +197,18 @@ export default class UsersRepository extends BaseRepository { }); } + /** + * @description : Find one user with office + */ + public async findOneByUidWithRole(uid: string): Promise<((Users & {role: Role} )| null)> { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: { role: true }, + }); + } + /** * @description : Find one user */ diff --git a/src/common/repositories/VotesRepository.ts b/src/common/repositories/VotesRepository.ts new file mode 100644 index 00000000..a9bf7746 --- /dev/null +++ b/src/common/repositories/VotesRepository.ts @@ -0,0 +1,89 @@ +import Database from "@Common/databases/database"; +import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client"; +import BaseRepository from "@Repositories/BaseRepository"; +import { Vote } from "le-coffre-resources/dist/SuperAdmin"; +import { Service } from "typedi"; + +@Service() +export default class VotesRepository extends BaseRepository { + constructor(private database: Database) { + super(); + } + protected get model() { + return this.database.getClient().votes; + } + protected get instanceDb() { + return this.database.getClient(); + } + + /** + * @description : Find many votes + */ + public async findMany(query: Prisma.VotesFindManyArgs) { + query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows); + return this.model.findMany(query); + } + + /** + * @description : Create new vote + */ + public async create(vote: Vote): Promise { + let whereArg: Prisma.AppointmentsWhereUniqueInput; + if(vote.appointment.targeted_user.uid) { + whereArg = { + user_uid_choice_status: { + user_uid: vote.appointment.targeted_user.uid, + choice: EVote[vote.appointment.choice as keyof typeof EVote], + status: EAppointmentStatus.OPEN, + } + }; + } else { + whereArg = { + uid: vote.appointment.uid, + }; + } + const createArgs: Prisma.VotesCreateArgs = { + data: { + appointment: { + connectOrCreate: { + where: whereArg, + create: { + choice: EVote[vote.appointment.choice as keyof typeof EVote], + user_uid: vote.appointment.targeted_user.uid!, + } + }, + }, + voter: { + connect: { + uid: vote.voter.uid, + }, + }, + } + }; + + return this.model.create({...createArgs, include: {appointment: {include: {votes: true}}}}); + } + + /** + * @description : Find one vote + */ + public async findOneByUid(uid: string, query?: Prisma.VotesInclude): Promise { + return this.model.findUnique({ + where: { + uid: uid, + }, + include: query, + }); + } + + /** + * @description : delete a vote + */ + public async delete(uid: string): Promise { + return this.model.delete({ + where: { + uid: uid, + }, + }); + } +} diff --git a/src/common/system/database/DbProvider.ts b/src/common/system/database/DbProvider.ts index fa640f45..c84b75e9 100644 --- a/src/common/system/database/DbProvider.ts +++ b/src/common/system/database/DbProvider.ts @@ -9,7 +9,7 @@ dotenv.config(); export default class DbProvider { protected readonly variables = Container.get(BackendVariables); - protected url = `postgres://${this.variables.DATABASE_USERNAME}:${this.variables.DATABASE_PASSWORD}@${this.variables.DATABASE_HOST}:${this.variables.DATABASE_PORT}/${this.variables.DATABASE_NAME}`; + protected url = this.variables.DATABASE_URL; protected client = new PrismaClient({ datasources: { db: { diff --git a/src/services/admin/UsersService/UsersService.ts b/src/services/admin/UsersService/UsersService.ts index f23c09d7..6167352e 100644 --- a/src/services/admin/UsersService/UsersService.ts +++ b/src/services/admin/UsersService/UsersService.ts @@ -31,7 +31,7 @@ export default class UsersService extends BaseService { * @description : Modify a user * @throws {Error} If user modification failed */ - public update(uid: string, userEntity: User): Promise { + public async update(uid: string, userEntity: User): Promise { return this.userRepository.updateRole(uid, userEntity); } @@ -51,6 +51,14 @@ export default class UsersService extends BaseService { return this.userRepository.findOneByUidWithOffice(uid); } + /** + * @description : Get a user by uid with office + * @throws {Error} If user cannot be get by uid + */ + public getByUidWithRole(uid: string) { + return this.userRepository.findOneByUidWithRole(uid); + } + /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid diff --git a/src/services/common/AuthService/AuthService.ts b/src/services/common/AuthService/AuthService.ts index b0628cf0..4410cd35 100644 --- a/src/services/common/AuthService/AuthService.ts +++ b/src/services/common/AuthService/AuthService.ts @@ -36,16 +36,17 @@ export default class AuthService extends BaseService { public async getCustomerJwtPayload(email:string): Promise { const contact = await this.contactService.getByEmail(email); - if (!contact) return null; + const customer = await this.customerService.getByUid(contact.customers!.uid, { contact: true }); + if (!customer) return null; - if(contact.customers?.status === ECustomerStatus["PENDING"]) { - contact.customers.status = ECustomerStatus["VALIDATED"]; - this.customerService.update(contact.customers.uid, contact.customers); + if(customer.status === ECustomerStatus["PENDING"]) { + customer.status = ECustomerStatus["VALIDATED"]; + this.customerService.update(customer.uid, customer); } return { - customerId: contact.customers!.uid, + customerId: customer.uid, email: contact.email, }; } @@ -56,22 +57,19 @@ export default class AuthService extends BaseService { if (!user) return null; const rules: string[] = []; - if (user.office_role) { - user.office_role.rules.forEach((rule) => { - rules.push(rule.name); - }); - return { - userId: user.uid, - openId: { providerName: providerName, userId: user.idNot }, - office_Id: user.office_membership.uid, - role: user.role.name, - rules: rules, - }; - } user.role.rules.forEach((rule) => { rules.push(rule.name); }); + + if (user.office_role) { + user.office_role.rules.forEach((rule) => { + if(!rules.includes(rule.name)) { + rules.push(rule.name); + } + }); + } + return { userId: user.uid, openId: { providerName: providerName, userId: user.idNot }, @@ -80,7 +78,6 @@ export default class AuthService extends BaseService { rules: rules, }; } - public generateAccessToken(user: any): string { return jwt.sign({ ...user }, this.variables.ACCESS_TOKEN_SECRET, { expiresIn: "1h" }); } diff --git a/src/services/common/FilesService/FilesService.ts b/src/services/common/FilesService/FilesService.ts index 2ec4e6b5..4023b5db 100644 --- a/src/services/common/FilesService/FilesService.ts +++ b/src/services/common/FilesService/FilesService.ts @@ -8,7 +8,6 @@ import { BackendVariables } from "@Common/config/variables/Variables"; import { Readable } from "stream"; import { v4 } from "uuid"; import { Files, Prisma } from "@prisma/client"; -import fetch from "node-fetch"; @Service() export default class FilesService extends BaseService { diff --git a/src/services/customer/CustomersService/CustomersService.ts b/src/services/customer/CustomersService/CustomersService.ts new file mode 100644 index 00000000..38509164 --- /dev/null +++ b/src/services/customer/CustomersService/CustomersService.ts @@ -0,0 +1,35 @@ +import { Customers, Prisma } from "@prisma/client"; +import CustomersRepository from "@Repositories/CustomersRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; + +@Service() +export default class CustomersService extends BaseService { + constructor(private customerRepository: CustomersRepository) { + super(); + } + + /** + * @description : Get all Customers + * @throws {Error} If Customers cannot be get + */ + public async get(query: Prisma.CustomersFindManyArgs): Promise { + return this.customerRepository.findMany(query); + } + + /** + * @description : Get a customer by uid + * @throws {Error} If customer cannot be get by uid + */ + public async getByUid(uid: string, query?: Prisma.CustomersInclude): Promise { + return this.customerRepository.findOneByUid(uid, query); + } + + /** + * @description : Get a customer by contact uid + * @throws {Error} If customer cannot be get by contact uid + */ + public async getByContact(contactUid: string): Promise { + return this.customerRepository.findOneByContact(contactUid); + } +} diff --git a/src/services/customer/DocumentsService/DocumentsService.ts b/src/services/customer/DocumentsService/DocumentsService.ts index 26c45c6a..fb6d925c 100644 --- a/src/services/customer/DocumentsService/DocumentsService.ts +++ b/src/services/customer/DocumentsService/DocumentsService.ts @@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/Customer"; import DocumentsRepository from "@Repositories/DocumentsRepository"; import BaseService from "@Services/BaseService"; import { Service } from "typedi"; +import DocumentTypesService from "@Services/notary/DocumentTypesService/DocumentTypesService"; @Service() export default class DocumentsService extends BaseService { - constructor(private documentsRepository: DocumentsRepository) { + constructor(private documentsRepository: DocumentsRepository, private documentTypeService: DocumentTypesService) { super(); } @@ -18,6 +19,21 @@ export default class DocumentsService extends BaseService { return this.documentsRepository.findMany(query); } + /** + * @description : Create a new document + * @throws {Error} If document cannot be created + */ + public async create(document: Document): Promise { + const otherDocumentType = await this.documentTypeService.get({ where: { name: "Other" } }); + + if(otherDocumentType.length < 1) throw new Error("Other document type not found"); + + document.document_type = otherDocumentType[0]; + document.document_status = "DEPOSITED"; + + return this.documentsRepository.create(document); + } + /** * @description : Modify a document * @throws {Error} If document cannot be modified diff --git a/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts b/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts new file mode 100644 index 00000000..6afdede7 --- /dev/null +++ b/src/services/customer/OfficeFoldersService/OfficeFoldersService.ts @@ -0,0 +1,29 @@ +import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository"; +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import { Prisma } from "@prisma/client"; + +@Service() +export default class OfficeFoldersService extends BaseService { + constructor( + private officeFoldersRepository: OfficeFoldersRepository, + ) { + super(); + } + + /** + * @description : Get all folders + * @throws {Error} If folders cannot be get + */ + public async get(query: Prisma.OfficeFoldersFindManyArgs) { + return this.officeFoldersRepository.findMany(query); + } + + /** + * @description : Get a folder by uid + * @throws {Error} If folder cannot be get by uid + */ + public async getByUid(uid: string, query?: Prisma.OfficeFoldersInclude) { + return this.officeFoldersRepository.findOneByUid(uid, query); + } +} diff --git a/src/services/notary/RolesService/RolesService.ts b/src/services/notary/RolesService/RolesService.ts index f59c26b1..6e652687 100644 --- a/src/services/notary/RolesService/RolesService.ts +++ b/src/services/notary/RolesService/RolesService.ts @@ -1,5 +1,4 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import RolesRepository from "@Repositories/RolesRepository"; import { Prisma } from "@prisma/client"; diff --git a/src/services/notary/RulesService/RulesService.ts b/src/services/notary/RulesService/RulesService.ts index e52ad9bf..c59c9133 100644 --- a/src/services/notary/RulesService/RulesService.ts +++ b/src/services/notary/RulesService/RulesService.ts @@ -1,5 +1,4 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import RulesRepository from "@Repositories/RulesRepository"; import { Prisma } from "@prisma/client"; diff --git a/src/services/notary/UsersService/UsersService.ts b/src/services/notary/UsersService/UsersService.ts index f6927c87..5efbfff9 100644 --- a/src/services/notary/UsersService/UsersService.ts +++ b/src/services/notary/UsersService/UsersService.ts @@ -1,9 +1,7 @@ import BaseService from "@Services/BaseService"; -import "reflect-metadata"; import { Service } from "typedi"; import UsersRepository from "@Repositories/UsersRepository"; -import User from "le-coffre-resources/dist/Notary"; -import { Prisma, Users } from "@prisma/client"; +import { Prisma } from "@prisma/client"; @Service() export default class UsersService extends BaseService { @@ -19,22 +17,6 @@ export default class UsersService extends BaseService { return this.userRepository.findMany(query); } - /** - * @description : Create a user - * @throws {Error} If user couldn't be created - */ - public create(userEntity: User): Promise { - return this.userRepository.create(userEntity); - } - - /** - * @description : Modify a user - * @throws {Error} If user modification failed - */ - public update(uid: string, userEntity: User): Promise { - return this.userRepository.update(uid, userEntity); - } - /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid diff --git a/src/services/super-admin/AppointmentsService/AppointmentsService.ts b/src/services/super-admin/AppointmentsService/AppointmentsService.ts new file mode 100644 index 00000000..45d8b481 --- /dev/null +++ b/src/services/super-admin/AppointmentsService/AppointmentsService.ts @@ -0,0 +1,53 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import AppointmentsRepository from "@Repositories/AppointmentsRepository"; +import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client"; + +@Service() +export default class AppointmentService extends BaseService { + constructor(private appointmentRepository: AppointmentsRepository) { + super(); + } + + /** + * @description : Get all appointments + * @throws {Error} If appointments cannot be get + */ + public get(query: Prisma.AppointmentsFindManyArgs) { + return this.appointmentRepository.findMany(query); + } + + /** + * @description : Modify a appointment + * @throws {Error} If appointment cannot be modified + */ + public async update(uid: string, status: EAppointmentStatus): Promise { + return this.appointmentRepository.update(uid, status); + } + + /** + * @description : Get a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public getByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise { + return this.appointmentRepository.findOneByUid(uid, query); + } + + /** + * @description : Get a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public getByUidWithVotes(uid: string) { + return this.appointmentRepository.findOneByUidWithVotes(uid); + } + + /** + * @description : delete a appointment by uid + * @throws {Error} If appointment cannot be get by uid + */ + public delete(uid: string) { + return this.appointmentRepository.delete(uid); + } + + +} diff --git a/src/services/super-admin/LiveVoteService/LiveVoteService.ts b/src/services/super-admin/LiveVoteService/LiveVoteService.ts new file mode 100644 index 00000000..5576bb28 --- /dev/null +++ b/src/services/super-admin/LiveVoteService/LiveVoteService.ts @@ -0,0 +1,97 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin"; +import VotesRepository from "@Repositories/VotesRepository"; +import { Appointments, EAppointmentStatus, EVote, Votes } from "@prisma/client"; +import AppointmentService from "../AppointmentsService/AppointmentsService"; +import UsersService from "../UsersService/UsersService"; +import RolesService from "../RolesService/RolesService"; + +@Service() +export default class LiveVoteService extends BaseService { + constructor( + private voteRepository: VotesRepository, + private appointmentService: AppointmentService, + private userService: UsersService, + private roleService: RolesService, + ) { + super(); + } + + public async verifyVoterChoice(vote: Vote): Promise { + const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!); + if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) { + return true; + } + if (userWithRole!.role.name !== "super-admin" && vote.appointment.choice === EVote.NOMINATE) { + return true; + } + return false; + } + + public async getAppointmentWithVotes(vote: Vote): Promise { + if (vote.appointment.uid) { + return this.appointmentService.getByUidWithVotes(vote.appointment.uid); + } + const appointmentByUser = await this.appointmentService.get({ + where: { + AND: [ + { user_uid: vote.appointment.targeted_user.uid }, + { status: EAppointmentStatus.OPEN }, + { choice: EVote[vote.appointment.choice as keyof typeof EVote] }, + ], + }, + include: { votes: true }, + }); + if (appointmentByUser.length >= 1) { + return this.appointmentService.getByUidWithVotes(appointmentByUser[0]!.uid); + } + return null; + } + + private async closeVote(appointment: Appointments, vote: Votes) { + await this.appointmentService.update(vote.appointment_uid, EAppointmentStatus.CLOSED); + const user = await this.userService.getByUid(appointment.user_uid, { role: true }); + const userEntity = User.hydrate(user!, { strategy: "excludeAll" }); + + return await this.updateRole(appointment, userEntity, vote); + } + + private async updateRole(appointment: Appointments, userEntity: User, vote: Votes) { + if (appointment.choice === EVote.DISMISS) { + const roles = await this.roleService.get({ where: { name: "default" } }); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); + return vote; + } else if (appointment.choice === EVote.NOMINATE) { + const roles = await this.roleService.get({ where: { name: "super-admin" } }); + const roleEntity = Role.hydrate(roles[0]!, { strategy: "excludeAll" }); + userEntity!.role = roleEntity; + await this.userService.update(appointment!.user_uid, userEntity); + return vote; + } + return vote; + } + + /** + * @description : Create a vote + * @throws {Error} If vote couldn't be created + */ + public async create(vote: Vote): Promise { + const appointment = await this.getAppointmentWithVotes(vote); + + if (appointment) { + const appointmentEntity = Appointment.hydrate(appointment, { strategy: "excludeAll" }); + if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) { + const voteCreated = await this.voteRepository.create(vote); + return this.closeVote(appointment, voteCreated); + } + } + + const approvedChoice = await this.verifyVoterChoice(vote); + if(!approvedChoice) return null; + + return this.voteRepository.create(vote); + } +} diff --git a/src/services/super-admin/UsersService/UsersService.ts b/src/services/super-admin/UsersService/UsersService.ts index da350fea..241cb1e4 100644 --- a/src/services/super-admin/UsersService/UsersService.ts +++ b/src/services/super-admin/UsersService/UsersService.ts @@ -51,6 +51,14 @@ export default class UsersService extends BaseService { return this.userRepository.findOneByUidWithOffice(uid); } + /** + * @description : Get a user by uid with role + * @throws {Error} If user cannot be get by uid + */ + public getByUidWithRole(uid: string) { + return this.userRepository.findOneByUidWithRole(uid); + } + /** * @description : Get a user by uid * @throws {Error} If user cannot be get by uid diff --git a/src/services/super-admin/VotesService/VotesService.ts b/src/services/super-admin/VotesService/VotesService.ts new file mode 100644 index 00000000..fa32fb4d --- /dev/null +++ b/src/services/super-admin/VotesService/VotesService.ts @@ -0,0 +1,35 @@ +import BaseService from "@Services/BaseService"; +import { Service } from "typedi"; +import VotesRepository from "@Repositories/VotesRepository"; +import { Prisma } from "@prisma/client"; + +@Service() +export default class VoteService extends BaseService { + constructor(private voteRepository: VotesRepository) { + super(); + } + + /** + * @description : Get all votes + * @throws {Error} If votes cannot be get + */ + public get(query: Prisma.VotesFindManyArgs) { + return this.voteRepository.findMany(query); + } + + /** + * @description : Get a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public getByUid(uid: string, query?: Prisma.VotesInclude) { + return this.voteRepository.findOneByUid(uid, query); + } + + /** + * @description : delete a vote by uid + * @throws {Error} If vote cannot be get by uid + */ + public delete(uid: string) { + return this.voteRepository.delete(uid); + } +} diff --git a/src/test/config/Init.ts b/src/test/config/Init.ts index 74721622..4541cb77 100644 --- a/src/test/config/Init.ts +++ b/src/test/config/Init.ts @@ -18,7 +18,7 @@ const prisma = new PrismaClient(); export const initOffice = (office: Office): Promise => { return prisma.offices.create({ data: { - idNot: office.idNot, + idNot: office.idNot!, name: office.name, crpcen: office.crpcen, address: { @@ -95,6 +95,7 @@ export const initRules = (rule: Rule): Promise => { return prisma.rules.create({ data: { name: rule.name, + label: rule.label, }, }); }; @@ -103,6 +104,7 @@ export const initRoles = (role: Role): Promise => { return prisma.roles.create({ data: { name: role.name, + label: role.label, }, }); }; @@ -117,7 +119,7 @@ export const initUsers = (user: User): Promise => { idNot: user.office_membership!.idNot, }, create: { - idNot: user.office_membership!.idNot, + idNot: user.office_membership!.idNot!, name: user.office_membership!.name, crpcen: user.office_membership!.crpcen, address: { @@ -154,6 +156,7 @@ export const initUsers = (user: User): Promise => { }, create: { name: user.role!.name, + label: user.role!.label }, }, },