diff --git a/.env.example b/.env.example index 44fcae3da..b3e592bdf 100644 --- a/.env.example +++ b/.env.example @@ -56,3 +56,10 @@ LANGFLOW_REMOVE_API_KEYS= # LANGFLOW_REDIS_CACHE_EXPIRE (default: 3600) LANGFLOW_CACHE_TYPE= +# Superuser username +# Example: LANGFLOW_SUPERUSER=admin +LANGFLOW_SUPERUSER= + +# Superuser password +# Example: LANGFLOW_SUPERUSER_PASSWORD=123456 +LANGFLOW_SUPERUSER_PASSWORD= diff --git a/Makefile b/Makefile index 031c5e479..65d4253f0 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ coverage: --cov-report term-missing:skip-covered tests: + @make install_backend poetry run pytest tests -n auto format: diff --git a/poetry.lock b/poetry.lock index 30efaa559..8fb013726 100644 --- a/poetry.lock +++ b/poetry.lock @@ -907,76 +907,76 @@ testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] [[package]] name = "clickhouse-connect" -version = "0.6.13" +version = "0.6.14" description = "ClickHouse Database Core Driver for Python, Pandas, and Superset" optional = false python-versions = "~=3.7" files = [ - {file = "clickhouse-connect-0.6.13.tar.gz", hash = "sha256:affec3369f486db1d17fc5447fef541a9a70df09c03e0ed4af6b328b6e6a4827"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3538dd61054af1d7af712f0203265969e351ca6e21a138c5cc967a4d63bc684"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:08eac69a47c5d5bba727a475593662d5583a44a2168cb34c7e9727b0949edf05"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34cad54d3af842f98db7eda9a0fd4c0201383c6e6316b3db364a5e62957d3f92"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9ecd833018ae61b1b5c23f1856e63112eb5a9240e30ae79e7cd63032bcc7683"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52cf7b75f4c9a215d1cde4bdab079b463f75edecf311a9f34248340de8c58ab8"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a5febb40a3220c2a3aaddaffe3cbc0c2c668dbf58d68875c5236551a43fb54f2"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:71072c28ef2d1d5c41f23b898014c8c491c54a745a13a545cd18e60d44d7276e"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:47135049bacfdb67272df3e988458fc8cb3ca31df7fd020d7c28801272f319ae"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-win32.whl", hash = "sha256:3ad88ca2b34d330513ac8e76f74dca4c1879a6ad81f6ef331e626400c3b9ff62"}, - {file = "clickhouse_connect-0.6.13-cp310-cp310-win_amd64.whl", hash = "sha256:092ddacb003a193f17ee3dbb6ac5df8397730154df95c668342e419e35dc42df"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e77efffc06dede8ac479678420cc5e15b2be28b73119a458766047b964d31a36"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:39669fc21d1ab76fe6042511e424a00c7b5b731db2ff59c7a6222f15a65a77b0"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25005cf2c44bc46fa11b3e95de53830c172bf6f1cc512a2628bd62861b60777a"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d049b3c88466db6806d9b301436ddb69024df8cb1c14e5b21fab4517b67094"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c329296469651124fb9787b6c060c22c05dfad1129f8e3683721cfe98b2b6574"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9bb3a8f985626a8c5fc8d12e7e16e1f1774ef5c574faf10432e41a2e97ec2684"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ed964a08ebd8ce4ddf44686efcf706fe6089a0b439813a4796c6cf3fc4f5ab11"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9f4d3e17fa7c0b35e420450b18ad9fdde70f92635c12a69e5a18c699720c0442"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-win32.whl", hash = "sha256:fcab92aadd62ecc4dbe9f841c72e714f519f5251f45bf04f761504cd419abff3"}, - {file = "clickhouse_connect-0.6.13-cp311-cp311-win_amd64.whl", hash = "sha256:a312939b94ec2dd49556cbef880804898fc14d5ca52aeb3d00b9905047ca64e0"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e3fef39ce56c5550ebc701fc439ca517eca10c57166216ebd37b664a5352be7"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1841a5f1c1298907c42e23fef1f4bdcdb6c7c40b2844469ccd4780e8f7cc16f"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:120618bf66df0908c0b8b5e8ea07c068d98032a9f498c832b1b02aa2cef91474"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3a7c34efd02e68445cc6bf13f6de9c4b294112351e79a386cbd65c13fa08965"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a3f6a6975759b0b3aa8a4a6e05533bdce234a16804e69282bb0c01a5a37851a"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6317a3ee357ce7129de18ce344792c545f4b28a190a47bf4047414c9b12dfaf2"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b0d07ae7b0d7ede51a336dfee5bbfdbf123957a50e9452d57f58b0c803517f21"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-win32.whl", hash = "sha256:ef0ca69741762e512a6f1882d53bb1e607e2e04d24db995c8c0b3409943891b4"}, - {file = "clickhouse_connect-0.6.13-cp37-cp37m-win_amd64.whl", hash = "sha256:a5ba1ed57f4d8a47a87e353756746d4199527568b962931f5d6b9388ba72d8f3"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:03f6738e9c737531d7ec67611cb476ca8b817b583e5f46349fc63b7357cdda4e"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:484b528d3c79f07f9c8a6586fb254578b8f8140a5a309820737f5017e9edd02e"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0c5589016da8a0a1c21d2461a98a6cab7c22633423735647632f5b5c0de7109"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81495c2d12a6420c1f3ee5d0cf3996329dbfd60e12e53905fd9da577b992c0c8"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2239972b84dd33baf7cd552b53dec024716b87fbebb3a2ff741398a96fa15777"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9737310a7466f5ac10077ecbe10237e816a12a8cc4c651c2be82eaf25895042b"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a229d67f1dec0351faf7634f523c8fcf78b602ee02b0e25c93f4d5018147d4f4"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a996fdf7d8e6bc18c9365fc06bd429418510cf63476a056e36afee505f570dad"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-win32.whl", hash = "sha256:56e51196caeb6b7f7b62af8e58ce1a653e29c694e4cf0964907ca7b42b32e7f0"}, - {file = "clickhouse_connect-0.6.13-cp38-cp38-win_amd64.whl", hash = "sha256:a7b0cfec5eff21ec81f713de77a136d74f9336a20da5096b7a046b27ca1014b7"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:909a6d4406a9320d85d7b71a131e68f9289ec66453ba7bf14e9a110db5f18e3d"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7845ad20a8fba276dff1670c1bbedc3dc2c4d560fa486d8960fdd217b188099"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9d5eb2036b740496a8d9f871cf928493fbc7d9edfc543e16f5db56ef359d468"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe0b889587bfe2962cbfe1b0a908f8bafee332a8f955f38fa307561dd73a962c"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0414e6a2b2e19ad4165cb01503086d229473465217be86a7824cf9f4a2d3964"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9065b9a7def6e1f7bf74e9c81825927f0b9147fcf1f0d172533552d931311279"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2b7b4e29c781d8feb87cac6133ef8a20b59cd70e600d9f37875dd74384c8b792"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:66778f60bc66891ff375aa28447846a7f176743800f8fbec23001b05b8912020"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-win32.whl", hash = "sha256:fa1f34d5b56f86417be2490e9cb22b1b27ff788e569636fdae1027d66816c2b3"}, - {file = "clickhouse_connect-0.6.13-cp39-cp39-win_amd64.whl", hash = "sha256:b66574c7dc2a805071b582a66a0a46c92d3b3e1e897336cc32c5e0054204b401"}, - {file = "clickhouse_connect-0.6.13-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c87224b4ecec054395759cfbe5aab56f1728a14fb382178b0ae29c06068a1487"}, - {file = "clickhouse_connect-0.6.13-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2f416e38cc935f982443a21642eac3d09e56f32fffa7a2ec90f36175bcd92ee"}, - {file = "clickhouse_connect-0.6.13-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caffe66da4d9f8777b72ac93884ce7726a08a154527a444aa3e9913f4f44523f"}, - {file = "clickhouse_connect-0.6.13-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fdcb082acf5a1b754ea360e5df0f8805c17df1db9cdc47dcf10c7cfc2f0ea4d0"}, - {file = "clickhouse_connect-0.6.13-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:bebfd2d9fbaf67a84c78cce0f48cac3224c9eef62de7334e57dd32d38399bec9"}, - {file = "clickhouse_connect-0.6.13-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:98ef70b8e63f3145603a570bd479bc66f1269be18baec5df71c2f58959c345c1"}, - {file = "clickhouse_connect-0.6.13-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd1ea8c2b694bb441371c7c964a9ff9b92489863087a306419fa8680ff189056"}, - {file = "clickhouse_connect-0.6.13-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba59dead59a7f32522f502d3061fa70f0978b0a03ebe7992dcea53be4a5f587e"}, - {file = "clickhouse_connect-0.6.13-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c40ac936bb35bbf32aca6881755e392ba2ef3eece028e7b24c40498a662e9bfe"}, - {file = "clickhouse_connect-0.6.13-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:70397690dc7574d2ff546f311bd2243177925cc74f0df2613d2985a0da8c7516"}, - {file = "clickhouse_connect-0.6.13-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d3ec25049fff943844e24a65112d15ed4d006f7c528362dd997844e4bcfce7cd"}, - {file = "clickhouse_connect-0.6.13-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b8614233a0ff7a3b469876b95dcf4557ed8fbc15c6997d49ddbde323537161"}, - {file = "clickhouse_connect-0.6.13-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bf02bc20bf308853d6d382dac0d3347e4db2e76987610a098c7b1b207f355"}, - {file = "clickhouse_connect-0.6.13-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebd96561056f316ce129e9f7bdaa8043ee4c2f872903f36eff0920022487cba"}, - {file = "clickhouse_connect-0.6.13-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7de7099025a00954940dfe76f29ab529c5bece4ad8a2bc4131b7b8ff35ad60c8"}, + {file = "clickhouse-connect-0.6.14.tar.gz", hash = "sha256:0531bbd5b8bdee616bf1cca5ddcb0af86db12e2b48fd39257a8ecdf32200bd57"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04affbd255fb8b1e4a882ddc1336c86530976d05578f47bb65e3a53471d291e4"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5bd61f2665f1890fa632b1181df2900ea838cf152cd9a3f775841ea2deab680"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79897a0987008993f32737e17045a5c1982f9193f7511a3832a7ba3429cbf6b4"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa95c8a96bdff593924407b074d616ee8a1bfb989579c17b330c6f3b27febfe3"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501c0d843be30c86719b61089fb1de6298ac44b3670594f0a1cb0dc3ad97651e"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1ec9672c9ed9d5e62f66ac14d6470b9b6be9946d6d24ddac87376437863b8f59"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:92173354a6c7c5862fab09dab338197b86a192e0c117137e899e8cf92cc3b5b7"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:757b4c05ebf10bdcb916334c3021ee571a61238907cdeee8c54bcf0550cd0d19"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-win32.whl", hash = "sha256:2e74badf6c7569e1a0ad32f3be250a3ebf28a9df3b15c9709104e5f050486016"}, + {file = "clickhouse_connect-0.6.14-cp310-cp310-win_amd64.whl", hash = "sha256:7b56c422467df5a0b2790e0943b747639f1f172fac7f8d9585adb3302c961fb1"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d2aa6d28d79eb5ca94d7c756ec4dc599d2354897f5ef40fd0d8bdc579a81dd94"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70cd5b2e0d80dc030355d09db213c73caa78ef259f2b04ce30c1c8cb513bf45b"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:826c85e37555443af945a0d977598814ba7cb09447b0cdd167eae57dfd3f0724"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cdb1f843d134a1e30828900bc51c9c1b4f4e638aac693767685e512fb095af5"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a8ea6ca6e0d6b1af50078413e280f271559c462a8644541002e44c2cb5c371"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8b72a5e5d54069dff419a6ec9bbc7f3896fe558551cae6a2b2cba60eaa0607a3"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c531ed454ca9b6d85e739de3770a82eec2087ed2cb9660fb8ff0e62f7f1446cc"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ae6ebf7c507f9d0fece9d1e387c9eec77762693f91647bca18f588cf1d594d24"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-win32.whl", hash = "sha256:cf1e3067c2da8525b6f59a37f8e13cd6c4524f439be8fd7d8fa03f007f96c863"}, + {file = "clickhouse_connect-0.6.14-cp311-cp311-win_amd64.whl", hash = "sha256:15a040210877cc34155943c7870bf78247d4d4fa3bd4e0595ca22e97760679b7"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:eb91e4ee0435088fc8bd36de51a93ff9286a514d82ac373b57b2d6cad4655d77"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48108bb1cfe99b6ff60344838859aec1315213dfa618f6ca4b92c0c6e5ae8d41"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c75d4bd8ef0b90f9e89ea70c16ff099278e4bb8f1e045008376ac34c6122b73d"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:897f40eda84e9c45d0bdaf3a9e638e614e236a4a5eeab5cddd920857f9f8f22a"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5ecc88656df05ae49e70062aee7022982eec3f87fb14db97c25276fef6633d7c"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:76cec48265774ae3fa61a77b290dcc8385aad4312a8d7dfcaffb9fc00f79458e"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dba280e00ec4cfe0e4d69f88baa9a0491bc1ed83ec57336e5197adae8d42d0c9"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-win32.whl", hash = "sha256:6c77f537e04747702e009c05f4a7f6f96cbe1696bb89d29f72e39e7370924836"}, + {file = "clickhouse_connect-0.6.14-cp37-cp37m-win_amd64.whl", hash = "sha256:d0eceaff68a53f71384bb9aee7fc1630f68ac10538727c8516ae0af1103f2580"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dfa09948caeed539cdd019a1e341a379a1dcacdd755b278d12484b4a703afa3"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a30d99cb1fd57b8fed4449632e51d48386d0eec1673f905572c5fc7059215c20"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e88de4fe66ae2b1c15726760cc87a703e4d1162de52a19c8d8b57a4429f08e"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03d721de610beae823068665d6c604a5f390a99e7b2354264b17136a3a520b13"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a627762f2f692e226b3cb574a83133844213c6507c6313d3fefd8a3de08e5798"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:62a596f8d9db8592477a2032c329be7449ea32d133cdc4e5d6f804e251b8617a"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e8ab9e5a61968c328a0fdc254b02b96142ebb4ec2bc1623f9498538f0ebfdc7c"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6c21fe379b1b8822eb9644600e38220b5c4b530fd0f2b1da824a0918120a8f01"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-win32.whl", hash = "sha256:2a17b336781d3fbb67ed556918c17e63c7d462709aa6a953bb3410ddb67fd7f4"}, + {file = "clickhouse_connect-0.6.14-cp38-cp38-win_amd64.whl", hash = "sha256:838a008c0f7d911ab81f741ea27a64ef7bdcc2508698b70f018987dfc742ffa9"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:083649a97c3f366f66f0f2578b9f88d86c1d3a40b9015c9403db524fda36a952"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e9bd6849852b2c55e51a477e10bc8b61990c5f37f31cce5ea6fc970b447b5af"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9152c45423f488cf6229bce1f9e695cd81e7ffcd3ae0f1e40e5e62079b18d4a5"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341e068d4a6a423ed22fb3b96cfe16be0d6305943c3fb1cc48251b7d9729931d"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead7acb841524bd7a73b1f10592a36e901d63bc89af3270ab76b89a11d44fe20"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8bce432f72dcf6679c2d0bac4e3a82a126389ad7951d316f213109cee6925c7c"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1f403499f169574cafb05888dfdaf18065cc49ff1321e5e108c504c8c220e172"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3189fcd339bfd7ae4e703ff40b110b9740d6b1ec8385ed8bd1547663fd046578"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-win32.whl", hash = "sha256:a30de3f0997a9157e840c2d4e07fd9c6fc6e359f1ff9f3a46386b5abdca73c1a"}, + {file = "clickhouse_connect-0.6.14-cp39-cp39-win_amd64.whl", hash = "sha256:c3476a95780374e94dfba2a28093d15f8370bfa6f4cb46a02e0af8813e5f7368"}, + {file = "clickhouse_connect-0.6.14-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:22affe46983e67e3923e9330336d21e9ec4b4812b6fbeb1865514145b3870170"}, + {file = "clickhouse_connect-0.6.14-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62727090af8875631115911f58442967386b31cd4efa93c951c2aa7e57d1ce4b"}, + {file = "clickhouse_connect-0.6.14-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee4ea5ac58de0580f2e12b46cfd2f8d13c1e690378bf9775bfed0c935232de71"}, + {file = "clickhouse_connect-0.6.14-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a126fe486dd02fa5f8adb0b9d8fd0fc701fb73b2275e1040ed210afadd189f90"}, + {file = "clickhouse_connect-0.6.14-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:de6bf773c8776033ca5fb5a6a376729ae69afdd0b19a71d1460d1a221fc5a627"}, + {file = "clickhouse_connect-0.6.14-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d27d2c9698d1acb550ac8c30c4d9440c7d826a16444e4aea4dacf11ed7ec8988"}, + {file = "clickhouse_connect-0.6.14-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f57efbe536dfbfb7e10dd16ced6fe02441fb174450760f0b29b2b60d23c6462f"}, + {file = "clickhouse_connect-0.6.14-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c134483da38a3d3e38c44da9f3d519d73e177998052d36129e21863c7a3497ee"}, + {file = "clickhouse_connect-0.6.14-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d6ae7ccb4ca3d310c2971ead9839935890e40da8602dcc92ecda9bbbb24366"}, + {file = "clickhouse_connect-0.6.14-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0acf6b69b11b757d60545b0ccac3df4980f69351994e30074df84729bb5af5d1"}, + {file = "clickhouse_connect-0.6.14-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e043b3b606749d23eca7601a1a44f188c6f117ae57a2852c66c21f11b7296fe4"}, + {file = "clickhouse_connect-0.6.14-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a887dfef3f3914454c7d7a428db8063b1678c66678cbabcd6368f0b67876f1"}, + {file = "clickhouse_connect-0.6.14-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e255e7c9c38fb9bceefc659374d04914ef2222a6f121fccf86a865b81110e96b"}, + {file = "clickhouse_connect-0.6.14-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2be9a6ba1d3055bb6956be218ffecfa3bfbe47121dfa34467815aa883f15d159"}, + {file = "clickhouse_connect-0.6.14-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:59faa034fdd58c1e7c8b2f4a033e9c611a0c58e193339cdd62d9d91a62f11195"}, ] [package.dependencies] @@ -3960,13 +3960,13 @@ files = [ [[package]] name = "metal-sdk" -version = "2.1.2" +version = "2.1.3" description = "SDK for getmetal.io" optional = false python-versions = ">=3.7" files = [ - {file = "metal_sdk-2.1.2-py3-none-any.whl", hash = "sha256:542ee620173994b43344779d8d9fc5540b06d4ac30941d824769f1e8bf767c0c"}, - {file = "metal_sdk-2.1.2.tar.gz", hash = "sha256:a22895a5babd9c6bdd651ca4289f593ba5eee9742b97d12e6c5a859a3befef96"}, + {file = "metal_sdk-2.1.3-py3-none-any.whl", hash = "sha256:c79f4ddb78b9ec83bb73969ce535ae33c601d34525088ee40268bc2ac5f69ba2"}, + {file = "metal_sdk-2.1.3.tar.gz", hash = "sha256:43cb6244d7af5e1fe21b3d0fe59ee2e0f40d0350ea4779e80d9cf366d760407e"}, ] [package.dependencies] diff --git a/src/backend/langflow/__main__.py b/src/backend/langflow/__main__.py index a6a2ea540..c63b371ed 100644 --- a/src/backend/langflow/__main__.py +++ b/src/backend/langflow/__main__.py @@ -360,8 +360,8 @@ def superuser( # Verify that the superuser was created from langflow.services.database.models.user.user import User - user = session.query(User).filter(User.username == username).first() - if user is None: + user: User = session.query(User).filter(User.username == username).first() + if user is None or not user.is_superuser: typer.echo("Superuser creation failed.") return diff --git a/src/backend/langflow/api/v1/api_key.py b/src/backend/langflow/api/v1/api_key.py index 280f240e8..7f5916d06 100644 --- a/src/backend/langflow/api/v1/api_key.py +++ b/src/backend/langflow/api/v1/api_key.py @@ -14,7 +14,7 @@ from langflow.services.database.models.api_key.crud import ( delete_api_key, ) from langflow.services.database.models.user.user import User -from langflow.services.utils import get_session +from langflow.services.getters import get_session from sqlmodel import Session diff --git a/src/backend/langflow/api/v1/chat.py b/src/backend/langflow/api/v1/chat.py index 0740b7517..f97c65aff 100644 --- a/src/backend/langflow/api/v1/chat.py +++ b/src/backend/langflow/api/v1/chat.py @@ -13,9 +13,9 @@ from langflow.api.v1.schemas import BuildStatus, BuiltResponse, InitResponse, St from langflow.graph.graph.base import Graph from langflow.services.auth.utils import get_current_active_user, get_current_user -from langflow.services.utils import get_cache_service, get_session from loguru import logger -from langflow.services.utils import get_chat_service +from langflow.services.getters import get_chat_service, get_session, get_cache_service +from cachetools import LRUCache from sqlmodel import Session from langflow.services.chat.manager import ChatService from langflow.services.cache.manager import BaseCacheService diff --git a/src/backend/langflow/api/v1/components.py b/src/backend/langflow/api/v1/components.py index 4071461fb..d2b39dfd2 100644 --- a/src/backend/langflow/api/v1/components.py +++ b/src/backend/langflow/api/v1/components.py @@ -2,7 +2,7 @@ from datetime import timezone from typing import List from uuid import UUID from langflow.services.database.models.component import Component, ComponentModel -from langflow.services.utils import get_session +from langflow.services.getters import get_session from sqlmodel import Session, select from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.exc import IntegrityError diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 274fe26ff..4d034a59f 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -7,7 +7,7 @@ from langflow.services.cache.utils import save_uploaded_file from langflow.services.database.models.flow import Flow from langflow.processing.process import process_graph_cached, process_tweaks from langflow.services.database.models.user.user import User -from langflow.services.utils import get_settings_service, get_task_service +from langflow.services.getters import get_settings_service, get_task_service from loguru import logger from fastapi import APIRouter, Depends, HTTPException, UploadFile, Body, status import sqlalchemy as sa diff --git a/src/backend/langflow/api/v1/login.py b/src/backend/langflow/api/v1/login.py index e67580b9d..969cf096e 100644 --- a/src/backend/langflow/api/v1/login.py +++ b/src/backend/langflow/api/v1/login.py @@ -2,7 +2,7 @@ from sqlmodel import Session from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm -from langflow.services.utils import get_session +from langflow.services.getters import get_session from langflow.api.v1.schemas import Token from langflow.services.auth.utils import ( authenticate_user, diff --git a/src/backend/langflow/api/v1/users.py b/src/backend/langflow/api/v1/users.py index e68512e43..e1e24d197 100644 --- a/src/backend/langflow/api/v1/users.py +++ b/src/backend/langflow/api/v1/users.py @@ -13,7 +13,7 @@ from sqlalchemy.exc import IntegrityError from sqlmodel import Session, select from fastapi import APIRouter, Depends, HTTPException -from langflow.services.utils import get_session +from langflow.services.getters import get_session from langflow.services.auth.utils import ( get_current_active_superuser, get_current_active_user, diff --git a/src/backend/langflow/main.py b/src/backend/langflow/main.py index c869ec138..9caa157d0 100644 --- a/src/backend/langflow/main.py +++ b/src/backend/langflow/main.py @@ -9,9 +9,11 @@ from langflow.api import router from langflow.interface.utils import setup_llm_caching -from langflow.services.database.utils import initialize_database -from langflow.services.manager import initialize_services, teardown_services +from langflow.services.utils import initialize_services from langflow.services.plugins.langfuse import LangfuseInstance +from langflow.services.utils import ( + teardown_services, +) from langflow.utils.logger import configure @@ -39,11 +41,12 @@ def create_app(): app.include_router(router) app.on_event("startup")(initialize_services) - app.on_event("startup")(initialize_database) app.on_event("startup")(setup_llm_caching) - app.on_event("shutdown")(teardown_services) app.on_event("startup")(LangfuseInstance.update) + + app.on_event("shutdown")(teardown_services) app.on_event("shutdown")(LangfuseInstance.teardown) + return app diff --git a/src/backend/langflow/services/auth/utils.py b/src/backend/langflow/services/auth/utils.py index 3d52ba80f..a8c7d7b4f 100644 --- a/src/backend/langflow/services/auth/utils.py +++ b/src/backend/langflow/services/auth/utils.py @@ -37,15 +37,13 @@ async def api_key_security( result: Optional[Union[ApiKey, User]] = None if settings_service.auth_settings.AUTO_LOGIN: # Get the first user - if not settings_service.auth_settings.FIRST_SUPERUSER: + if not settings_manager.auth_settings.SUPERUSER: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Missing first superuser credentials", ) - result = get_user_by_username( - db, settings_service.auth_settings.FIRST_SUPERUSER - ) + result = get_user_by_username(db, settings_manager.auth_settings.SUPERUSER) elif not query_param and not header_param: raise HTTPException( @@ -181,9 +179,9 @@ def create_super_user( def create_user_longterm_token(db: Session = Depends(get_session)) -> dict: - settings_service = get_settings_service() - username = settings_service.auth_settings.FIRST_SUPERUSER - password = settings_service.auth_settings.FIRST_SUPERUSER_PASSWORD + settings_manager = get_settings_service() + username = settings_manager.auth_settings.SUPERUSER + password = settings_manager.auth_settings.SUPERUSER_PASSWORD if not username or not password: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, diff --git a/src/backend/langflow/services/base.py b/src/backend/langflow/services/base.py index aaa966047..301771944 100644 --- a/src/backend/langflow/services/base.py +++ b/src/backend/langflow/services/base.py @@ -3,6 +3,10 @@ from abc import ABC class Service(ABC): name: str + ready: bool = False def teardown(self): pass + + def set_ready(self): + self.ready = True diff --git a/src/backend/langflow/services/database/manager.py b/src/backend/langflow/services/database/manager.py index f348a6a5d..46ced4524 100644 --- a/src/backend/langflow/services/database/manager.py +++ b/src/backend/langflow/services/database/manager.py @@ -164,10 +164,10 @@ class DatabaseService(Service): try: settings_service = get_settings_service() # remove the default superuser if auto_login is enabled - # using the FIRST_SUPERUSER to get the user + # using the SUPERUSER to get the user if settings_service.auth_settings.AUTO_LOGIN: logger.debug("Removing default superuser") - username = settings_service.auth_settings.FIRST_SUPERUSER + username = settings_service.auth_settings.SUPERUSER with Session(self.engine) as session: user = get_user_by_username(session, username) session.delete(user) diff --git a/src/backend/langflow/services/database/models/user/crud.py b/src/backend/langflow/services/database/models/user/crud.py index f7f5958fe..36f03e684 100644 --- a/src/backend/langflow/services/database/models/user/crud.py +++ b/src/backend/langflow/services/database/models/user/crud.py @@ -3,7 +3,7 @@ from typing import Union from uuid import UUID from fastapi import Depends, HTTPException, status from langflow.services.database.models.user.user import User, UserUpdate -from langflow.services.utils import get_session +from langflow.services.getters import get_session from sqlalchemy.exc import IntegrityError from sqlmodel import Session from typing import Optional diff --git a/src/backend/langflow/services/getters.py b/src/backend/langflow/services/getters.py new file mode 100644 index 000000000..8b32aef02 --- /dev/null +++ b/src/backend/langflow/services/getters.py @@ -0,0 +1,26 @@ +from langflow.services import ServiceType, service_manager +from typing import TYPE_CHECKING, Generator + + +if TYPE_CHECKING: + from langflow.services.database.manager import DatabaseManager + from langflow.services.settings.manager import SettingsManager + from langflow.services.chat.manager import ChatManager + from sqlmodel import Session + + +def get_settings_manager() -> "SettingsManager": + return service_manager.get(ServiceType.SETTINGS_MANAGER) + + +def get_db_manager() -> "DatabaseManager": + return service_manager.get(ServiceType.DATABASE_MANAGER) + + +def get_session() -> Generator["Session", None, None]: + db_manager = service_manager.get(ServiceType.DATABASE_MANAGER) + yield from db_manager.get_session() + + +def get_chat_manager() -> "ChatManager": + return service_manager.get(ServiceType.CHAT_MANAGER) diff --git a/src/backend/langflow/services/manager.py b/src/backend/langflow/services/manager.py index e6d8aabd1..31aeeda60 100644 --- a/src/backend/langflow/services/manager.py +++ b/src/backend/langflow/services/manager.py @@ -62,6 +62,7 @@ class ServiceManager: self.services[service_name] = self.factories[service_name].create( **dependent_services ) + self.services[service_name].set_ready() def _validate_service_creation(self, service_name: ServiceType): """ @@ -113,34 +114,34 @@ def initialize_services(): service_manager.register_factory(settings_factory.SettingsServiceFactory()) service_manager.register_factory( database_factory.DatabaseServiceFactory(), - dependencies=[ServiceType.SETTINGS_MANAGER], + dependencies=[ServiceType.SETTINGS_SERVICE], ) service_manager.register_factory( - cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_MANAGER] + cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE] ) service_manager.register_factory( - auth_factory.AuthServiceFactory(), dependencies=[ServiceType.SETTINGS_MANAGER] + auth_factory.AuthServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE] ) service_manager.register_factory(chat_factory.ChatServiceFactory()) service_manager.register_factory( session_service_factory.SessionServiceFactory(), - dependencies=[ServiceType.CACHE_MANAGER], + dependencies=[ServiceType.CACHE_SERVICE], ) service_manager.register_factory( task_factory.TaskServiceFactory(), ) # Test cache connection - service_manager.get(ServiceType.CACHE_MANAGER) + service_manager.get(ServiceType.CACHE_SERVICE) # Test database connection - service_manager.get(ServiceType.DATABASE_MANAGER) + service_manager.get(ServiceType.DATABASE_SERVICE) # Test cache connection - service_manager.get(ServiceType.CACHE_MANAGER) + service_manager.get(ServiceType.CACHE_SERVICE) # Test database connection - service_manager.get(ServiceType.DATABASE_MANAGER) + service_manager.get(ServiceType.DATABASE_SERVICE) def reinitialize_services(): @@ -155,23 +156,23 @@ def reinitialize_services(): from langflow.services.auth import factory as auth_factory from langflow.services.task import factory as task_factory - service_manager.update(ServiceType.SETTINGS_MANAGER) - service_manager.update(ServiceType.DATABASE_MANAGER) - service_manager.update(ServiceType.CACHE_MANAGER) - service_manager.update(ServiceType.CHAT_MANAGER) - service_manager.update(ServiceType.SESSION_MANAGER) - service_manager.update(ServiceType.AUTH_MANAGER) - service_manager.update(ServiceType.TASK_MANAGER) + service_manager.update(ServiceType.SETTINGS_SERVICE) + service_manager.update(ServiceType.DATABASE_SERVICE) + service_manager.update(ServiceType.CACHE_SERVICE) + service_manager.update(ServiceType.CHAT_SERVICE) + service_manager.update(ServiceType.SESSION_SERVICE) + service_manager.update(ServiceType.AUTH_SERVICE) + service_manager.update(ServiceType.TASK_SERVICE) # Test cache connection - service_manager.get(ServiceType.CACHE_MANAGER) + service_manager.get(ServiceType.CACHE_SERVICE) # Test database connection - service_manager.get(ServiceType.DATABASE_MANAGER) + service_manager.get(ServiceType.DATABASE_SERVICE) # Test cache connection - service_manager.get(ServiceType.CACHE_MANAGER) + service_manager.get(ServiceType.CACHE_SERVICE) # Test database connection - service_manager.get(ServiceType.DATABASE_MANAGER) + service_manager.get(ServiceType.DATABASE_SERVICE) def initialize_settings_service(): @@ -193,12 +194,12 @@ def initialize_session_service(): initialize_settings_service() service_manager.register_factory( - cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_MANAGER] + cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE] ) service_manager.register_factory( session_service_factory.SessionServiceFactory(), - dependencies=[ServiceType.CACHE_MANAGER], + dependencies=[ServiceType.CACHE_SERVICE], ) diff --git a/src/backend/langflow/services/settings/auth.py b/src/backend/langflow/services/settings/auth.py index 87a156df7..b6d288183 100644 --- a/src/backend/langflow/services/settings/auth.py +++ b/src/backend/langflow/services/settings/auth.py @@ -1,6 +1,10 @@ from pathlib import Path from typing import Optional import secrets +from langflow.services.settings.constants import ( + DEFAULT_SUPERUSER, + DEFAULT_SUPERUSER_PASSWORD, +) from langflow.services.settings.utils import read_secret_from_file, write_secret_to_file from pydantic import BaseSettings, Field, validator @@ -30,9 +34,9 @@ class AuthSettings(BaseSettings): # If AUTO_LOGIN = True # > The application does not request login and logs in automatically as a super user. - AUTO_LOGIN: bool = True - FIRST_SUPERUSER: str = "langflow" - FIRST_SUPERUSER_PASSWORD: str = "langflow" + AUTO_LOGIN: bool = False + SUPERUSER: str = DEFAULT_SUPERUSER + SUPERUSER_PASSWORD: str = DEFAULT_SUPERUSER_PASSWORD pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") @@ -41,6 +45,28 @@ class AuthSettings(BaseSettings): extra = "ignore" env_prefix = "LANGFLOW_" + def reset_credentials(self): + self.SUPERUSER = DEFAULT_SUPERUSER + self.SUPERUSER_PASSWORD = DEFAULT_SUPERUSER_PASSWORD + + # If autologin is true, then we need to set the credentials to + # the default values + # so we need to validate the superuser and superuser_password + # fields + @validator("SUPERUSER", "SUPERUSER_PASSWORD", pre=True) + def validate_superuser(cls, value, values): + if values.get("AUTO_LOGIN"): + if value != DEFAULT_SUPERUSER: + value = DEFAULT_SUPERUSER + logger.debug("Resetting superuser to default value") + if values.get("SUPERUSER_PASSWORD") != DEFAULT_SUPERUSER_PASSWORD: + values["SUPERUSER_PASSWORD"] = DEFAULT_SUPERUSER_PASSWORD + logger.debug("Resetting superuser password to default value") + + return value + + return value + @validator("SECRET_KEY", pre=True) def get_secret_key(cls, value, values): config_dir = values.get("CONFIG_DIR") diff --git a/src/backend/langflow/services/settings/constants.py b/src/backend/langflow/services/settings/constants.py new file mode 100644 index 000000000..6cf7d4823 --- /dev/null +++ b/src/backend/langflow/services/settings/constants.py @@ -0,0 +1,2 @@ +DEFAULT_SUPERUSER = "langflow" +DEFAULT_SUPERUSER_PASSWORD = "langflow" diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index 9eb7ce66a..71ad9258d 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -1,48 +1,143 @@ -from langflow.services import ServiceType, service_manager -from typing import TYPE_CHECKING, Generator +from langflow.services.auth.utils import create_super_user +from langflow.services.database.utils import initialize_database +from langflow.services.manager import service_manager +from langflow.services.schema import ServiceType +from langflow.services.settings.constants import ( + DEFAULT_SUPERUSER, + DEFAULT_SUPERUSER_PASSWORD, +) +from .getters import get_session, get_settings_service +from loguru import logger -if TYPE_CHECKING: - from langflow.services.database.manager import DatabaseService - from langflow.services.settings.manager import SettingsService - from langflow.services.cache.manager import BaseCacheService - from langflow.services.session.manager import SessionService - from langflow.services.task.manager import TaskService - from langflow.services.chat.manager import ChatService - from sqlmodel import Session +def setup_superuser(): + """ + Setup the superuser. + """ + # We will use the SUPERUSER and SUPERUSER_PASSWORD + # vars on settings_manager.auth_settings to create the superuser + # if it does not exist. + settings_manager = get_settings_service() + if settings_manager.auth_settings.AUTO_LOGIN: + logger.debug("AUTO_LOGIN is set to True. Creating default superuser.") + session = next(get_session()) + username = settings_manager.auth_settings.SUPERUSER + password = settings_manager.auth_settings.SUPERUSER_PASSWORD + if username == DEFAULT_SUPERUSER and password == DEFAULT_SUPERUSER_PASSWORD: + logger.debug("Default superuser credentials detected.") + logger.debug("Creating default superuser.") + else: + logger.debug("Creating superuser.") -def get_settings_service() -> "SettingsService": try: - return service_manager.get(ServiceType.SETTINGS_MANAGER) - except ValueError: - # initialize settings service - from langflow.services.manager import initialize_settings_service + from langflow.services.database.models.user.user import User - initialize_settings_service() - return service_manager.get(ServiceType.SETTINGS_MANAGER) + user = session.query(User).filter(User.username == username).first() + if user and user.is_superuser is True: + return + except Exception as exc: + logger.exception(exc) + raise RuntimeError( + "Could not create superuser. Please create a superuser manually." + ) from exc + try: + # create superuser + create_super_user(db=session, username=username, password=password) + except Exception as exc: + logger.exception(exc) + raise RuntimeError( + "Could not create superuser. Please create a superuser manually." + ) from exc + # reset superuser credentials + settings_manager.auth_settings.reset_credentials() + logger.debug("Superuser created successfully.") -def get_db_service() -> "DatabaseService": - return service_manager.get(ServiceType.DATABASE_MANAGER) +def teardown_superuser(): + """ + Teardown the superuser. + """ + # If AUTO_LOGIN is True, we will remove the default superuser + # from the database. + settings_manager = get_settings_service() + if settings_manager.auth_settings.AUTO_LOGIN: + logger.debug("AUTO_LOGIN is set to True. Removing default superuser.") + session = next(get_session()) + username = settings_manager.auth_settings.SUPERUSER + from langflow.services.database.models.user.user import User + + user = session.query(User).filter(User.username == username).first() + if user and user.is_superuser: + session.delete(user) + session.commit() + logger.debug("Default superuser removed successfully.") + else: + logger.debug("Default superuser not found.") -def get_session() -> Generator["Session", None, None]: - db_service = service_manager.get(ServiceType.DATABASE_MANAGER) - yield from db_service.get_session() +def teardown_services(): + """ + Teardown all the services. + """ + teardown_superuser() + service_manager.teardown() -def get_cache_service() -> "BaseCacheService": - return service_manager.get(ServiceType.CACHE_MANAGER) +def initialize_settings_manager(): + """ + Initialize the settings manager. + """ + from langflow.services.settings import factory as settings_factory + + service_manager.register_factory(settings_factory.SettingsManagerFactory()) -def get_session_service() -> "SessionService": - return service_manager.get(ServiceType.SESSION_MANAGER) +def initialize_session_manager(): + """ + Initialize the session manager. + """ + from langflow.services.session import factory as session_manager_factory # type: ignore + from langflow.services.cache import factory as cache_factory + + initialize_settings_manager() + + service_manager.register_factory( + cache_factory.CacheManagerFactory(), dependencies=[ServiceType.SETTINGS_MANAGER] + ) + + service_manager.register_factory( + session_manager_factory.SessionManagerFactory(), + dependencies=[ServiceType.CACHE_MANAGER], + ) -def get_task_service() -> "TaskService": - return service_manager.get(ServiceType.TASK_MANAGER) +def initialize_services(): + """ + Initialize all the services needed. + """ + from langflow.services.database import factory as database_factory + from langflow.services.cache import factory as cache_factory + from langflow.services.chat import factory as chat_factory + from langflow.services.settings import factory as settings_factory + from langflow.services.auth import factory as auth_factory + service_manager.register_factory(settings_factory.SettingsManagerFactory()) + service_manager.register_factory( + auth_factory.AuthManagerFactory(), dependencies=[ServiceType.SETTINGS_MANAGER] + ) + service_manager.register_factory( + database_factory.DatabaseManagerFactory(), + dependencies=[ServiceType.SETTINGS_MANAGER], + ) + service_manager.register_factory(cache_factory.CacheManagerFactory()) + service_manager.register_factory(chat_factory.ChatManagerFactory()) -def get_chat_service() -> "ChatService": - return service_manager.get(ServiceType.CHAT_MANAGER) + # Test cache connection + service_manager.get(ServiceType.CACHE_MANAGER) + # Test database connection + db_manager = service_manager.get(ServiceType.DATABASE_MANAGER) + # Setup the superuser + initialize_database() + if db_manager.ready: + setup_superuser() diff --git a/src/frontend/src/components/EditFlowSettingsComponent/index.tsx b/src/frontend/src/components/EditFlowSettingsComponent/index.tsx index b939b4f07..8f9907129 100644 --- a/src/frontend/src/components/EditFlowSettingsComponent/index.tsx +++ b/src/frontend/src/components/EditFlowSettingsComponent/index.tsx @@ -36,15 +36,16 @@ export const EditFlowSettings: React.FC = ({ } if (invalidName !== undefined) { if (!nameLists.current.includes(value)) { - setInvalidName(false); + setInvalidName!(false); } else { - setInvalidName(true); + setInvalidName!(true); + } + + if (!nameLists.current.includes(value)) { + setInvalidName!(false); + } else { + setInvalidName!(true); } - } - if (!nameLists.current.includes(value)) { - setInvalidName!(false); - } else { - setInvalidName!(true); } setName(value); }; diff --git a/tests/conftest.py b/tests/conftest.py index b767b602d..b07da309f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,13 +2,14 @@ from contextlib import contextmanager import json from pathlib import Path from typing import AsyncGenerator, TYPE_CHECKING -from langflow.api.v1.flows import get_session from langflow.graph.graph.base import Graph from langflow.services.auth.utils import get_password_hash from langflow.services.database.models.flow.flow import Flow, FlowCreate from langflow.services.database.models.user.user import User, UserCreate import orjson +from langflow.services.database.utils import session_getter +from langflow.services.getters import get_db_manager import pytest from fastapi.testclient import TestClient from httpx import AsyncClient @@ -16,6 +17,9 @@ from sqlmodel import SQLModel, Session, create_engine from sqlmodel.pool import StaticPool from typer.testing import CliRunner +# we need to import tmpdir +import tempfile + if TYPE_CHECKING: from langflow.services.database.manager import DatabaseService @@ -61,22 +65,6 @@ def session_fixture(): yield session -@pytest.fixture(name="client") -def client_fixture(session: Session, monkeypatch): - def get_session_override(): - return session - - monkeypatch.setenv("LANGFLOW_AUTO_LOGIN", False) - from langflow.main import create_app - - app = create_app() - - app.dependency_overrides[get_session] = get_session_override - with TestClient(app) as client: - yield client - app.dependency_overrides.clear() - - class Config: broker_url = "redis://localhost:6379/0" result_backend = "redis://localhost:6379/0" @@ -182,27 +170,33 @@ def json_vector_store(): return f.read() -# @contextmanager -# def session_getter(): -# try: -# session = Session(engine) -# yield session -# except Exception as e: -# print("Session rollback because of exception:", e) -# session.rollback() -# raise -# finally: -# session.close() +@pytest.fixture(name="client", autouse=True) +def client_fixture(session: Session, monkeypatch): + # Set the database url to a test database + db_dir = tempfile.mkdtemp() + db_path = Path(db_dir) / "test.db" + monkeypatch.setenv("LANGFLOW_DATABASE_URL", f"sqlite:///{db_path}") + monkeypatch.setenv("LANGFLOW_AUTO_LOGIN", False) + + def get_session_override(): + return session + + from langflow.main import create_app + + app = create_app() + + # app.dependency_overrides[get_session] = get_session_override + with TestClient(app) as client: + yield client + # app.dependency_overrides.clear() + monkeypatch.undo() + # clear the temp db + db_path.unlink() # create a fixture for session_getter above @pytest.fixture(name="session_getter") def session_getter_fixture(client): - engine = create_engine( - "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool - ) - SQLModel.metadata.create_all(engine) - @contextmanager def blank_session_getter(db_service: "DatabaseService"): with Session(db_service.engine) as session: @@ -228,17 +222,18 @@ def test_user(client): @pytest.fixture(scope="function") -def active_user(client, session): - user = User( - username="activeuser", - password=get_password_hash( - "testpassword" - ), # Assuming password needs to be hashed - is_active=True, - is_superuser=False, - ) - session.add(user) - session.commit() +def active_user(client): + db_manager = get_db_manager() + with session_getter(db_manager) as session: + user = User( + username="activeuser", + password=get_password_hash("testpassword"), + is_active=True, + is_superuser=False, + ) + session.add(user) + session.commit() + session.refresh(user) return user @@ -253,7 +248,7 @@ def logged_in_headers(client, active_user): @pytest.fixture -def flow(client, json_flow: str, session, active_user): +def flow(client, json_flow: str, active_user): from langflow.services.database.models.flow.flow import FlowCreate loaded_json = json.loads(json_flow) @@ -261,8 +256,10 @@ def flow(client, json_flow: str, session, active_user): name="test_flow", data=loaded_json.get("data"), user_id=active_user.id ) flow = Flow(**flow_data.dict()) - session.add(flow) - session.commit() + with session_getter(get_db_manager()) as session: + session.add(flow) + session.commit() + session.refresh(flow) return flow diff --git a/tests/test_cli.py b/tests/test_cli.py index dfedb9710..ee938db12 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -3,7 +3,7 @@ from tempfile import tempdir from langflow.__main__ import app import pytest -from langflow.services import utils +from langflow.services import getters @pytest.fixture(scope="module") @@ -26,7 +26,7 @@ def test_components_path(runner, client, default_settings): ["run", "--components-path", str(temp_dir), *default_settings], ) assert result.exit_code == 0, result.stdout - settings_service = utils.get_settings_service() + settings_service = getters.get_settings_service() assert str(temp_dir) in settings_service.settings.COMPONENTS_PATH diff --git a/tests/test_custom_component.py b/tests/test_custom_component.py index e75dc0e5b..1695cfd38 100644 --- a/tests/test_custom_component.py +++ b/tests/test_custom_component.py @@ -518,13 +518,13 @@ def db(app): app.db.drop_all() -def test_list_flows_return_type(component, session_getter): - flows = component.list_flows(get_session=session_getter) +def test_list_flows_return_type(component): + flows = component.list_flows() assert isinstance(flows, list) -def test_list_flows_flow_objects(component, session_getter): - flows = component.list_flows(get_session=session_getter) +def test_list_flows_flow_objects(component): + flows = component.list_flows() assert all(isinstance(flow, Flow) for flow in flows) diff --git a/tests/test_database.py b/tests/test_database.py index 058c470c5..8ec17d5b6 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -1,4 +1,6 @@ from langflow.services.database.models.base import orjson_dumps +from langflow.services.database.utils import session_getter +from langflow.services.getters import get_db_manager import orjson import pytest @@ -194,18 +196,20 @@ def test_download_file( FlowCreate(name="Flow 2", description="description", data=data), ] ) - for flow in flow_list.flows: - flow.user_id = active_user.id - db_flow = Flow.from_orm(flow) - session.add(db_flow) - session.commit() + db_manager = get_db_manager() + with session_getter(db_manager) as session: + for flow in flow_list.flows: + flow.user_id = active_user.id + db_flow = Flow.from_orm(flow) + session.add(db_flow) + session.commit() # Make request to endpoint response = client.get("api/v1/flows/download/", headers=logged_in_headers) # Check response status code - assert response.status_code == 200 + assert response.status_code == 200, response.json() # Check response data response_data = response.json()["flows"] - assert len(response_data) == 2 + assert len(response_data) == 2, response_data assert response_data[0]["name"] == "Flow 1" assert response_data[0]["description"] == "description" assert response_data[0]["data"] == data diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py index 12d2340a2..44e8a9ff9 100644 --- a/tests/test_endpoints.py +++ b/tests/test_endpoints.py @@ -2,7 +2,9 @@ import uuid from langflow.processing.process import Result from langflow.services.auth.utils import get_password_hash from langflow.services.database.models.api_key.api_key import ApiKey -from langflow.services.utils import get_settings_service +from langflow.services.getters import get_settings_service +from langflow.services.database.utils import session_getter +from langflow.services.getters import get_db_manager import pytest from fastapi.testclient import TestClient from langflow.interface.tools.constants import CUSTOM_TOOLS @@ -117,7 +119,7 @@ PROMPT_REQUEST = { @pytest.fixture -def created_api_key(session, active_user): +def created_api_key(active_user): hashed = get_password_hash("random_key") api_key = ApiKey( name="test_api_key", @@ -125,10 +127,11 @@ def created_api_key(session, active_user): api_key="random_key", hashed_api_key=hashed, ) - - session.add(api_key) - session.commit() - session.refresh(api_key) + db_manager = get_db_manager() + with session_getter(db_manager) as session: + session.add(api_key) + session.commit() + session.refresh(api_key) return api_key diff --git a/tests/test_login.py b/tests/test_login.py index 07abb35ab..651e2264b 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -1,3 +1,5 @@ +from langflow.services.database.utils import session_getter +from langflow.services.getters import get_db_manager import pytest from langflow.services.database.models.user import User from langflow.services.auth.utils import get_password_hash @@ -15,10 +17,11 @@ def test_user(): ) -def test_login_successful(client, test_user, session): +def test_login_successful(client, test_user): # Adding the test user to the database - session.add(test_user) - session.commit() + with session_getter(get_db_manager()) as session: + session.add(test_user) + session.commit() response = client.post( "api/v1/login", data={"username": "testuser", "password": "testpassword"} diff --git a/tests/test_prompts_template.py b/tests/test_prompts_template.py index 4b4daffaa..ae9c1b4f6 100644 --- a/tests/test_prompts_template.py +++ b/tests/test_prompts_template.py @@ -1,5 +1,5 @@ from fastapi.testclient import TestClient -from langflow.services.utils import get_settings_service +from langflow.services.getters import get_settings_service def test_prompts_settings(client: TestClient, logged_in_headers): diff --git a/tests/test_setup_superuser.py b/tests/test_setup_superuser.py new file mode 100644 index 000000000..f1566d9ae --- /dev/null +++ b/tests/test_setup_superuser.py @@ -0,0 +1,140 @@ +from unittest.mock import patch, Mock, MagicMock, call +from langflow.services.database.models.user.user import User +from langflow.services.settings.constants import ( + DEFAULT_SUPERUSER, + DEFAULT_SUPERUSER_PASSWORD, +) +from langflow.services.utils import setup_superuser, teardown_superuser + + +@patch("langflow.services.utils.get_settings_manager") +@patch("langflow.services.utils.create_super_user") +@patch("langflow.services.utils.get_session") +def test_setup_superuser( + mock_get_session, mock_create_super_user, mock_get_settings_manager +): + # Test when AUTO_LOGIN is True + calls = [] + mock_settings_manager = Mock() + mock_settings_manager.auth_settings.AUTO_LOGIN = True + mock_settings_manager.auth_settings.SUPERUSER = DEFAULT_SUPERUSER + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = DEFAULT_SUPERUSER_PASSWORD + mock_get_settings_manager.return_value = mock_settings_manager + mock_session = Mock() + mock_session.query.return_value.filter.return_value.first.return_value = ( + mock_session + ) + # return value of get_session is a generator + mock_get_session.return_value = iter([mock_session, mock_session, mock_session]) + setup_superuser() + mock_session.query.assert_called_once_with(User) + actual_expr = mock_session.query.return_value.filter.call_args[0][0] + expected_expr = User.username == DEFAULT_SUPERUSER + + assert str(actual_expr) == str(expected_expr) + create_call = call( + db=mock_session, username=DEFAULT_SUPERUSER, password=DEFAULT_SUPERUSER_PASSWORD + ) + calls.append(create_call) + mock_create_super_user.assert_has_calls(calls) + assert 1 == mock_create_super_user.call_count + + def reset_mock_credentials(): + mock_settings_manager.auth_settings.SUPERUSER = DEFAULT_SUPERUSER + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = ( + DEFAULT_SUPERUSER_PASSWORD + ) + + ADMIN_USER_NAME = "admin_user" + # Test when username and password are default + mock_settings_manager.auth_settings = Mock() + mock_settings_manager.auth_settings.AUTO_LOGIN = False + mock_settings_manager.auth_settings.SUPERUSER = ADMIN_USER_NAME + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = "password" + mock_settings_manager.auth_settings.reset_credentials = Mock( + side_effect=reset_mock_credentials + ) + + mock_get_settings_manager.return_value = mock_settings_manager + + setup_superuser() + mock_session.query.assert_called_with(User) + actual_expr = mock_session.query.return_value.filter.call_args[0][0] + expected_expr = User.username == ADMIN_USER_NAME + + assert str(actual_expr) == str(expected_expr) + create_call = call(db=mock_session, username=ADMIN_USER_NAME, password="password") + calls.append(create_call) + mock_create_super_user.assert_has_calls(calls) + assert 2 == mock_create_super_user.call_count + # Test that superuser credentials are reset + mock_settings_manager.auth_settings.reset_credentials.assert_called_once() + assert mock_settings_manager.auth_settings.SUPERUSER != ADMIN_USER_NAME + assert mock_settings_manager.auth_settings.SUPERUSER_PASSWORD != "password" + + # Test when superuser already exists + mock_settings_manager.auth_settings.AUTO_LOGIN = False + mock_settings_manager.auth_settings.SUPERUSER = ADMIN_USER_NAME + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = "password" + mock_user = Mock() + mock_user.is_superuser = True + mock_session.query.return_value.filter.return_value.first.return_value = mock_user + setup_superuser() + mock_session.query.assert_called_with(User) + actual_expr = mock_session.query.return_value.filter.call_args[0][0] + expected_expr = User.username == ADMIN_USER_NAME + + assert str(actual_expr) == str(expected_expr) + + +@patch("langflow.services.utils.get_settings_manager") +@patch("langflow.services.utils.get_session") +def test_teardown_superuser_default_superuser( + mock_get_session, mock_get_settings_manager +): + mock_settings_manager = MagicMock() + mock_settings_manager.auth_settings.AUTO_LOGIN = True + mock_settings_manager.auth_settings.SUPERUSER = DEFAULT_SUPERUSER + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = DEFAULT_SUPERUSER_PASSWORD + mock_get_settings_manager.return_value = mock_settings_manager + + mock_session = MagicMock() + mock_user = MagicMock() + mock_user.is_superuser = True + mock_session.query.return_value.filter.return_value.first.return_value = mock_user + mock_get_session.return_value = iter([mock_session]) + + teardown_superuser() + + mock_session.query.assert_called_once_with(User) + actual_expr = mock_session.query.return_value.filter.call_args[0][0] + expected_expr = User.username == DEFAULT_SUPERUSER + + assert str(actual_expr) == str(expected_expr) + mock_session.delete.assert_called_once_with(mock_user) + mock_session.commit.assert_called_once() + + +@patch("langflow.services.utils.get_settings_manager") +@patch("langflow.services.utils.get_session") +def test_teardown_superuser_no_default_superuser( + mock_get_session, mock_get_settings_manager +): + ADMIN_USER_NAME = "admin_user" + mock_settings_manager = MagicMock() + mock_settings_manager.auth_settings.AUTO_LOGIN = False + mock_settings_manager.auth_settings.SUPERUSER = ADMIN_USER_NAME + mock_settings_manager.auth_settings.SUPERUSER_PASSWORD = "password" + mock_get_settings_manager.return_value = mock_settings_manager + + mock_session = MagicMock() + mock_user = MagicMock() + mock_user.is_superuser = False + mock_session.query.return_value.filter.return_value.first.return_value = mock_user + mock_get_session.return_value = [mock_session] + + teardown_superuser() + + mock_session.query.assert_not_called() + mock_session.delete.assert_not_called() + mock_session.commit.assert_not_called() diff --git a/tests/test_user.py b/tests/test_user.py index f0096c695..2b7bafcb4 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -2,20 +2,22 @@ from datetime import datetime from langflow.services.auth.utils import create_super_user, get_password_hash from langflow.services.database.models.user.user import User -from langflow.services.utils import get_settings_service +from langflow.services.database.utils import session_getter +from langflow.services.getters import get_db_service, get_settings_service import pytest from langflow.services.database.models.user import UserUpdate @pytest.fixture -def super_user(client, session): - settings_service = get_settings_service() - auth_settings = settings_service.auth_settings - return create_super_user( - db=session, - username=auth_settings.FIRST_SUPERUSER, - password=auth_settings.FIRST_SUPERUSER_PASSWORD, - ) +def super_user(client): + settings_manager = get_settings_service() + auth_settings = settings_manager.auth_settings + with session_getter(get_db_service()) as session: + return create_super_user( + db=session, + username=auth_settings.SUPERUSER, + password=auth_settings.SUPERUSER_PASSWORD, + ) @pytest.fixture @@ -23,8 +25,8 @@ def super_user_headers(client, super_user): settings_service = get_settings_service() auth_settings = settings_service.auth_settings login_data = { - "username": auth_settings.FIRST_SUPERUSER, - "password": auth_settings.FIRST_SUPERUSER_PASSWORD, + "username": auth_settings.SUPERUSER, + "password": auth_settings.SUPERUSER_PASSWORD, } response = client.post("/api/v1/login", data=login_data) assert response.status_code == 200 @@ -34,29 +36,34 @@ def super_user_headers(client, super_user): @pytest.fixture -def deactivated_user(session): - user = User( - username="deactivateduser", - password=get_password_hash("testpassword"), - is_active=False, - is_superuser=False, - last_login_at=datetime.now(), - ) - session.add(user) - session.commit() +def deactivated_user(): + with session_getter(get_db_manager()) as session: + user = User( + username="deactivateduser", + password=get_password_hash("testpassword"), + is_active=False, + is_superuser=False, + last_login_at=datetime.now(), + ) + session.add(user) + session.commit() + session.refresh(user) return user -def test_user_waiting_for_approval(client, session): +def test_user_waiting_for_approval( + client, +): # Create a user that is not active and has never logged in - user = User( - username="waitingforapproval", - password=get_password_hash("testpassword"), - is_active=False, - last_login_at=None, - ) - session.add(user) - session.commit() + with session_getter(get_db_manager()) as session: + user = User( + username="waitingforapproval", + password=get_password_hash("testpassword"), + is_active=False, + last_login_at=None, + ) + session.add(user) + session.commit() login_data = {"username": "waitingforapproval", "password": "testpassword"} response = client.post("/api/v1/login", data=login_data) @@ -106,16 +113,17 @@ def test_data_consistency_after_delete(client, test_user, super_user_headers): assert all(user["id"] != user_id for user in response.json()["users"]) -def test_inactive_user(client, session): +def test_inactive_user(client): # Create a user that is not active and has a last_login_at value - user = User( - username="inactiveuser", - password=get_password_hash("testpassword"), - is_active=False, - last_login_at="2023-01-01T00:00:00", # Set to a valid datetime string - ) - session.add(user) - session.commit() + with session_getter(get_db_manager()) as session: + user = User( + username="inactiveuser", + password=get_password_hash("testpassword"), + is_active=False, + last_login_at="2023-01-01T00:00:00", # Set to a valid datetime string + ) + session.add(user) + session.commit() login_data = {"username": "inactiveuser", "password": "testpassword"} response = client.post("/api/v1/login", data=login_data) diff --git a/tests/test_vectorstore_template.py b/tests/test_vectorstore_template.py index c0dace665..9dd131dbc 100644 --- a/tests/test_vectorstore_template.py +++ b/tests/test_vectorstore_template.py @@ -1,5 +1,5 @@ from fastapi.testclient import TestClient -from langflow.services.utils import get_settings_service +from langflow.services.getters import get_settings_service # check that all agents are in settings.agents