diff --git a/backend/Pipfile b/backend/Pipfile index 5f1f3fb07..ad1bdb46c 100644 --- a/backend/Pipfile +++ b/backend/Pipfile @@ -27,6 +27,7 @@ rocrate = "*" [dev-packages] requests = "*" pytest = "*" +pytest-asyncio = "*" black = "*" faker = "*" diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock index e0f002b45..8c9f7e56c 100644 --- a/backend/Pipfile.lock +++ b/backend/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "ab763f87e91bfba572248f4137cd96efd8dc32252b8f56e90b7907c5317ae47a" + "sha256": "81e6911fc9f48c1036174ca3b745cd14313ea469de000031b4dc269a1f9ba6a0" }, "pipfile-spec": 6, "requires": { @@ -49,11 +49,11 @@ }, "anyio": { "hashes": [ - "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b", - "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be" + "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421", + "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3" ], "markers": "python_full_version >= '3.6.2'", - "version": "==3.6.1" + "version": "==3.6.2" }, "arcp": { "hashes": [ @@ -80,44 +80,46 @@ }, "bcrypt": { "hashes": [ - "sha256:0b0f0c7141622a31e9734b7f649451147c04ebb5122327ac0bd23744df84be90", - "sha256:1c3334446fac200499e8bc04a530ce3cf0b3d7151e0e4ac5c0dddd3d95e97843", - "sha256:2d0dd19aad87e4ab882ef1d12df505f4c52b28b69666ce83c528f42c07379227", - "sha256:594780b364fb45f2634c46ec8d3e61c1c0f1811c4f2da60e8eb15594ecbf93ed", - "sha256:7c7dd6c1f05bf89e65261d97ac3a6520f34c2acb369afb57e3ea4449be6ff8fd", - "sha256:845b1daf4df2dd94d2fdbc9454953ca9dd0e12970a0bfc9f3dcc6faea3fa96e4", - "sha256:8780e69f9deec9d60f947b169507d2c9816e4f11548f1f7ebee2af38b9b22ae4", - "sha256:bf413f2a9b0a2950fc750998899013f2e718d20fa4a58b85ca50b6df5ed1bbf9", - "sha256:bfb67f6a6c72dfb0a02f3df51550aa1862708e55128b22543e2b42c74f3620d7", - "sha256:c59c170fc9225faad04dde1ba61d85b413946e8ce2e5f5f5ff30dfd67283f319", - "sha256:dc6ec3dc19b1c193b2f7cf279d3e32e7caf447532fbcb7af0906fe4398900c33", - "sha256:ede0f506554571c8eda80db22b83c139303ec6b595b8f60c4c8157bdd0bdee36" + "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535", + "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0", + "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410", + "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd", + "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665", + "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab", + "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71", + "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215", + "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b", + "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda", + "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9", + "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a", + "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344", + "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f", + "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d", + "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c", + "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c", + "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2", + "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d", + "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e", + "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3" ], "index": "pypi", - "version": "==4.0.0" + "version": "==4.0.1" }, "beanie": { "hashes": [ - "sha256:0d27c089fc316fbbe1effe09104f0d1b62185fd8cae766b322a05254f9018eb2", - "sha256:740d8479b17bc78b16b9636b274a01878844fc87aef01f8bffa97c967bcecfd9" + "sha256:3aae32ba6bd40c3768ca1126a07725577d45133d240cca50ef1e6a35699f6063", + "sha256:954e33ffc7b6b79eec87b61a20c36e296dab98fe021e6798f3f2de752f35f9a6" ], "index": "pypi", - "version": "==1.12.0" + "version": "==1.13.1" }, "bioblend": { "hashes": [ - "sha256:0cfbe8f11b0c3813a3822a9640931ae62ea14bea31e21591bca1310b25e745b3", - "sha256:2e1ce7e34f1363a0375d56185dcfa6a2834e2dff74157cb3b7fb34876772defb" + "sha256:3794288bbf891ae6edc1bcdd9618a3ae16b6ed4a04c946505f7e29f2f28898a5", + "sha256:db9616a77c614f3de900796079e9db72af739809232702d5ea4acf5ef49b4d38" ], "markers": "python_version >= '3.7'", - "version": "==0.18.0" - }, - "boto": { - "hashes": [ - "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8", - "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a" - ], - "version": "==2.49.0" + "version": "==1.0.0" }, "certifi": { "hashes": [ @@ -199,11 +201,11 @@ }, "fastapi": { "hashes": [ - "sha256:1803d962f169dc9f8dde54a64b22eb16f6d81573f54401971f90f0a67234a8b4", - "sha256:bb219cfafd0d2ccf8f32310c9a257a06b0210bd8e2a03706a6f5a9f9f1416878" + "sha256:3e10ea0992c700e0b17b6de8c2092d7b9cd763ce92c49ee8d4be10fee3b2f367", + "sha256:6292db0edd4a11f0d938d6033ccec5f706e9d476958bf33b119e8ddb4e524bde" ], "index": "pypi", - "version": "==0.85.0" + "version": "==0.85.2" }, "filelock": { "hashes": [ @@ -331,11 +333,11 @@ }, "motor": { "hashes": [ - "sha256:203bb5e29fce22bfedc232b84e0170cd0b8bdbfa3be9df1cd472bc5180e90b75", - "sha256:b76cf533f64adbeeaa192941fbc6474d38dfc61d1f53c8d06faea197fc6a91ff" + "sha256:01d93d7c512810dcd85f4d634a7244ba42ff6be7340c869791fe793561e734da", + "sha256:a4bdadf8a08ebb186ba16e557ba432aa867f689a42b80f2e9f8b24bbb1604742" ], "index": "pypi", - "version": "==3.1.0.dev0" + "version": "==3.1.1" }, "multidict": { "hashes": [ @@ -378,19 +380,19 @@ }, "pika": { "hashes": [ - "sha256:15357ddc47a5c28f0b07d80e93d504cbbf7a1ad5e1cd129ecd27afe76472c529", - "sha256:9195f37aed089862b205fd8f8ce1cc6ea0a7ee3cd80f58e6eea6cb9d8411a647" + "sha256:89f5e606646caebe3c00cbdbc4c2c609834adde45d7507311807b5775edac8e0", + "sha256:beb19ff6dd1547f99a29acc2c6987ebb2ba7c44bf44a3f8e305877c5ef7d2fdc" ], "index": "pypi", - "version": "==1.3.0" + "version": "==1.3.1" }, "pipenv": { "hashes": [ - "sha256:dc2539c7f4ad10737f6c211493f99e2bbc8161571d71ac29f162dfed86886bb0", - "sha256:fc1982e47e8214f47713efadf61cd61ff643b5988372a83edd040cf0f7d942f2" + "sha256:0ece09bd57c703c57a2b1dbe89758568819bf93a98ca0b471f249152120124c8", + "sha256:3e39c8d5a2bcaab324552a18576105c2a35e020bb311ff53d74eacb58b851853" ], "index": "pypi", - "version": "==2022.10.4" + "version": "==2022.10.25" }, "pipfile": { "hashes": [ @@ -459,84 +461,91 @@ }, "pyjwt": { "hashes": [ - "sha256:8d82e7087868e94dd8d7d418e5088ce64f7daab4b36db654cbaedb46f9d1ca80", - "sha256:e77ab89480905d86998442ac5788f35333fa85f65047a534adc38edf3c88fc3b" + "sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd", + "sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14" ], "index": "pypi", - "version": "==2.5.0" + "version": "==2.6.0" }, "pymongo": { "hashes": [ - "sha256:01721da74558f2f64a9f162ee063df403ed656b7d84229268d8e4ae99cfba59c", - "sha256:07564178ecc203a84f63e72972691af6c0c82d2dc0c9da66ba711695276089ba", - "sha256:0f53253f4777cbccc426e669a2af875f26c95bd090d88593287b9a0a8ac7fa25", - "sha256:10f09c4f09757c2e2a707ad7304f5d69cb8fdf7cbfb644dbacfe5bbe8afe311b", - "sha256:124d0e880b66f9b0778613198e89984984fdd37a3030a9007e5f459a42dfa2d3", - "sha256:147a23cd96feb67606ac957744d8d25b013426cdc3c7164a4f99bd8253f649e3", - "sha256:153b8f8705970756226dfeeb7bb9637e0ad54a4d79b480b4c8244e34e16e1662", - "sha256:193cc97d44b1e6d2253ea94e30c6f94f994efb7166e2452af4df55825266e88b", - "sha256:1a957cdc2b26eeed4d8f1889a40c6023dd1bd94672dd0f5ce327314f2caaefd4", - "sha256:1c81414b706627f15e921e29ae2403aab52e33e36ed92ed989c602888d7c3b90", - "sha256:21238b19243a42f9a34a6d39e7580ceebc6da6d2f3cf729c1cff9023cb61a5f1", - "sha256:2bfe6b59f431f40fa545547616f4acf0c0c4b64518b1f951083e3bad06eb368b", - "sha256:314b556afd72eb21a6a10bd1f45ef252509f014f80207db59c97372103c88237", - "sha256:31c50da4a080166bc29403aa91f4c76e0889b4f24928d1b60508a37c1bf87f9a", - "sha256:3be53e9888e759c49ae35d747ff77a04ff82b894dd64601e0f3a5a159b406245", - "sha256:44b36ccb90aac5ea50be23c1a6e8f24fbfc78afabdef114af16c6e0a80981364", - "sha256:4cadaaa5c19ad23fc84559e90284f2eb003c36958ebb2c06f286b678f441285f", - "sha256:60c470a58c5b62b1b12a5f5458f8e2f2f67b94e198d03dc5352f854d9230c394", - "sha256:6673ab3fbf3135cc1a8c0f70d480db5b2378c3a70af8d602f73f76b8338bdf97", - "sha256:68e1e49a5675748233f7b05330f092582cd52f2850b4244939fd75ba640593ed", - "sha256:69d0180bca594e81cdb4a2af328bdb4046f59e10aaeef7619496fe64f2ec918c", - "sha256:6bd5888997ea3eae9830c6cc7964b61dcfbc50eb3a5a6ce56ad5f86d5579b11c", - "sha256:701d331060dae72bf3ebdb82924405d14136a69282ccb00c89fc69dee21340b4", - "sha256:70216ec4c248213ae95ea499b6314c385ce01a5946c448fb22f6c8395806e740", - "sha256:72f338f6aabd37d343bd9d1fdd3de921104d395766bcc5cdc4039e4c2dd97766", - "sha256:764fc15418d94bce5c2f8ebdbf66544f96f42efb1364b61e715e5b33281b388d", - "sha256:766acb5b1a19eae0f7467bcd3398748f110ea5309cdfc59faa5185dcc7fd4dca", - "sha256:76892bbce743eb9f90360b3626ea92f13d338010a1004b4488e79e555b339921", - "sha256:773467d25c293f8e981b092361dab5fd800e1ba318403b7959d35004c67faedc", - "sha256:80cbf0b043061451660099fff9001a7faacb2c9c983842b4819526e2f944dc6c", - "sha256:83168126ae2457d1a19b2af665cafa7ef78c2dcff192d7d7b5dad6b36c73ae24", - "sha256:83cc3c35aeeceb67143914db67f685206e1aa37ea837d872f4bc28d7f80917c9", - "sha256:8a86e8c2ac2ec87141e1c6cb00bdb18a4560f06e5f96769abcd1dda24dc0e764", - "sha256:8a9bc4dcfc2bda69ee88cdb7a89b03f2b8eca668519b704384a264dea2db4209", - "sha256:8c223aea52c359cc8fdee5bd3475532590755c269ec4d4fe581acd47a44e9952", - "sha256:8cbb868e88c4eee1c53364bb343d226a3c0e959e791e6828030cb78f46cfcbe3", - "sha256:902e2c9030cb042c49750bc70d72d830d42c64ea0df5ff8630c171e065c93dd7", - "sha256:a25c0eb2d610b20e276e684be61c337396813b636b69373c17314283cb1a3b14", - "sha256:a3efdf154844244e0dabe902cf1827fdced55fa5b144adec2a86e5ce50a99b97", - "sha256:a6bf01b9237f794fa3bdad5089474067d28be7e199b356a18d3f247a45775f26", - "sha256:a7eb5b06744b911b6668b427c8abc71b6d624e72d3dfffed00988fa1b4340f97", - "sha256:b0be613d926c5dbb0d3fc6b58e4f2be4979f80ae76fda6e47309f011b388fe0c", - "sha256:b211e161b6cc2790e0d640ad38e0429d06c944e5da23410f4dc61809dba25095", - "sha256:b537dd282de1b53d9ae7cf9f3df36420c8618390f2da92100391f3ba8f3c141a", - "sha256:b9e4981a65f8500a3a46bb3a1e81b9feb45cf0b2115ad9c4f8d517326d026940", - "sha256:c549bb519456ee230e92f415c5b4d962094caac0fdbcc4ed22b576f66169764e", - "sha256:c69ef5906dcd6ec565d4d887ba97ceb2a84f3b614307ee3b4780cb1ea40b1867", - "sha256:c8b4a782aac43948308087b962c9ecb030ba98886ce6dee3ad7aafe8c5e1ce80", - "sha256:cc7ebc37b03956a070260665079665eae69e5e96007694214f3a2107af96816a", - "sha256:ccfdc7722df445c49dc6b5d514c3544cad99b53189165f7546793933050ac7fb", - "sha256:d8bb745321716e7a11220a67c88212ecedde4021e1de4802e563baef9df921d2", - "sha256:d94f535df9f539615bc3dbbef185ded3b609373bb44ca1afffcabac70202678a", - "sha256:d98d2a8283c9928a9e5adf2f3c0181e095579e9732e1613aaa55d386e2bcb6c5", - "sha256:dc24737d24ce0de762bee9c2a884639819485f679bbac8ab5be9c161ef6f9b2c", - "sha256:e08fe1731f5429435b8dea1db9663f9ed1812915ff803fc9991c7c4841ed62ad", - "sha256:e09cdf5aad507c8faa30d97884cc42932ed3a9c2b7f22cc3ccc607bae03981b3", - "sha256:e152c26ffc30331e9d57591fc4c05453c209aa20ba299d1deb7173f7d1958c22", - "sha256:e1b8f5e2f9637492b0da4d51f78ecb17786e61d6c461ead8542c944750faf4f9", - "sha256:e39cacee70a98758f9b2da53ee175378f07c60113b1fa4fae40cbaee5583181e", - "sha256:e64442aba81ed4df1ca494b87bf818569a1280acaa73071c68014f7a884e83f1", - "sha256:e7dcb73f683c155885a3488646fcead3a895765fed16e93c9b80000bc69e96cb", - "sha256:ecdcb0d4e9b08b739035f57a09330efc6f464bd7f942b63897395d996ca6ebd5", - "sha256:ed90a9de4431cbfb2f3b2ef0c5fd356e61c85117b2be4db3eae28cb409f6e2d5", - "sha256:f1c23527f8e13f526fededbb96f2e7888f179fe27c51d41c2724f7059b75b2fa", - "sha256:f47d5f10922cf7f7dfcd1406bd0926cef6d866a75953c3745502dffd7ac197dd", - "sha256:fe0820d169635e41c14a5d21514282e0b93347878666ec9d5d3bf0eed0649948", - "sha256:ff66014687598823b6b23751884b4aa67eb934445406d95894dfc60cb7bfcc18" + "sha256:006799ddba1f2e73ce27689f016791ab80e51876c52ae2265d8c76016baaa10e", + "sha256:02140c1a9f2107a16c074c9e558a556faafb0dc3c2e9332c6685c5506823ab9d", + "sha256:04597a5d877a984b5e3059e942b02d68f8af9bb4328592abca27e82015560112", + "sha256:07e05784578bf7f8ecdfc6d0fd1e684e6259e9b5fdb5439a58c4f0df950fae29", + "sha256:07f58d05d2289f93e16ddc93be6e0453fa67afd33c1b015f6bd3d9741c0963ff", + "sha256:0c8f061eabef3a6b3696f7f7be3eaed7928864ff84a2248429f9c7eb564343cc", + "sha256:0d7ad2112a705e992ca0cca98ccbb874276c495f8d9df627438c2ee94f810a3d", + "sha256:0f48c2562a1d1426b6db7567511dc62817df43357041e1fd4ea5c68278bfa11b", + "sha256:11630f5b3287375c85f5b7a788d3a7241671af24fda2b49a3396bc53cbf1c0c6", + "sha256:178ffaa833d473b16fbd65c4a485af56484a50e2a201e8d0547f98cf5007f133", + "sha256:1be15568e4b2be4c75bc54a542276c857628e09cbc283befcf4c45a0a22c1eec", + "sha256:21e1cfa3e73cd253afcad32e2a46a277f52553635ccc0dd4d643f5824af88428", + "sha256:253faefea46482ffa87c77fdd01cd95d430cc84aae8d7a78ba920ea6cebcf3c7", + "sha256:26dd79e60f883b6467b91c8af0be484147365b18cebf9248f8e72c035aecb693", + "sha256:28ab644adc92c21a249570e2d677ebf4f2ef374630ddec98f19d2630dcb154c6", + "sha256:2c821c897498e3e3c3254f7a90195f71473361f502201fd396281869d8108857", + "sha256:315fe5f628e9aee67cc4c17b91ddf08c5c0917b764f433a5acf9aed33164a8f0", + "sha256:352bc034e112c9f6a408e2796e74bae900d3167a804224b2c24ea75b5d57e9f9", + "sha256:35e9eec45a212306143367b0702c2aff75c375290015af00fa8b653641c20b34", + "sha256:36e7a74bdab9aa19f5ac94dfd74111d2164ccea752afbef0aa039d1266e7c404", + "sha256:372307185d8e17ea31d2f3ff6943e213a6c379ccf547f18b05a58a1620d6f92a", + "sha256:39308580bcdbc368a2664c48761226c06b1d3368cc3ab3492d3cca88dc2e5e27", + "sha256:3966dcba4b80dbc0eb4dd08d6f7127e3b1701cd829b6c13507a956c878b78546", + "sha256:3f41781c8310fe1ae3ed0b809e2d7be6ebba9f0954c08e1d18ac443916b82b29", + "sha256:404bc7f7190e8975f41f0c7498e303e9cb291f6384e1889ac4333448652a83d6", + "sha256:4f7763c9e37e6d59406ce2defc25266980b24a86708ec6db753b02459db45715", + "sha256:5231eb29e8174509250bc5fc609d6e8eceebfb209bf37bd6e014cbd7b6554344", + "sha256:53dd2c034fb92c019e5e581cd361ed3fa9833abb56cc76725d56dcba169746fe", + "sha256:6049927b50c39e7dc51e75b5bb30c8501fbf1f08414b3447bcc9f9f967c116ed", + "sha256:6461d29a967e1980ba7798e4da8178dbe4245fe4a66ebb3aa07339c9da383c3a", + "sha256:6498ae9a76ad64617703373a43e3cd8454271bca0d7d395b393b4f31aa68f734", + "sha256:64b010681019c0b312f342e3aae1f3091a7dc7ff4b7a3dec72fc0e7238be9477", + "sha256:68213f4c1531b95dcfef40f79dd95e94484f69ec5949b7f42f82ad2bee135f7f", + "sha256:68320e5326e2b1e49dcd901e6dcbe3009b8a0fd0da0c618579a2be7cf5f2d7be", + "sha256:6db95d3e955aa5dbe42db691dd77cdddc0bc15f9883aa1def51f3ca40d49c1d6", + "sha256:715ad027daff84e213ab74fa3ec98cad8dabb669653a71daa0dd6f80a1c32dd0", + "sha256:7424b7c59b16e7889a720a5b2e2dda518753c6fec6c6582ab2fcedf97df3df75", + "sha256:77436db17ab2baec2356cf38db32d13c7cd11267c8137864c67391f2dfdcc5e4", + "sha256:7b2a8b2b7d9196d46e5181f88632eeca5bf79a69ca2e9911229c58f66aebfbeb", + "sha256:7c22ad464688a807bec103734cbdf712489c74d439cdd346e6f12095070bfbf5", + "sha256:7ce5d43c011e03cd1a42a4dcc0d5c8772f18533cdfe672a63607942d62581df4", + "sha256:7f907daec92208d748db4ea04568aa33e9254e0c27e4e40ac287e1b1ca8b12b5", + "sha256:80bdfc7039674c670e1afbf95849ce2075731785527eeac7e3850e862dec239b", + "sha256:8817b17db2013354aa7f187d5825d65da0d7720b5ca697af37ff5efdf97e7f62", + "sha256:8d81f6f5f6e66481aadd2fc087a937833312de23cd94b5ea1b225f35fafb0a00", + "sha256:8f968621d019ed165f1cb5b037875ce3425ea7704407234895c7c52ad32190da", + "sha256:94639935caf13af551429bd13e4cb20e7c110a57d07f0c6a84a9bf3c2c9000ad", + "sha256:95913659d6c5fc714e662533d014836c988cc1561684f07b6a0a8343651afa66", + "sha256:95f41c4e3b9e315655d6d1136d904ceda24fe5ea2d273ec6f9d66dbef06f3446", + "sha256:98fd65c2aee7a55615dda1a1b0340ae8d756151983cb5040ea59a730083221e7", + "sha256:a06c9ca15a2133478d1c775c4e7e5e782961b6254a3fc81ab5d0fb3cf9b8e358", + "sha256:ab7f49c5ca3db7ae94743b0da1b21c5e7402a561a0614c1b0fba718aad591611", + "sha256:aee8fafea8bb669deb0dd4878d947f79b2ef298e60f06e1fe799598929b68be2", + "sha256:af46f635513c7339419374f46f4f662cee7140bfb86de4377885a2c1de2278d4", + "sha256:b36da8aeb95cc1abea7b80e578fb6bcdbe395638d16b1b0068bc121e2111a00f", + "sha256:b4b683a40cf07b6d16704ead92a7aee24208d3af83d55d31248cdac003f8591c", + "sha256:b510843ea70e5bc9c096a93f683b28e8d43f1ad89da0126502d88b3d90f07ebe", + "sha256:c5db3bddbbc2657aa76088e76d24a616aefc98883c48dc27f3c3829ddb2ca10d", + "sha256:c8e82d6cc2f1cf5017485f55d67375bacf73d95c40903759e46024a987bab86f", + "sha256:cad31512e6956c95210fbd585d5b80df28425251260387164c6382894f0c6eca", + "sha256:cb47ba9c19da8fb4174f9d7bbbdb1796ad288c61dda35c96fb45d69e61d3a5cb", + "sha256:cc7b269af274ac0d5d9a5c8d035b03ccc34438baa01705bf8ec7cc6a31093ace", + "sha256:ce14598b8fa93e51aed0f400e446fddd6b26297ba5965fd0c0585614b60b9fc0", + "sha256:cea32bd14d8c0725e22e5fcc607a81e3636650c689697c12423a34f9a125c7e2", + "sha256:ceded83530f5507dadd873f8d004b56f996de44d9c3f56b7f26c22ca823f12ee", + "sha256:cefd851fdea191fc4db780157a28a11e0a80bccd34c454a73f252a287d28b2c7", + "sha256:d7bdfac2f3c87d0971691f2a091427f55bb6b94b23d74213ed2de87d8facba85", + "sha256:dab1d89f969046057be2b904a7bbf40df114f43aebfb3ccdceb054d9c40ec56d", + "sha256:db94b741dde2cc44ec038495d041c8f6dd4d510bb4e5d0be1b9f9aae4fbb28c6", + "sha256:e4082d1b660e70d9df71da00050f7adb902b73a2287216e69ada124bd2f89636", + "sha256:e96483316a799923f13bb61170f05feab22e8bd8630bf8cdcd440c78f307039a", + "sha256:f3861081540e1f06d1e5d131d1419b9fc507834b6865407e0f56735b4082566c", + "sha256:f423e066de040f4f93dcac0e6ceec37ffc25cc591a609ecc3ab20adfdbb787ae", + "sha256:f84b8428a41d7d7f2931762c27b09ffa8b3bc51e3b5dab40ab2b1d008091247e" ], "markers": "python_version >= '3.7'", - "version": "==4.2.0" + "version": "==4.3.2" }, "python-dateutil": { "hashes": [ @@ -647,11 +656,11 @@ }, "setuptools": { "hashes": [ - "sha256:1b6bdc6161661409c5f21508763dc63ab20a9ac2f8ba20029aaaa7fdb9118012", - "sha256:3050e338e5871e70c72983072fe34f6032ae1cdeeeb67338199c2f74e083a80e" + "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17", + "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356" ], "markers": "python_version >= '3.7'", - "version": "==65.4.1" + "version": "==65.5.0" }, "six": { "hashes": [ @@ -701,11 +710,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" + "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", + "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" ], "markers": "python_version < '3.10'", - "version": "==4.3.0" + "version": "==4.4.0" }, "urllib3": { "hashes": [ @@ -717,19 +726,19 @@ }, "uvicorn": { "hashes": [ - "sha256:0abd429ebb41e604ed8d2be6c60530de3408f250e8d2d84967d85ba9e86fe3af", - "sha256:9a66e7c42a2a95222f76ec24a4b754c158261c4696e683b9dadc72b590e0311b" + "sha256:cc277f7e73435748e69e075a721841f7c4a95dba06d12a72fe9874acced16f6f", + "sha256:cf538f3018536edb1f4a826311137ab4944ed741d52aeb98846f52215de57f25" ], "index": "pypi", - "version": "==0.18.3" + "version": "==0.19.0" }, "virtualenv": { "hashes": [ - "sha256:227ea1b9994fdc5ea31977ba3383ef296d7472ea85be9d6732e42a91c04e80da", - "sha256:d07dfc5df5e4e0dbc92862350ad87a36ed505b978f6c39609dc489eadd5b0d27" + "sha256:186ca84254abcbde98180fd17092f9628c5fe742273c02724972a1d8a2035108", + "sha256:530b850b523c6449406dfba859d6345e48ef19b8439606c5d74d7d3c9e14d76e" ], "markers": "python_version >= '3.6'", - "version": "==20.16.5" + "version": "==20.16.6" }, "virtualenv-clone": { "hashes": [ @@ -816,32 +825,30 @@ }, "black": { "hashes": [ - "sha256:0a12e4e1353819af41df998b02c6742643cfef58282915f781d0e4dd7a200411", - "sha256:0ad827325a3a634bae88ae7747db1a395d5ee02cf05d9aa7a9bd77dfb10e940c", - "sha256:32a4b17f644fc288c6ee2bafdf5e3b045f4eff84693ac069d87b1a347d861497", - "sha256:3b2c25f8dea5e8444bdc6788a2f543e1fb01494e144480bc17f806178378005e", - "sha256:4a098a69a02596e1f2a58a2a1c8d5a05d5a74461af552b371e82f9fa4ada8342", - "sha256:5107ea36b2b61917956d018bd25129baf9ad1125e39324a9b18248d362156a27", - "sha256:53198e28a1fb865e9fe97f88220da2e44df6da82b18833b588b1883b16bb5d41", - "sha256:5594efbdc35426e35a7defa1ea1a1cb97c7dbd34c0e49af7fb593a36bd45edab", - "sha256:5b879eb439094751185d1cfdca43023bc6786bd3c60372462b6f051efa6281a5", - "sha256:78dd85caaab7c3153054756b9fe8c611efa63d9e7aecfa33e533060cb14b6d16", - "sha256:792f7eb540ba9a17e8656538701d3eb1afcb134e3b45b71f20b25c77a8db7e6e", - "sha256:8ce13ffed7e66dda0da3e0b2eb1bdfc83f5812f66e09aca2b0978593ed636b6c", - "sha256:a05da0430bd5ced89176db098567973be52ce175a55677436a271102d7eaa3fe", - "sha256:a983526af1bea1e4cf6768e649990f28ee4f4137266921c2c3cee8116ae42ec3", - "sha256:bc4d4123830a2d190e9cc42a2e43570f82ace35c3aeb26a512a2102bce5af7ec", - "sha256:c3a73f66b6d5ba7288cd5d6dad9b4c9b43f4e8a4b789a94bf5abfb878c663eb3", - "sha256:ce957f1d6b78a8a231b18e0dd2d94a33d2ba738cd88a7fe64f53f659eea49fdd", - "sha256:cea1b2542d4e2c02c332e83150e41e3ca80dc0fb8de20df3c5e98e242156222c", - "sha256:d2c21d439b2baf7aa80d6dd4e3659259be64c6f49dfd0f32091063db0e006db4", - "sha256:d839150f61d09e7217f52917259831fe2b689f5c8e5e32611736351b89bb2a90", - "sha256:dd82842bb272297503cbec1a2600b6bfb338dae017186f8f215c8958f8acf869", - "sha256:e8166b7bfe5dcb56d325385bd1d1e0f635f24aae14b3ae437102dedc0c186747", - "sha256:e981e20ec152dfb3e77418fb616077937378b322d7b26aa1ff87717fb18b4875" + "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7", + "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6", + "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650", + "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb", + "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d", + "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d", + "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de", + "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395", + "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae", + "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa", + "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef", + "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383", + "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66", + "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87", + "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d", + "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0", + "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b", + "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458", + "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4", + "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1", + "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff" ], "index": "pypi", - "version": "==22.8.0" + "version": "==22.10.0" }, "certifi": { "hashes": [ @@ -867,13 +874,21 @@ "markers": "python_version >= '3.7'", "version": "==8.1.3" }, + "exceptiongroup": { + "hashes": [ + "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41", + "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad" + ], + "markers": "python_version < '3.11'", + "version": "==1.0.0" + }, "faker": { "hashes": [ - "sha256:245fc7d23470dc57164bd9a59b7b1126e16289ffcf813d88a6c8e9b8a37ea3fb", - "sha256:84c83f0ac1a2c8ecabd784c501aa0ef1d082d4aee52c3d797d586081c166434c" + "sha256:096c15e136adb365db24d8c3964fe26bfc68fe060c9385071a339f8c14e09c8a", + "sha256:a741b77f484215c3aab2604100669657189548f440fcb2ed0f8b7ee21c385629" ], "index": "pypi", - "version": "==15.0.0" + "version": "==15.1.1" }, "idna": { "hashes": [ @@ -929,14 +944,6 @@ "markers": "python_version >= '3.6'", "version": "==1.0.0" }, - "py": { - "hashes": [ - "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", - "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.11.0" - }, "pyparsing": { "hashes": [ "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", @@ -947,11 +954,19 @@ }, "pytest": { "hashes": [ - "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7", - "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39" + "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71", + "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59" + ], + "index": "pypi", + "version": "==7.2.0" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:2c85a835df33fda40fe3973b451e0c194ca11bc2c007eabff90bb3d156fc172b", + "sha256:626699de2a747611f3eeb64168b3575f70439b06c3d0206e6ceaeeb956e65519" ], "index": "pypi", - "version": "==7.1.3" + "version": "==0.20.1" }, "python-dateutil": { "hashes": [ @@ -987,11 +1002,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" + "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", + "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" ], "markers": "python_version < '3.10'", - "version": "==4.3.0" + "version": "==4.4.0" }, "urllib3": { "hashes": [ diff --git a/backend/app/database/errors.py b/backend/app/database/errors.py new file mode 100644 index 000000000..fe4be1e8b --- /dev/null +++ b/backend/app/database/errors.py @@ -0,0 +1,42 @@ +import logging +import traceback +import motor.motor_asyncio +from typing import Optional, Generator +from fastapi import Depends +from pymongo import MongoClient + +from app.config import settings +from app.mongo import crete_mongo_indexes +from app.models.errors import Error +from app.models.metadata import MongoDBRef + +logger = logging.getLogger(__name__) + + +async def _get_db() -> Generator: + """Duplicate of app.dependencies.get_db(), but importing that causes circular import.""" + mongo_client = motor.motor_asyncio.AsyncIOMotorClient(settings.MONGODB_URL) + db = mongo_client[settings.MONGO_DATABASE] + await crete_mongo_indexes(db) + yield db + + +async def log_error( + exception: Exception, + resource: Optional[MongoDBRef] = None, + user: Optional[str] = None, +): + """Insert new Error into the database. + + Arguments: + exception -- instance of an Exception or subclass + resource -- if error relates to a specific resource, you can include it + user --- if error relates to actions performed by a user, you can include them + """ + db = _get_db() + message = str(exception) + trace = traceback.format_exc(exception, limit=4) + + logger.error(message) + error_log = Error(message=message, trace=trace, resource=resource, user=user) + await db["errors"].insert_one(error_log.to_mongo()) diff --git a/backend/app/main.py b/backend/app/main.py index e44b01288..1062c6191 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -145,7 +145,7 @@ @app.on_event("startup") async def startup_elasticsearch(): # create elasticsearch indices - es = connect_elasticsearch() + es = await connect_elasticsearch() create_index( es, "file", settings.elasticsearch_setting, indexSettings.file_mappings ) diff --git a/backend/app/models/errors.py b/backend/app/models/errors.py new file mode 100644 index 000000000..bfda50ce1 --- /dev/null +++ b/backend/app/models/errors.py @@ -0,0 +1,25 @@ +from datetime import datetime +from typing import Optional +from pydantic import Field + +from app.models.mongomodel import MongoModel +from app.models.metadata import MongoDBRef + + +class ServiceUnreachable(Exception): + """Raised when Clowder can't connect to an outside service e.g. MongoDB, Elasticsearch.""" + + def __init__(self, service, *args): + super().__init__(args) + self.service = service + + def __str__(self): + return f"{self.service} could not be reached." + + +class Error(MongoModel): + message: str # Shorthand message of the error + trace: str # Full stack trace of the error + resource: Optional[MongoDBRef] = None + user_id: Optional[str] = None + timestamp: datetime = Field(default_factory=datetime.utcnow) diff --git a/backend/app/routers/datasets.py b/backend/app/routers/datasets.py index d42f8a69b..983f1851b 100644 --- a/backend/app/routers/datasets.py +++ b/backend/app/routers/datasets.py @@ -31,6 +31,7 @@ from app import dependencies from app import keycloak_auth from app.search.connect import ( + connect_elasticsearch, insert_record, delete_document_by_id, update_record, @@ -191,6 +192,7 @@ async def save_dataset( db: MongoClient = Depends(dependencies.get_db), es=Depends(dependencies.get_elasticsearchclient), ): + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or es is None: @@ -304,6 +306,7 @@ async def edit_dataset( user_id=Depends(get_user), es=Depends(dependencies.get_elasticsearchclient), ): + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or es is None: @@ -347,6 +350,7 @@ async def patch_dataset( db: MongoClient = Depends(dependencies.get_db), es=Depends(dependencies.get_elasticsearchclient), ): + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or es is None: @@ -388,6 +392,7 @@ async def delete_dataset( fs: Minio = Depends(dependencies.get_fs), es=Depends(dependencies.get_elasticsearchclient), ): + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or fs is None or es is None: diff --git a/backend/app/routers/elasticsearch.py b/backend/app/routers/elasticsearch.py index 3fe4bec05..822756090 100644 --- a/backend/app/routers/elasticsearch.py +++ b/backend/app/routers/elasticsearch.py @@ -7,26 +7,26 @@ @router.put("/search", response_model=str) async def search(index_name: str, query: str): - es = connect_elasticsearch() + es = await connect_elasticsearch() return search_index(es, index_name, query) @router.post("/file/_msearch") async def search_file(request: Request): - es = connect_elasticsearch() + es = await connect_elasticsearch() query = await request.body() return search_index(es, "file", query) @router.post("/dataset/_msearch") async def search_dataset(request: Request): - es = connect_elasticsearch() + es = await connect_elasticsearch() query = await request.body() return search_index(es, "dataset", query) @router.post("/file,dataset/_msearch") async def search_file_and_dataset(request: Request): - es = connect_elasticsearch() + es = await connect_elasticsearch() query = await request.body() return search_index(es, ["file", "dataset"], query) diff --git a/backend/app/routers/files.py b/backend/app/routers/files.py index 7d5d22370..e0ac313fb 100644 --- a/backend/app/routers/files.py +++ b/backend/app/routers/files.py @@ -22,6 +22,7 @@ from app import dependencies from app.config import settings from app.search.connect import ( + connect_elasticsearch, insert_record, delete_document_by_id, update_record, @@ -55,6 +56,7 @@ async def add_file_entry( file_db: FileDB object controlling dataset and folder destination file: bytes to upload """ + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or fs is None or es is None: @@ -124,6 +126,8 @@ async def remove_file_entry( """Remove FileDB object into MongoDB, Minio, and associated metadata and version information.""" # TODO: Deleting individual versions will require updating version_id in mongo, or deleting entire document + es = await connect_elasticsearch() + # Check all connection and abort if any one of them is not available if db is None or fs is None or es is None: raise HTTPException(status_code=503, detail="Service not available") @@ -146,6 +150,7 @@ async def update_file( file: UploadFile = File(...), es=Depends(dependencies.get_elasticsearchclient), ): + es = await connect_elasticsearch() # Check all connection and abort if any one of them is not available if db is None or fs is None or es is None: diff --git a/backend/app/search/connect.py b/backend/app/search/connect.py index e3d8449b2..f4b29dbd4 100644 --- a/backend/app/search/connect.py +++ b/backend/app/search/connect.py @@ -7,21 +7,26 @@ from app.models.files import FileOut from app.models.search import SearchCriteria from app.models.feeds import SearchObject +from app.models.errors import ServiceUnreachable +from app.database.errors import log_error logger = logging.getLogger(__name__) no_of_shards = settings.elasticsearch_no_of_shards no_of_replicas = settings.elasticsearch_no_of_replicas -def connect_elasticsearch(): +async def connect_elasticsearch(): """To connect to elasticsearch server and return the elasticsearch client""" _es = None logger.info(settings.elasticsearch_url) _es = Elasticsearch(settings.elasticsearch_url) - if _es.ping(): - logger.info("Successfully connected to Elasticsearch") - else: - logger.info("Can not connect to Elasticsearch") + try: + if _es.ping(): + logger.info("Successfully connected to Elasticsearch") + else: + raise ServiceUnreachable("Elasticsearch") + except ServiceUnreachable as e: + await log_error(e) return _es diff --git a/backend/app/tests/test_elastic_search.py b/backend/app/tests/test_elastic_search.py index 7bebdf324..d05418e18 100644 --- a/backend/app/tests/test_elastic_search.py +++ b/backend/app/tests/test_elastic_search.py @@ -1,5 +1,6 @@ import json import time +import pytest from datetime import datetime from bson import ObjectId @@ -57,8 +58,9 @@ } -def test_files(): - es = connect_elasticsearch() +@pytest.mark.asyncio +async def test_files(): + es = await connect_elasticsearch() if es is not None: create_index( es, @@ -95,8 +97,9 @@ def test_files(): delete_index(es, dummy_file_index_name) -def test_datasets(): - es = connect_elasticsearch() +@pytest.mark.asyncio +async def test_datasets(): + es = await connect_elasticsearch() if es is not None: create_index( es,